using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Net;
using System.Concurrency;
using System.Web;

namespace Aqua877.WinApp.IronLivetube
{
	public class LivetubeMirrors
	{
		public string Host;
		public bool IsLivetubesServer;
		public int CurrentUsedBandWidth;
		public int CanUseBandWidth;
	}

	public class LivetubeInformation
	{
		public string LiveTitle { get; set; }
		public string LiveAuthor { get; set; }
		public int Listeners { get; set; }
		public int Visitors { get; set; }
		public string[] Tags { get; set; }
		public double CatchCommentsPerHour { get; set; }
		public bool IsLoading = false;

		private IDisposable Timer;
		private Uri LiveUrl;

		public event Action OnLiveEnded;
		public event Action OnInformationRefreshed;

		public void LoadAsync(Uri url)
		{
			this.LiveUrl = url;
			this.Timer = Observable.Timer(TimeSpan.FromSeconds(0), TimeSpan.FromMinutes(1))
				.ObserveOnDispatcher()
				.Subscribe(_ => this.Elapsed());
		}

		public void StopLoad()
		{
			this.IsLoading = false;
			this.Timer.Dispose();
		}

		private void Elapsed()
		{
			var liveReader = new WebClient() { Encoding = Encoding.UTF8 };
			liveReader.DownloadStringCompleted += this.GetLiveDataCompleted;
			this.IsLoading = true;
			liveReader.DownloadStringAsync(this.LiveUrl, liveReader);
		}

		private void GetLiveDataCompleted(object sender, DownloadStringCompletedEventArgs e)
		{
			if (e.Error != null)
			{
				(e.UserState as WebClient).Dispose();
				return;
			}

			if (e.Result.Contains("フラッシュ動画ファイル(FLV9)"))
			{
				this.NotifyLiveEnded();
				return;
			}
			
			//配信タイトルと配信者名取得
			Regex.Match(HttpUtility.HtmlDecode(e.Result), "<title>(.*?)</title>").Groups[1].Value
				.Let(m =>
				{
					this.LiveAuthor = m.Split(':')[2].Trim();
					this.LiveTitle = m.Split(':')[1].Trim();
					return m;
				});
				
			//タグ取得
			this.Tags = Regex.Matches(HttpUtility.UrlDecode(e.Result), @"<a href=""/tag\.(.*?)"">")
				.Cast<Match>()
				.Select(m => 
					m.Let(xs => xs.Groups[1].Value)
				)
				.ToArray();

			//リスナー数取得
			this.Listeners = int.Parse(Regex.Match(e.Result, "今見ている人の数 : <span id=\"viewing\">(.*?)</span><br />").Groups[1].Value);
			
			//見た人の数取得
			this.Visitors = int.Parse(Regex.Match(e.Result, "見た人の数 : <span id=\"view\">(.*?)</span><br />").Groups[1].Value);
			
			//1時間あたりのコメントの個数(流速)を計算
			double comments = int.Parse(Regex.Match(e.Result, "コメント : <span id=\"comments_num\">(.*?)</span><br />").Groups[1].Value);
			var start = DateTime.ParseExact(
					Regex.Match(e.Result, "<span style=\"display: block; text-align: right; font-size: smaller;\">リリース: (.*?)</span>").Groups[1].Value, "M/d yyyy, H:mm", null
				);
			this.CatchCommentsPerHour = comments / (DateTime.Now - start).TotalHours;

			//通知
			this.NotifyInformationRefreshed();

			(e.UserState as WebClient).Dispose();
			this.IsLoading = false;
		}

		
		protected virtual void NotifyLiveEnded()
		{
			if (this.OnLiveEnded != null)
			{
				this.OnLiveEnded();
			}
		}

		protected virtual void NotifyInformationRefreshed()
		{
			if (this.OnInformationRefreshed != null)
			{
				this.OnInformationRefreshed();
			}
		}
	}
}
