using skyscraper5.Mpeg2;
using skyscraper5.Skyscraper.IO;
using skyscraper5.Skyscraper.Plugins;

namespace skyscraper8.InteractionChannel.Model2.Descriptors;

[SkyscraperPlugin]
[TsDescriptor(0xb7,"TIM")]
public class _0xb7_FramePayloadFormatDescriptor : TsDescriptor
{
    public _0xb7_FramePayloadFormatDescriptor()
    {

    }

    public _0xb7_FramePayloadFormatDescriptor(byte[] buffer)
    {
        InBitStream bitstream = new InBitStream(buffer);
        byte contextLoopCount = bitstream.ReadBitsAsByte(8);
        Contexts = new TransmissionContext[contextLoopCount];
        for (int i = 0; i < contextLoopCount; i++)
        {
            TransmissionContext child = new TransmissionContext();
            Contexts[i] = child;
            child.TransmissionContextId = bitstream.ReadBitsAsByte(8);
            bitstream.Reserved(3);
            child.AllowPTypeOmission = bitstream.ReadBitAsBoolean();
            child.UseCompressedPType = bitstream.ReadBitAsBoolean();
            child.AllowAlpduCrc = bitstream.ReadBitAsBoolean();
            child.AllowAlpduSequenceNumber = bitstream.ReadBitAsBoolean();
            child.UseExplicitPayloadHeaderMap =  bitstream.ReadBitAsBoolean();
            child.ImplicitProtocolType = bitstream.ReadBitsAsByte(8);
            child.ImplicitPpduLabelSize = bitstream.ReadBitsAsByte(4);
            child.ImplicitPayloadLabelSize = bitstream.ReadBitsAsByte(4);
            bitstream.Reserved(4);
            child.Type0AlpduLabelSize = bitstream.ReadBitsAsByte(4);
        }

        Valid = true;
    }

    public TransmissionContext[] Contexts;

    public class TransmissionContext
    {
        public byte TransmissionContextId { get; set; }
        public bool AllowPTypeOmission { get; set; }
        public bool UseCompressedPType { get; set; }
        public bool AllowAlpduCrc { get; set; }
        public bool AllowAlpduSequenceNumber { get; set; }
        public bool UseExplicitPayloadHeaderMap { get; set; }
        public byte ImplicitProtocolType { get; set; }
        public byte ImplicitPpduLabelSize { get; set; }
        public byte ImplicitPayloadLabelSize { get; set; }
        public byte Type0AlpduLabelSize { get; set; }

		public override bool Equals(object? obj)
		{
			return obj is TransmissionContext context &&
				   TransmissionContextId == context.TransmissionContextId &&
				   AllowPTypeOmission == context.AllowPTypeOmission &&
				   UseCompressedPType == context.UseCompressedPType &&
				   AllowAlpduCrc == context.AllowAlpduCrc &&
				   AllowAlpduSequenceNumber == context.AllowAlpduSequenceNumber &&
				   UseExplicitPayloadHeaderMap == context.UseExplicitPayloadHeaderMap &&
				   ImplicitProtocolType == context.ImplicitProtocolType &&
				   ImplicitPpduLabelSize == context.ImplicitPpduLabelSize &&
				   ImplicitPayloadLabelSize == context.ImplicitPayloadLabelSize &&
				   Type0AlpduLabelSize == context.Type0AlpduLabelSize;
		}

		public override int GetHashCode()
		{
			HashCode hash = new HashCode();
			hash.Add(TransmissionContextId);
			hash.Add(AllowPTypeOmission);
			hash.Add(UseCompressedPType);
			hash.Add(AllowAlpduCrc);
			hash.Add(AllowAlpduSequenceNumber);
			hash.Add(UseExplicitPayloadHeaderMap);
			hash.Add(ImplicitProtocolType);
			hash.Add(ImplicitPpduLabelSize);
			hash.Add(ImplicitPayloadLabelSize);
			hash.Add(Type0AlpduLabelSize);
			return hash.ToHashCode();
		}
	}

	public override bool DescriptorEquals(TsDescriptor thatDescriptor)
	{
        _0xb7_FramePayloadFormatDescriptor that = thatDescriptor as _0xb7_FramePayloadFormatDescriptor;
        if (that == null)
            return false;

        bool thisHasContexts = this.Contexts != null;
        bool thatHasContexts = that.Contexts != null;

        if (thisHasContexts != thatHasContexts)
            return false;

        if (this.Contexts.Length != that.Contexts.Length)
            return false;

        for (int i = 0; i < this.Contexts.Length; i++)
        {
            if (!this.Contexts[i].Equals(that.Contexts[i]))
                return false;
        }
        return true;
	}

	public override string ToString()
	{
        return String.Format("{0} Frame Payload Formats", Contexts.Length);
	}
}
