// X2chServerTracer.cs

namespace Twin.Tools
{
	using System;
	using System.IO;
	using System.Text;
	using System.Text.RegularExpressions;
	using System.Net;
	using Twin.Text;

	/// <summary>
	/// 2chÌT[o[Ú]ÇÕ
	/// </summary>
	public class X2chServerTracer
	{
		private BoardInfoCollection traceList;
		private BoardInfo result;

		/// <summary>
		/// ÂÌÇÕððæ¾
		/// </summary>
		public BoardInfoCollection TraceList {
			get { return traceList; }
		}

		/// <summary>
		/// Ú]æðæ¾
		/// </summary>
		public BoardInfo Result {
			get { return result; }
		}

		/// <summary>
		/// ÂÌÇÕÉ¬÷µ½Æ«É­¶·éCxg
		/// </summary>
		public event EventHandler<ServerChangeEventArgs> Tracing;

		/// <summary>
		/// X2chServerTracerNXÌCX^Xðú»
		/// </summary>
		public X2chServerTracer()
		{
			// 
			// TODO: RXgN^ WbNð±±ÉÇÁµÄ­¾³¢B
			//
			traceList = new BoardInfoCollection();
			result = null;
		}

		/// <summary>
		/// wèµ½ÂÌÚ]ðÇÕ
		/// </summary>
		/// <param name="board">ÇÕ·éÂ</param>
		/// <param name="recursive">Ú]æª³çÉÚ]µÄ¢½êAÄNÇÕ·é©Ç¤©</param>
		/// <returns>ÇÕÅ«êÎtrueA¸s·êÎfalseðÔ·</returns>
		public bool Trace(BoardInfo board, bool recursive)
		{
			if (board == null) {
				throw new ArgumentNullException("board");
			}

			traceList.Clear();
			result = null;
Check:
			// Htmlf[^ðæ¾
			HttpWebRequest req = (HttpWebRequest)WebRequest.Create(board.Url);
			req.UserAgent = TwinDll.UserAgent;
			req.AddRange(0, 499);

			HttpWebResponse res = (HttpWebResponse)req.GetResponse();
			string html;
			
			using (StreamReader sr = new StreamReader(res.GetResponseStream(), Encoding.GetEncoding("Shift_Jis")))
				html = sr.ReadToEnd();

			res.Close();
			
			// T[o[Ú]
			if (html.IndexOf("2chbbs..") >= 0)
			{
				TwinDll.Output("{0} ªÚ]µÄ¢Ü·B", board.Url);

				// Ú]æÌURLðæ¾
				Match m = Regex.Match(html, "<a href=\"(?<url>.+?)\">GO !</a>", RegexOptions.IgnoreCase);
				if (m.Success)
				{
					string newUrl = m.Groups["url"].Value;

					TwinDll.Output("Ú]æ {0} ð­©µÜµ½B", newUrl);

					result = URLParser.ParseBoard(m.Groups["url"].Value);
					if (result != null)
					{
						result.Name = board.Name;
						traceList.Add(result);

						OnTracing(new ServerChangeEventArgs(board, result));

						if (recursive)
						{
							board = result;
							html = null;

							goto Check;
						}
					}
				}
			}
			// ÇÕI¹µ½êÍÂ¼ðæ¾
			else if (result != null)
			{
				if (String.IsNullOrEmpty(result.Name))
				{
					Match m = Regex.Match(html, "<title>(?<t>.+?)</title>", RegexOptions.IgnoreCase);
					if (m.Success)
					{
						result.Name = m.Groups["t"].Value;
					}
				}
				TwinDll.Output("{0} ÌÇÕÉ¬÷µÜµ½B", result.Name);
			}

			return (result != null) ? true : false;
		}

		/// <summary>
		/// TracingCxgð­¶³¹é
		/// </summary>
		/// <param name="e"></param>
		protected void OnTracing(ServerChangeEventArgs e)
		{
			if (Tracing != null)
				Tracing(this, e);
		}
	}
}
