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

namespace skyscraper5.Dvb.Psi.Model
{
    public class BatTransportStream
    {
        public ushort TransportStreamId { get; }
        public ushort OriginalNetworkId { get; }
        public List<ServiceListDescriptor.Service> ServiceList { get; set; }

        //from 0x5f private data specifier descriptor
        public uint? PrivateDataSpecifier { get; set; }

        //from private descriptor 0x83 nordig private logical channel descriptor,
        //might also appear elsewhere
        public List<BaseLcn> LCNs { get; set; }

        //from country availability descriptor
        public Dictionary<string,bool> CountryAvailability { get; set; }

        //from default authority descriptor
        public string DefaultAuthority { get; set; }

        public BatTransportStream(ushort transportStreamId, ushort originalNetworkId)
        {
            TransportStreamId = transportStreamId;
            OriginalNetworkId = originalNetworkId;
            CountryAvailability = new Dictionary<string, bool>();
        }

        public bool NeedsUpdate(BatTransportStream child)
        {
            if (ServiceList != null && child.ServiceList != null)
            {
                foreach (ServiceListDescriptor.Service service in ServiceList)
                {
                    if (!child.ServiceList.Contains(service))
                        return true;
                }

                foreach (ServiceListDescriptor.Service service in child.ServiceList)
                {
                    if (!ServiceList.Contains(service))
                        return true;
                }
            }

            if (ServiceList == null && child.ServiceList != null)
                return true;

            if (!this.PrivateDataSpecifier.HasValue && child.PrivateDataSpecifier.HasValue)
                return true;
            
            foreach (KeyValuePair<string, bool> keyValuePair in CountryAvailability)
            {
                if (!child.CountryAvailability.ContainsKey(keyValuePair.Key))
                    return true;
                if (child.CountryAvailability[keyValuePair.Key] != keyValuePair.Value)
                    return true;
            }

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

            return false;
        }

        protected bool Equals(BatTransportStream other)
        {
            return TransportStreamId == other.TransportStreamId && OriginalNetworkId == other.OriginalNetworkId;
        }

        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((BatTransportStream)obj);
        }

        public override int GetHashCode()
        {
            return HashCode.Combine(TransportStreamId, OriginalNetworkId);
        }
    }
}
