using System;
using System.Collections.Generic;
using System.IO;
using skyscraper5.Skyscraper.IO;

namespace skyscraper5.Dvb.Subtitling
{
    internal class ClutDefinitionSegment
    {
        public ClutDefinitionSegment(byte[] segmentData)
        {
            MemoryStream ms = new MemoryStream(segmentData, false);
            ClutId = ms.ReadUInt8();
            ClutVersionNumber = (ms.ReadUInt8()) >> 4;

            ClutEntries = new List<ClutEntry>();
            while (ms.GetAvailableBytes() > 0)
            {
                ClutEntry child = new ClutEntry();
                child.ClutEntryId = ms.ReadUInt8();
                byte readUInt8 = ms.ReadUInt8();
                child._2bitEntryClutFlag = (readUInt8 & 0x80) != 0;
                child._4bitEntryClutFlag = (readUInt8 & 0x40) != 0;
                child._8bitEntryClutFlag = (readUInt8 & 0x20) != 0;
                child.FullRangeFlag = (readUInt8 & 0x01) != 0;
                if (child.FullRangeFlag)
                {
                    if (ms.GetAvailableBytes() < 4)
                        break;
                    child.Y = ms.ReadUInt8();
                    child.Cr = ms.ReadUInt8();
                    child.Cb = ms.ReadUInt8();
                    child.T = ms.ReadUInt8();
                }
                else
                {
                    if (ms.GetAvailableBytes() < 2)
                        break;
                    ushort readUInt16Be = ms.ReadUInt16BE();
                    child.Y = (byte)((readUInt16Be & 0xfc00) >> 10);
                    child.Cr = (byte)((readUInt16Be & 0x03c0) >> 6);
                    child.Cb = (byte)((readUInt16Be & 0x003c) >> 2);
                    child.T = (byte)((readUInt16Be & 0x0003));

                    child.Y = (byte)((double)child.Y * 1.25);
                    child.Cr *= 2;
                    child.Cb *= 2;
                    child.T *= 4;
                }

                ClutEntries.Add(child);
            }
        }

        public List<ClutEntry> ClutEntries { get; private set; }
        public int ClutVersionNumber { get; private set; }

        public byte ClutId { get; private set; }

        public class ClutEntry
        {
            public byte ClutEntryId { get; internal set; }
            public bool _2bitEntryClutFlag { get; internal set; }
            public bool _4bitEntryClutFlag { get; internal set; }
            public bool _8bitEntryClutFlag { get; internal set; }
            public bool FullRangeFlag { get; internal set; }
            public byte Y { get; internal set; }
            public byte Cr { get; internal set; }
            public byte Cb { get; internal set; }
            public byte T { get; internal set; }

            public override string ToString()
            {
                return
                    $"{nameof(ClutEntryId)}: {ClutEntryId}, {nameof(Y)}: {Y}, {nameof(Cr)}: {Cr}, {nameof(Cb)}: {Cb}, {nameof(T)}: {T}";
            }
        }
    }
}