using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using skyscraper5.Skyscraper.IO;
using skyscraper5.Skyscraper.Plugins;

namespace skyscraper5.Dvb.Descriptors.Extension
{
    [SkyscraperPlugin]
    [ExtensionDescriptor(0x04,"NIT")]
    public class T2DeliverySystemDescriptor : Dvb.ExtensionDescriptor
    {
        public T2DeliverySystemDescriptor(byte[] buffer)
        {
            MemoryStream ms = new MemoryStream(buffer, false);
            PlpId = ms.ReadUInt8();
            T2SystemId = ms.ReadUInt16BE();

            if (buffer.Length > 4)
            {
                byte readUInt8 = ms.ReadUInt8();
                SisoMiso = (readUInt8 & 0xc0) >> 6;
                Bandwidth = (readUInt8 & 0x3c) >> 2;

                readUInt8 = ms.ReadUInt8();
                GuardInterval = (readUInt8 & 0xe0) >> 5;
                TransmissionMode = (readUInt8 & 0x1c) >> 2;
                OtherFrequencyFlag = (readUInt8 & 0x02) != 0;
                TfsFlag = (readUInt8 & 0x01) != 0;

                List<CellInfo> cellInfos = new List<CellInfo>();
                while (ms.GetAvailableBytes() > 2)
                {
                    CellInfo child = new CellInfo();
                    child.CellId = ms.ReadUInt16BE();
                    if (TfsFlag.Value)
                    {
                        byte frequencyLoopLength = ms.ReadUInt8();
                        frequencyLoopLength /= 4;
                        child.CentreFrequencies = new uint[frequencyLoopLength];
                        for (int i = 0; i < frequencyLoopLength; i++)
                            child.CentreFrequencies[i] = ms.ReadUInt32BE();
                    }
                    else
                    {
                        child.CentreFrequencies = new uint[1];
                        child.CentreFrequencies[0] = ms.ReadUInt32BE();
                    }

                    byte subcellInfoLength = ms.ReadUInt8();
                    subcellInfoLength /= 5;
                    child.SubcellInfos = new SubcellInfo[subcellInfoLength];
                    for (int i = 0; i < subcellInfoLength; i++)
                    {
                        child.SubcellInfos[i] = new SubcellInfo();
                        child.SubcellInfos[i].CellIdExtension = ms.ReadUInt8();
                        child.SubcellInfos[i].TransposerFrequency = ms.ReadUInt32BE();
                    }

                    cellInfos.Add(child);
                }

                CellInfos = cellInfos.AsReadOnly();
            }
        }

        public ReadOnlyCollection<CellInfo> CellInfos { get; private set; }

        public class SubcellInfo
        {
            public byte CellIdExtension { get; set; }
            public uint TransposerFrequency { get; set; }
        }

        public class CellInfo
        {
            public ushort CellId { get; set; }
            public uint[] CentreFrequencies { get; set; }
            public SubcellInfo[] SubcellInfos { get; set; }
        }

        public bool? TfsFlag { get; private set; }

        public bool? OtherFrequencyFlag { get; private set; }

        public int? TransmissionMode { get; private set; }

        public int? GuardInterval { get; private set; }

        public int? Bandwidth { get; private set; }

        public int? SisoMiso { get; private set; }

        public ushort T2SystemId { get; private set; }

        public byte PlpId { get; private set; }
    }
}
