using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using skyscraper5.Dvb.Descriptors;
using skyscraper5.Dvb.Descriptors.Extension;

namespace skyscraper5.Dvb.Psi.Model
{
    public class NitNetwork
    {
        public ushort NetworkId { get; }
        public string Name { get; set; }
        public List<LinkageDescriptor> Linkages { get; private set; }
        public uint? PrivateDataSpecifierId { get; set; }

        //from 0x6c cell list descriptor
        public ReadOnlyCollection<CellListDescriptor.Cell> Cells { get; set; }

        //from extension 0x0c xait pid descriptor
        public ushort? XaitPid { get; set; }

        //from 0x05b multilingual network name descriptor
        public ReadOnlyCollection<KeyValuePair<string, string>> MultilingualNetworkName { get; set; }

        //from extension 0x0a target region name descriptor
        public IReadOnlyList<TargetRegionNameDescriptor.TargetRegionName> RegionNames { get; set; }
        public string RegionNameCountryCode { get; set; }
        public string RegionNameLanguageCode { get; set; }

        //from extension 0x09 target region descriptor
        public IReadOnlyList<TargetRegionDescriptor.TargetRegion> Regions { get; set; }
        public string RegionCountryCode { get; set; }

        //from extension 0x08 message descriptor
        public HashSet<MessageDescriptor> Messages { get; set; }

        //from extension 0x13 uri linkage descriptor
        public ushort? MinPollingInterval { get; set; }
        public string Uri { get; set; }
        public byte? UriLinkageType { get; set; }

        //from descriptor 0x41
        public ServiceListDescriptor.Service[] ServiceList { get; set; }
		public ReadOnlyCollection<NitTransportStream> Streams { get; internal set; }

		public NitNetwork(ushort networkId)
        {
            NetworkId = networkId;
            Linkages = new List<LinkageDescriptor>();
        }

        protected bool Equals(NitNetwork other)
        {
            return NetworkId == other.NetworkId;
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != this.GetType()) return false;
            return Equals((NitNetwork)obj);
        }

        public override int GetHashCode()
        {
            return NetworkId.GetHashCode();
        }

        public bool NeedsUpdate(NitNetwork other)
        {
            if (this.Name == null && other.Name != null)
                return true;

            if (this.Name != null)
            {
                if (other.Name != null)
                {
                    this.Name = this.Name.Trim('\0');
                    other.Name = other.Name.Trim('\0');
                    if (!this.Name.Equals(other.Name))
                        return true;
                }
                else
                {
                    return false;
                }
            }

            if (this.PrivateDataSpecifierId != null && other.PrivateDataSpecifierId != null)
            {
                if (this.PrivateDataSpecifierId != other.PrivateDataSpecifierId)
                    return true;
            }

            if (this.PrivateDataSpecifierId != null && other.PrivateDataSpecifierId == null)
                return true;
            
            if (this.XaitPid != other.XaitPid)
                return true;

            if (this.RegionNameCountryCode != null)
            {
                if (!this.RegionNameCountryCode.Equals(other.RegionNameCountryCode))
                    return true;
            }

            if (this.RegionNameLanguageCode != null)
            {
                if (!this.RegionNameLanguageCode.Equals(other.RegionNameLanguageCode))
                    return true;
            }

            if (this.RegionCountryCode != null)
            {
                if (!this.RegionCountryCode.Equals(other.RegionCountryCode))
                    return true;
            }

            if (this.MinPollingInterval != other.MinPollingInterval)
                return true;

            if (this.Uri != null)
            {
                if (!this.Uri.Equals(this.Uri))
                    return true;
            }

            if (this.UriLinkageType != other.UriLinkageType)
                return true;

            return false;
        }

        public void Sanitize()
        {
	        if (Name != null)
	        {
		        Name = Name.Replace("\0", "");
	        }
        }
    }
}
