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.Mpeg2;
using skyscraper5.Skyscraper.IO;
using skyscraper5.Skyscraper.Plugins;

namespace skyscraper5.Dvb.Descriptors
{
	[SkyscraperPlugin]
	[TsDescriptor(0x6c,"NIT")]
    [BannedTable("PMT","TSDT")]
    public class CellListDescriptor : TsDescriptor
    {
        public CellListDescriptor(byte[] buffer)
        {
            List<Cell> resultCells = new List<Cell>();
            MemoryStream ms = new MemoryStream(buffer, false);
            while (ms.GetAvailableBytes() >= 10)
            {
                Cell child = new Cell();
                child.CellId = ms.ReadUInt16BE();           
                child.CellLatitude = ms.ReadUInt16BE();     
                child.CellLongitude = ms.ReadUInt16BE();    
                
                uint readUInt32Be = ms.ReadUInt32BE();      
                child.ExtentOfLatitude = (readUInt32Be & 0xfff00000) >> 20;
                child.ExtentOfLongitude = (readUInt32Be & 0x000fff00) >> 8;
                
                uint subcellInfoLoopLength = (readUInt32Be & 0x000000ff);
                subcellInfoLoopLength /= 8;
                child.Subcells = new Subcell[subcellInfoLoopLength];
                for (int i = 0; i < subcellInfoLoopLength; i++)
                {
                    Subcell subchild = new Subcell();
                    child.Subcells[i] = subchild;

                    subchild.CellIdExtension = ms.ReadUInt8();
                    subchild.SubcellLatitude = ms.ReadUInt16BE();
                    subchild.SubcellLongitude = ms.ReadUInt16BE();

                    byte readUInt8 = ms.ReadUInt8();
                    subchild.SubcellExtentOfLatitude = readUInt8;
                    subchild.SubcellExtentOfLatitude <<= 4;

                    readUInt8 = ms.ReadUInt8();
                    subchild.SubcellExtentOfLatitude += ((readUInt8 & 0xf0) >> 4);
                    subchild.SubcellExtentOfLongitude = (readUInt8 & 0x0f);
                    subchild.SubcellExtentOfLongitude <<= 4;

                    readUInt8 = ms.ReadUInt8();
                    subchild.SubcellExtentOfLongitude += readUInt8;
                }

                resultCells.Add(child);
            }

            Cells = resultCells.AsReadOnly();
        }

        public ReadOnlyCollection<Cell> Cells { get; private set; }

        public class Cell
        {
            public ushort CellId { get; set; }
            public ushort CellLatitude { get; set; }
            public ushort CellLongitude { get; set; }
            public uint ExtentOfLatitude { get; set; }
            public uint ExtentOfLongitude { get; set; }

            public Subcell[] Subcells { get; set; }
        }

        public class Subcell
        {
            public byte CellIdExtension { get; set; }
            public ushort SubcellLatitude { get; set; }
            public ushort SubcellLongitude { get; set; }
            public int SubcellExtentOfLatitude { get; set; }
            public int SubcellExtentOfLongitude { get; set; }
        }
    }
}
