using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.Net;
using System.Diagnostics;

namespace WinnyProtocolAnalyzer
{
    [Serializable]
    [XmlRoot("エンドポイント")]
    public class EndPoint
    {
        [XmlElement("IPアドレス")]
        public string IPAddress { get; set; }
        [XmlElement("ポイント")]
        public string Point { get; set; }
        [XmlElement("ドメイン")]
        public string Domain { get; set; }
        [XmlElement("ポート")]
        public int Port { get; set; }

        /// <summary>
        /// EndPoint クラスの新しいインスタンスを作成します。
        /// </summary>
        public EndPoint()
        {
            IPAddress = "";
            Point = "";
            Domain = "";
            Port = 0;
        }

        /// <summary>
        /// EndPoint クラスの新しいインスタンスを作成します。
        /// </summary>
        /// <param name="IPAddress">IPアドレス</param>
        /// <param name="Point">ポイント</param>
        /// <param name="Port">ポート</param>
        public EndPoint(IPAddress IPAddress, int Port, bool ReverseLookup)
        {
            this.IPAddress = IPAddress.ToString();
            if (!ReverseLookup)
            {
                this.Point = IPAddress.ToString();
                this.Domain = "";
            }
            else
            {
                this.Point = Domains.GetNodeEndPoint(IPAddress, true);
                this.Domain = GetDomain(this.Point);
            }
            this.Port = Port;
        }

        /// <summary>
        /// EndPoint クラスの新しいインスタンスを作成します。
        /// </summary>
        /// <param name="IPAddress">IPアドレス</param>
        /// <param name="Point">ポイント</param>
        /// <param name="Port">ポート</param>
        public EndPoint(string IPAddressString, int Port, bool ReverseLookup)
        {
            IPAddress IPAddress = null;
            try
            {
                IPAddress = IPAddress.Parse(IPAddressString);
                this.IPAddress = IPAddress.ToString();
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Exception caught (EndPoint)");
                Debug.WriteLine(string.Format("Source: {0}", ex.Source));
                Debug.WriteLine(string.Format("Message: {0}", ex.Message));
                Debug.WriteLine(string.Format("StackTrace: {0}", ex.StackTrace));
            }

            if (!ReverseLookup)
            {
                this.Point = IPAddressString;
                this.Domain = "";
            }
            else
            {
                this.Point = Domains.GetNodeEndPoint(IPAddress, true);
                this.Domain = GetDomain(this.Point);
            }
            this.Port = Port;
        }

        /// <summary>
        /// ドメイン閾値から所属ドメインを判定する。
        /// </summary>
        /// <param name="Point">エンドポイント</param>
        /// <returns>ドメイン</returns>
        private string GetDomain(string EndPoint)
        {
            if (string.IsNullOrEmpty(EndPoint.Replace(" ", "")))
            {
                return "";
            }

            IPAddress IPAddress;
            if (IPAddress.TryParse(EndPoint, out IPAddress))
            {
                return "";
            }

            try
            {
                if (Domains.CalculateLinkPointThreshold(EndPoint) == (int)TopLevelDomain.ccTLD)
                {
                    string[] aosPartition = EndPoint.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
                    return aosPartition[aosPartition.Length - 2 - 1];
                }
                else
                {
                    string[] aosPartition = EndPoint.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
                    return aosPartition[aosPartition.Length - 1 - 1];
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Exception caught (EndPoint)");
                Debug.WriteLine(string.Format("Source: {0}", ex.Source));
                Debug.WriteLine(string.Format("Message: {0}", ex.Message));
                Debug.WriteLine(string.Format("StackTrace: {0}", ex.StackTrace));
            }
            return "";
        }
    }
}
