using System;
using System.Collections.Generic;
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(0x51,"SDT","PMT","SIT")]
    [BannedTable("TSDT")]
    class MosaicDescriptor : TsDescriptor
    {
        public MosaicDescriptor(byte[] buffer)
        {
            MemoryStream ms = new MemoryStream(buffer, false);
            byte readUInt8 = ms.ReadUInt8();
            MosaicEntryPoint = (readUInt8 & 0x80) != 0;
            NumberOfHorizontalElementaryCells = (readUInt8 & 0x70) >> 4;
            NumberOfHorizontalElementaryCells++;
            NumberOfVerticalElementaryCells = (readUInt8 & 0x07);
            NumberOfVerticalElementaryCells++;

            int totalCells = NumberOfHorizontalElementaryCells * NumberOfVerticalElementaryCells;
            Cells = new MosaicCell[totalCells];
            for (int i = 0; i < totalCells; i++)
            {
                MosaicCell child = new MosaicCell();
                Cells[i] = child;

                if (ms.GetAvailableBytes() < 2)
                    return;

                ushort readUInt16Be = ms.ReadUInt16BE();
                child.LogicalCellId = (readUInt16Be & 0xfc00) >> 10;
                if (child.LogicalCellId > 64)
                    return;
                child.LogicalCellPresentationInfo = (readUInt16Be & 0x0007);
                byte elementaryCellFieldLength = ms.ReadUInt8();

                child.ElementaryCellIds = ms.ReadBytes(elementaryCellFieldLength);
                for (int j = 0; j < child.ElementaryCellIds.Length; j++)
                {
                    child.ElementaryCellIds[j] &= 0x3f;
                }

                child.CellLinkageInfo = ms.ReadUInt8();
                if (child.CellLinkageInfo == 0x01)
                {
                    child.BouquetId = ms.ReadUInt16BE();
                }
                else if (child.CellLinkageInfo == 0x02)
                {
                    child.OriginalNetworkId = ms.ReadUInt16BE();
                    child.TransportStreamId = ms.ReadUInt16BE();
                    child.ServiceId = ms.ReadUInt16BE();
                }
                else if (child.CellLinkageInfo == 0x03)
                {
                    child.OriginalNetworkId = ms.ReadUInt16BE();
                    child.TransportStreamId = ms.ReadUInt16BE();
                    child.ServiceId = ms.ReadUInt16BE();
                }
                else if (child.CellLinkageInfo == 0x04)
                {
                    child.OriginalNetworkId = ms.ReadUInt16BE();
                    child.TransportStreamId = ms.ReadUInt16BE();
                    child.ServiceId = ms.ReadUInt16BE();
                    child.EventId = ms.ReadUInt16BE();
                }
            }

            this.Valid = true;
        }

        public MosaicCell[] Cells { get; private set; }
        public class MosaicCell
        {
            public int LogicalCellId { get; set; }
            public int LogicalCellPresentationInfo { get; set; }
            public byte[] ElementaryCellIds { get; set; }
            public byte CellLinkageInfo { get; set; }
            public ushort? BouquetId { get; set; }
            public ushort? OriginalNetworkId { get; set; }
            public ushort? TransportStreamId { get; set; }
            public ushort? ServiceId { get; set; }
            public ushort? EventId { get; set; }
        }

        public int NumberOfVerticalElementaryCells { get; private set; }

        public int NumberOfHorizontalElementaryCells { get; private set; }

        public bool MosaicEntryPoint { get; private set; }
    }
}
