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

namespace skyscraper5.Dvb.Descriptors
{
	[SkyscraperPlugin]
	[TsDescriptor(0x43,"NIT")]
    [BannedTable("BAT","TSDT")]
    public class SatelliteDeliverySystemDescriptor : TsDescriptor
    {
        public SatelliteDeliverySystemDescriptor(byte[] buffer)
        {
            MemoryStream ms = new MemoryStream(buffer);
            Frequency = ms.ReadUInt32BE().UnpackBcd();
            OrbitalPosition = (float)ms.ReadUInt16BE().UnpackBcd() / 10.0f;

            byte readUInt8 = ms.ReadUInt8();
            East = (readUInt8 & 0x80) != 0;
            Polarization = (PolarizationEnum)((readUInt8 & 0x60) >> 5);
            int temp1 = ((readUInt8 & 0x18) >> 3);
            S2 = (readUInt8 & 0x04) != 0;
            ModulationType = (readUInt8 & 0x03);

            uint readUInt32Be = ms.ReadUInt32BE();
            SymbolRate = (readUInt32Be >> 4).UnpackBcd();
            FecInner = (InnerFecScheme)(readUInt32Be & 0x0000000f);

            if (S2)
            {
                switch (temp1)
                {
                    case 0:
                        RollOff = 0.35f;
                        break;
                    case 1:
                        RollOff = 0.25f;
                        break;
                    case 2:
                        RollOff = 0.20f;
                        break;
                    default:
                        break;
                }
            }

            Valid = true;
        }

        public int ModulationType { get; private set; }

        public float? RollOff { get; set; }

        public InnerFecScheme FecInner { get; set; }

        public long SymbolRate { get; set; }
        
        public bool S2 { get; set; }

        public PolarizationEnum Polarization { get; set; }

        public bool East { get; set; }

        public float OrbitalPosition { get; set; }

        public long Frequency { get; set; }

        public enum PolarizationEnum : byte
        {
            HorizontalLinear = 0,
            VerticalLinear = 1,
            LeftCircular = 2,
            RightCircular = 3
        }

        /*public enum ModulationTypeForSattelite
        {
            Auto = 0,
            QPSK = 2,
            _8PSK = 1,
            _16QAM = 3
        }*/

        public enum InnerFecScheme
        {
            NotDefined = 0,
            OneHalf = 1,
            TwoOfThree = 2,
            ThreeOfFour = 3,
            FiveOfSix = 4,
            SevenOfEight = 5,
            EightOfNine = 6,
            ThreeOfFive = 7,
            FourOfFive = 8,
            NineOfTen = 9,
            NoConventionalCoding = 15
        }

        public override string ToString()
        {
			StringBuilder sb = new StringBuilder();
			sb.Append(this.OrbitalPosition);
			sb.Append("°");
			sb.Append(this.East ? 'E' : 'W');
			sb.Append("/");
			sb.Append(Frequency / 100);
			sb.Append("/");
			sb.Append(this.Polarization.ToString()[0]);
			sb.Append("/");
			sb.Append(this.SymbolRate / 10);
			return sb.ToString();
		}
    }
}
