using System.Collections.Generic;
using System.IO;
using System;
using System.Linq;
using System.Diagnostics;
using System.Text.RegularExpressions;

namespace Aqua877.WinApp.IronLivetube
{
	public enum MatchTarget
	{
		ToText,
		ExceptText,
		All
	}

	public class Replacement
	{
		public string Before { get; set; }
		public string After { get; set; }
		public bool AddedByUser { get; set; }
		public MatchTarget ReplacementTarget { get; set; }
		public bool IsApplyToListView { get; set; }
		public bool IsUseRegex { get; set; }
	}

	public class TextReaderServices
	{
		public bool IsEnable = false;
		private bool FirstPush = true;
		private Queue<string> TextQueue = new Queue<string>();
		private IDisposable ReadTimer = null;
		private object SyncObj = new object();

		public void Read(IEnumerable<LivetubeCommentData> text)
		{
			if (this.FirstPush && !GlobalValues.Setting.IsReadCommentAtFirst)
			{
				//このあたりをObservable.Throttle使って書きなおしたほうが重くならずに済むかも
				this.FirstPush = false;
				return;
			}
			text.OrderBy(d => d.Number)
				.ForEach(s => this.Read(s));
		}

		public void Read(LivetubeCommentData comment)
		{
			if (!GlobalValues.Setting.IsEnableReading)
			{
				return;
			}

			lock (this.SyncObj)
			{

				//softalkに読ませるためのテキスト作成
				string readText = GlobalValues.Setting.ReadingTemplate;

				readText = readText
					.Replace("{ResID}", comment.Number.ToString())
					.Replace("{NanashiID}", comment.ID)
					.Replace("{PostText}", comment.Text);

				if (comment.Name != "")
				{
					readText = Regex.Replace(readText, "{Writer\\[(.*?)\\]}", comment.Name + "$1");
				}
				else
				{
					readText = Regex.Replace(readText, "{Writer\\[(.*?)\\]}", "");
				}

				if (Regex.IsMatch(readText, "{PostDate\\[(.*?)\\]}"))
				{
					string format = Regex.Replace(readText, "{PostDate\\[(.*?)\\]}", "$1");
					readText = Regex.Replace(readText, "{PostDate\\[(.*?)\\]}", comment.PostedDate.ToString(format));
				}
				this.TextQueue.Enqueue(readText);
			}
		}

		public void Start()
		{
			this.FirstPush = true;
			this.IsEnable = true;
			this.ReadTimer = Observable.Timer(TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(3))
				.Subscribe(_ => this.Elapsed());
		}

		public void Stop()
		{
			this.IsEnable = false;
			this.ReadTimer.Dispose();
			this.TextQueue.Clear();
		}

		public void Restart()
		{
			this.IsEnable = true;
			this.ReadTimer = Observable.Timer(TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(3))
				.Subscribe(_ => this.Elapsed());
		}

		public void Suspend()
		{
			this.IsEnable = false;
			this.ReadTimer.Dispose();
		}

		private void Elapsed()
		{
			if(!IsEnable)
			{
				return;
			}

			lock (this.SyncObj)
			{
				if (this.TextQueue.Count == 0)
				{
					return;
				}

				//読み込み待機数の数によって速度を設定
				var readSpeed = 50 + (int)(100 * this.TextQueue.Count * 0.5);

				if (readSpeed > 300)
				{
					readSpeed += 300 - readSpeed;
				}

				string readText = String.Format("/T:0 /S:{0} /W:{1}", readSpeed, this.TextQueue.Dequeue());

				try
				{
					Process.Start(GlobalValues.Setting.SoftalkPath, readText);
				}
				catch
				{
					#warning TODO : エラーロギング
					this.Stop();
				}
			}
		}
	}
}
