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;

namespace skyscraper5.Dvb.TvAnytime
{
    internal class RctParser : IPsiProcessor
    {
        public IRctEventHandler EventHandler { get; }
        public ushort ResultProgramNumber { get; }

        public RctParser(IRctEventHandler eventHandler, ushort resultProgramNumber)
        {
            EventHandler = eventHandler;
            ResultProgramNumber = resultProgramNumber;
        }

        public void GatherPsi(PsiSection section, int sourcePid)
        {
            //found in ETSI TS 102 323 V1.5.1 (2012-01)
            MemoryStream ms = new MemoryStream(section.GetDataCopy(), false);

            if (ms.ReadUInt8() != 0x76)
                return;

            ushort readUInt16Be = ms.ReadUInt16BE();
            bool sectionSyntaxIndicator = (readUInt16Be & 0x8000) != 0;
            if (!sectionSyntaxIndicator)
                return;

            bool tableIdExtensionFlag = (readUInt16Be & 0x4000) != 0;
            int sectionLength = readUInt16Be & 0x0fff;
            ms = new MemoryStream(ms.ReadBytes(sectionLength), false);

            Rct result = new Rct();
            result.ServiceId = ms.ReadUInt16BE();
            if (tableIdExtensionFlag)
                result.ServiceId = 0;

            byte readUInt8 = ms.ReadUInt8();
            int versionNumber = (readUInt8 & 0x7e) >> 1;
            bool currentNextIndicator = (readUInt8 & 0x01) != 0;

            byte sectionNumber = ms.ReadUInt8();
            byte lastSectionNumber = ms.ReadUInt8();
            result.YearOffset = ms.ReadUInt16BE();

            byte linkCount = ms.ReadUInt8();
            result.LinkInfo = new RctLinkInfo[linkCount];
            for (int j = 0; j < linkCount; j++)
            {
                readUInt16Be = ms.ReadUInt16BE();
                int linkInfoLength = readUInt16Be & 0x0fff;
                byte[] linkInfoBytes = ms.ReadBytes(linkInfoLength);
                result.LinkInfo[j] = new RctLinkInfo(linkInfoBytes);
            }

            readUInt16Be = ms.ReadUInt16BE();
            int descriptorLoopLength = readUInt16Be & 0x0fff;
            if (descriptorLoopLength > 0)
            {
                byte[] descriptorLoop = ms.ReadBytes(descriptorLoopLength);
                throw new NotImplementedException();
            }

            uint crc32 = ms.ReadUInt32BE();
            EventHandler.OnRelatedContent(result, ResultProgramNumber);
        }
    }
}
