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

namespace skyscraper5.Scte35
{
    public class SpliceInsert
    {
        public SpliceInsert(byte[] buffer)
        {
            MemoryStream ms = new MemoryStream(buffer, false);
            SpliceEventId = ms.ReadUInt32BE();
            SpliceEventCancelIndicator = (ms.ReadUInt8() & 0x80) != 0;
            if (!SpliceEventCancelIndicator)
            {
                byte readUInt8 = ms.ReadUInt8();
                OutOfNetworkIndicator = (readUInt8 & 0x80) != 0;
                ProgramSpliceFlag = (readUInt8 & 0x40) != 0;
                DurationFlag = (readUInt8 & 0x20) != 0;
                SpliceImmediateFlag = (readUInt8 & 0x10) != 0;
                if (ProgramSpliceFlag.Value && !SpliceImmediateFlag.Value)
                    SpliceTime = ms.ReadSpliceTime();
                if (!ProgramSpliceFlag.Value)
                {
                    byte componentCount = ms.ReadUInt8();
                    Components = new Tuple<byte, ulong?>[componentCount];
                    for (int i = 0; i < componentCount; i++)
                    {
                        byte componentTag = ms.ReadUInt8();
                        ulong? spliceTime = null;
                        if (!SpliceImmediateFlag.Value)
                            spliceTime = ms.ReadSpliceTime();
                        Components[i] = new Tuple<byte, ulong?>(componentTag, spliceTime);
                    }
                }

                if (DurationFlag.Value)
                {
                    readUInt8 = ms.ReadUInt8();
                    DurationAutoReturn = (readUInt8 & 0x80) != 0;
                    Duration = (ulong)(readUInt8 & 0x01);
                    Duration <<= 32;
                    Duration += ms.ReadUInt32BE();
                }

                UniqueProgramId = ms.ReadUInt16BE();
                AvailNum = ms.ReadUInt8();
                AvailsExpected = ms.ReadUInt8();
            }
        }

        public byte? AvailsExpected { get; private set; }

        public byte? AvailNum { get; private set; }

        public ushort? UniqueProgramId { get; private set; }

        public ulong? Duration { get; private set; }

        public bool? DurationAutoReturn { get; set; }

        public Tuple<byte,ulong?>[] Components { get; private set; }

        public bool? SpliceImmediateFlag { get; private set; }

        public bool? DurationFlag { get; private set; }

        public bool? ProgramSpliceFlag { get; private set; }

        public bool? OutOfNetworkIndicator { get; private set; }

        public bool SpliceEventCancelIndicator { get; private set; }

        public uint SpliceEventId { get; private set; }
        public ulong? SpliceTime { get; }
        public Scte35DescriptorCollection Descriptors { get; set; }
    }
}
