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 skyscraper8.Dvb.Descriptors.Extension;

namespace skyscraper5.Dvb.Psi.Model
{
    public class EitEvent
    {
        protected bool Equals(EitEvent other)
        {
            return ServiceId == other.ServiceId && TransportStreamId == other.TransportStreamId && OriginalNetworkId == other.OriginalNetworkId && EventId == other.EventId && StartTime.Equals(other.StartTime);
        }

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

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

        public ushort ServiceId { get; }
        public ushort TransportStreamId { get; }
        public ushort OriginalNetworkId { get; }
        public ushort EventId { get; internal set; }
        public DateTime StartTime { get; internal set; }
        public TimeSpan Duration { get; internal set; }
        public RunningStatus RunningStatus { get; internal set; }
        public bool FreeCa { get; internal set; }

        //Short Event Descriptor
        public string Iso639LanguageCode { get; set; }
        public string EventName { get; set; }
        public string Text { get; set; }

        //Extended Event Descriptor
        public List<EitEventItem> Items { get; private set; }
        public string[] ExtendedText { get; internal set; }

        //PDC Descriptor
        public DateTime? Pdc { get; set; }

        //Component Descriptor
        public HashSet<ComponentDescriptor> Components { get; set; }

        //Content Descriptor
        public Tuple<int, int, byte>[] Content { get; set; }

        //Private Data Specifier Descriptor
        public uint? PrivateDataSpecifier { get; set; }
        
        //ARD's VPS Descriptor
        public string VpsString { get; set; }
        
        //Parental Rating Descriptor
        public Tuple<string, int>[] ParentalRatings { get; set; }

        //Linkage Descriptor
        public List<LinkageDescriptor> Linkages { get; private set; }

        //Ca Identifier Descriptor
        public ushort[] CaSystems { get; set; }

        //Time Shifted Event Descriptor
        public ushort? ReferenceServiceId { get; set; }
        public ushort? ReferenceEventId { get; set; }

        //Content Identifier Descriptor
        public ReadOnlyCollection<ContentIdentifierDescriptor.Crid> Crids { get; set; }

        //FTA content management descriptor
        public int? ControlRemoteAccessOverInternet { get; set; }
        public bool? DoNotApplyRevocation { get; set; }
        public bool? DoNotScramble { get; set; }

        //Image Icon Descriptor
        public _0x00_ImageIconDescriptor[] IconComponents { get; set; }
        public string IconUrl { get; set; }
        public byte[] IconData { get; set; }
        public string IconType { get; set; }
        public int? IconVerticalOrigin { get; set; }
        public int? IconHorizontalOrigin { get; set; }
        public int? IconCoordinateSystem { get; set; }
        public int? IconTransportMode { get; set; }


		public EitEvent(ushort serviceId, ushort transportStreamId, ushort originalNetworkId)
        {
            ServiceId = serviceId;
            TransportStreamId = transportStreamId;
            OriginalNetworkId = originalNetworkId;
            Linkages = new List<LinkageDescriptor>();
        }

        public void AddItem(KeyValuePair<string, string> keyValuePair)
        {
            if (Items == null)
                Items = new List<EitEventItem>();
            EitEventItem newItem = new EitEventItem(keyValuePair.Key, keyValuePair.Value, Items.Count);
            if (Items == null)
                Items = new List<EitEventItem>();
            if (!Items.Contains(newItem))
                Items.Add(newItem);
        }

        public class EitEventItem
        {
            public string Description { get; }
            public string Item { get; }
            public int Ordinal { get; }

            public EitEventItem(string description, string item, int ordinal)
            {
                Description = description;
                Item = item;
                Ordinal = ordinal;
            }

            protected bool Equals(EitEventItem other)
            {
                return Description == other.Description && Item == other.Item;
            }

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

            public override int GetHashCode()
            {
                return HashCode.Combine(Description, Item);
            }
        }
    }
}
