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

namespace skyscraper5.Mpeg2.Descriptors
{
	[SkyscraperPlugin]
	[TsDescriptor(0x02,"PMT")]
    [BannedTable("TSDT","BAT")]
    class VideoStreamDescriptor : TsDescriptor
    {
        public VideoStreamDescriptor(byte[] buffer)
        {
            if (buffer.Length != 1 && buffer.Length != 3)
            {
                return;
            }

            MemoryStream ms = new MemoryStream(buffer, false);
            byte readUInt8 = ms.ReadUInt8();
            MultipleFramerateFlag = (readUInt8 & 0x80) != 0;
            DecodeFramerateCode((readUInt8 & 0x78) >> 3);
            Mpeg1OnlyFlag = (readUInt8 & 0x04) != 0;
            ConstrainedParameterFlag = (readUInt8 & 0x02) != 0;
            StillPictureFlag = (readUInt8 & 0x01) != 0;
            if (Mpeg1OnlyFlag)
            {
                ProfileAndLevelIndication = ms.ReadUInt8();
                readUInt8 = ms.ReadUInt8();
                ChromaFormat = (readUInt8 & 0xc0) >> 6;
                FrameRateExtensionFlag = (readUInt8 & 0x20) >> 5;
            }

            this.Valid = true;
        }
        
        public int? FrameRateExtensionFlag { get; private set; }

        public int? ChromaFormat { get; private set; }

        public byte? ProfileAndLevelIndication { get; private set; }

        public bool StillPictureFlag { get; private set; }

        public bool ConstrainedParameterFlag { get; private set; }

        public bool Mpeg1OnlyFlag { get; private set; }

        private void DecodeFramerateCode(int i)
        {
            switch (i)
            {
                case 0b0001: FrameRate = 24000.0 / 1001.0; break;
                case 0b0010: FrameRate = 24; break;
                case 0b0011: FrameRate = 25; break;
                case 0b0100: FrameRate = 30000.0 / 1001.0; break;
                case 0b0101: FrameRate = 30; break;
                case 0b0110: FrameRate = 50; break;
                case 0b0111: FrameRate = 60000.0 / 1001.0; break;
                case 0b1000: FrameRate = 60; break;
            }
        }

        public double FrameRate { get; private set; }


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