using log4net;
using skyscraper5.Skyscraper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using skyscraper8.Ssdp.Schema;

namespace skyscraper8.SimpleServiceDiscoveryProtocol
{
	public class SsdpDevice : Validatable
	{
		private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);

		public SsdpDevice(string notification)
		{
			StringReader sr = new StringReader(notification);
			string httpHeaderLine = sr.ReadLine();
			int indexOf = httpHeaderLine.IndexOf(' ');
			string protocol = httpHeaderLine.Substring(0, indexOf);
			httpHeaderLine = httpHeaderLine.Substring(indexOf + 1);
			if (!protocol.StartsWith("HTTP"))
			{
				Valid = false;
				return;
			}

			HttpStatusCode = int.Parse(httpHeaderLine.Substring(0, 3));
			httpHeaderLine = httpHeaderLine.Substring(4);

			string line = httpHeaderLine;
			while (!string.IsNullOrEmpty(line = sr.ReadLine()))
			{
				int seperator = line.IndexOf(": ");
				if (seperator == -1)
					continue;
				string key = line.Substring(0, seperator);
				string value = line.Substring(seperator + 2);
				key = key.ToLowerInvariant();
				switch (key)
				{
					case "cache-control":
						this.CacheControl = value;
						break;
					case "st":
						this.SearchTarget = value;
						break;
					case "usn":
						this.UniqueServiceName = value;
						break;
					case "server":
						Server = value;
						break;
					case "location":
						Location = value;
						break;
					case "opt":
						Options = value;
						break;
					case "01-nls":
						//Same as BOOT ID
						break;
					case "bootid.upnp.org":
						BootId = value;
						break;
					case "configid.upnp.org":
						ConfigId = value;
						break;
					case "deviceid.ses.com":
						SatIpDeviceId = value;
						break;
					case "date":
						Date = value;
						break;
					case "x-user-agent":
						UserAgent = value;
						break;
					case "content-length":
						//Irrelevant. Always 0, because these thingies dont contain any http payload.
						break;
					default:
						logger.WarnFormat("Don't know how to format: {0}", line);
						break;
				}
			}

			logger.DebugFormat("Found UPnP Device: {0}", Server);
			Valid = true;
		}

		public string UserAgent { get; set; }

		public string Date { get; set; }

		public string SatIpDeviceId { get; set; }

		public string ConfigId { get; set; }

		public string BootId { get; set; }


		public string Options { get; set; }

		/// <summary>
		/// This is an URL to an XML file
		/// </summary>
		public string Location { get; set; }

		/// <summary>
		/// This just says what software is running on the device, not what it actually is.
		/// </summary>
		public string Server { get; set; }

		/// <summary>
		/// This can only be used to identify one specific device, not a device type.
		/// </summary>
		public string UniqueServiceName { get; set; }

		public string SearchTarget { get; set; }

		public string CacheControl { get; private set; }

		public int HttpStatusCode { get; private set; }
		public root DeviceMetadata { get; set; }

		public IPAddress GetIpAddress()
		{
			Uri uri = new Uri(Location);
			string uriHost = uri.Host;
			return IPAddress.Parse(uriHost);
		}
	}
}
