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;
using skyscraper5.Skyscraper.Scraper;

namespace skyscraper5.Dvb.Psi.Model
{
    public class SdtService
    {
        public ushort ServiceId { get; }
        public bool EitScheduleFlag { get; }
        public bool EitPresentFollowingFlag { get; }
        public RunningStatus RunningStatus { get; }
        public bool FreeCaMode { get; }

        //From 0x48 Service Descriptor
        public string ServiceName { get; set; }
        public string ServiceProviderName { get; set; }
        public ServiceDescriptor.ServiceTypeCoding? ServiceType { get; set; }

        //From 0x5f Private Data Specifier
        public uint? PrivateDataSpecifier { get; set; }

        //From 0x53 Ca Identifier Descriptor
        public ushort[] CaIdentifiers { get; set; }

        //From 0x50 Component Descriptor

        public List<ComponentDescriptor> Components { get; set; }

        //From 0x64 data braodcast descriptor
        public ushort? DataBroadcastId { get; set; }
        public byte[] Selector { get; set; }

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

        //From 0x4a linkage descriptor
        public HashSet<LinkageDescriptor> Linkages { get; set; }

        //From 0x4c time shifted service descriptor
        public ushort? ReferenceServiceId { get; set; }

        //From 0x4b nvod reference descriptor
        public NvodReferenceDescriptor.NvodReference[] NvodReferences { get; set; }

        //From 0x73 default authority descriptor
        public string DefaultAuthority { get; set; }

        //From 0x5d multilingual service name descriptor
        public ReadOnlyCollection<MultilingualServiceNameDescriptor.MultilingualServiceName> MultilingualServiceName { get; set; }

        //From 0x7e fta content management descriptor
        public int? ControlRemoteAccessOverInternet { get; set; }
        public bool? DoNotApplyRevocation { get; set; }
        public bool? DoNotScramble { get; set; }

        //From extension 0x07 service relocated descriptor
        public ushort? OldOriginalNetworkId { get; set; }
        public ushort? OldServiceId { get; set; }
        public ushort? OldTransportStreamId { get; set; }

        //From Data Broadcast Descriptor
        public byte? ComponentTag { get; set; }
        public string Iso639LanguageCode { get; set; }
        public string Text { get; set; }

        //From Message Descriptor
        public List<MessageDescriptor> Messages { get; set; }

        public SdtService(ushort serviceId, bool eitScheduleFlag, bool eitPresentFollowingFlag, RunningStatus runningStatus, bool freeCaMode)
        {
            ServiceId = serviceId;
            EitScheduleFlag = eitScheduleFlag;
            EitPresentFollowingFlag = eitPresentFollowingFlag;
            RunningStatus = runningStatus;
            FreeCaMode = freeCaMode;
        }

        protected bool Equals(SdtService other)
        {
            return ServiceId == other.ServiceId;
        }

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

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

        public bool NeedsUpdate(SdtService newer)
        {
            if (this.EitScheduleFlag != newer.EitScheduleFlag)
                return true;
            if (this.EitPresentFollowingFlag != newer.EitPresentFollowingFlag)
                return true;
            if (this.FreeCaMode != newer.FreeCaMode)
                return true;
            if (!this.ServiceType.Equals(newer.ServiceType))
                return true;

            if (!this.PrivateDataSpecifier.HasValue && newer.PrivateDataSpecifier.HasValue)
                return true;

            if (!this.ComponentTag.HasValue && newer.ComponentTag.HasValue)
                return true;
            
            if (!this.DataBroadcastId.HasValue && newer.DataBroadcastId.HasValue)
                return true;

            if (!this.ReferenceServiceId.Equals(newer.ReferenceServiceId))
                return true;
            if (!this.ControlRemoteAccessOverInternet.Equals(newer.ControlRemoteAccessOverInternet))
                return true;
            if (!this.DoNotApplyRevocation.Equals(newer.DoNotApplyRevocation))
                return true;
            if (!this.DoNotScramble.Equals(newer.DoNotScramble))
                return true;
            return false;
        }

        public string GetCaSystemName()
        {
	        if (CaIdentifiers == null)
		        return "";
	        if (CaIdentifiers.Length == 0)
		        return "";

	        return CaSystemNames.GetHumanReadableName(CaIdentifiers[0]);
        }
    }
}
