using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using System.Xml;

namespace MusicMetaTagger.Client.AllMusicGuide.RemoteDataAccess.Parser
{
	public abstract class ParserBase<TEntity> : IParser<TEntity>
	{
		public abstract TEntity Parse(XmlDocument xml);

		protected static string RegexCapture(string str, string regexStr)
		{
			var regex = new Regex(regexStr);
			var match = regex.Match(str);
			if (match.Captures.Count == 0)
				throw new ApplicationException("Couldn't make regex match for "
				                               + regexStr + " in " + str);
			return match.Captures[0].Value;
		}

		protected static bool RegexMatch(string str, string regexStr)
		{
			var regex = new Regex(regexStr);
			var match = regex.Match(str);
			return match.Captures.Count > 0;
		}

		protected static bool XpathMatch(XmlDocument xml, string xPath)
		{
			var nodes = xml.SelectNodes(xPath);
			return nodes != null && nodes.Count > 0;
		}

		protected static string XpathMatchString(XmlDocument xml, string xPath)
		{
			var titleNodes = xml.SelectNodes(xPath);
			if (titleNodes == null || titleNodes.Count == 0)
			{
				//xml.Save(@"problem_" + DateTime.Now.Ticks + ".xml");
				throw new ApplicationException(string.Format("Couldn't find matching nodes for : \"{0}\" in {1}", xPath,
				                                             xml.InnerXml));
			}
			var decodedValue = WebUtility.HtmlDecode(titleNodes[0].InnerText);
			return decodedValue.Trim();
		}

		protected static List<string> XpathMatchStringList(XmlDocument xml, string xPath)
		{
			var titleNodes = xml.SelectNodes(xPath);
			if (titleNodes == null || titleNodes.Count == 0)
				throw new ApplicationException("Couldn't find matching nodes for : " + xPath);

			return (
			       	from XmlNode node in titleNodes
					select WebUtility.HtmlDecode(node.InnerText)
			       	into decodedValue
			       	select decodedValue.Trim()
			       ).ToList();
		}

		protected static IEnumerable<XmlDocument> XpathMatchXmlList(XmlDocument xml, string xPath)
		{
			var titleNodes = xml.SelectNodes(xPath);
			if (titleNodes == null || titleNodes.Count == 0)
			{
				xml.Save("problem.xml");
				throw new ApplicationException("Couldn't find matching nodes for : " + xPath);
			}

			var xmlList = new List<XmlDocument>();
			foreach (XmlNode node in titleNodes)
			{
				var xmlDocument = new XmlDocument();
				xmlDocument.LoadXml(xml.FirstChild.InnerXml + "<root></root>");

				var importNode = xmlDocument.ImportNode(node, true);
				if (xmlDocument.DocumentElement == null)
					throw new ApplicationException("xmlDocument.DocumentElement Null");
				xmlDocument.DocumentElement.AppendChild(importNode);

				xmlList.Add(xmlDocument);
			}
			return xmlList;
		}
	}
}