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

namespace skyscraper5.src.InteractionChannel.Model.Descriptors
{
	[SkyscraperPlugin]
	[TsDescriptor(0xa1, "TIM")]
	public class _0xa1_CorrectionMessageDescriptor : TsDescriptor, IEquatable<_0xa1_CorrectionMessageDescriptor?>
    {
		public _0xa1_CorrectionMessageDescriptor()
		{

		}

		public _0xa1_CorrectionMessageDescriptor(byte[] buffer)
		{
			MemoryStream ms = new MemoryStream(buffer, false);
			InBitStream ibs = new InBitStream(ms);

			bool timeCorrectionFlag = ibs.ReadBitAsBoolean();
			bool powerCorrectionFlag = ibs.ReadBitAsBoolean();
			bool frequencyCorrectionFlag = ibs.ReadBitAsBoolean();
			SlotType = (CorrectionMessageSlotType)ibs.ReadBitsAsByte(2);
			BurstTimeScaling = ibs.ReadBitsAsUInt16(3);

			if (timeCorrectionFlag)
			{
				BurstTimeCorrection = ibs.ReadBitsAsByte(8);
			}

			if (powerCorrectionFlag)
			{
				bool powerControlFlag = ibs.ReadBitAsBoolean();
				if (powerControlFlag)
				{
					PowerCorrection = ibs.ReadBitsAsByte(7);
				}
				else
				{
					EsN0 = ibs.ReadBitsAsByte(7);
				}
			}

			if (frequencyCorrectionFlag)
			{
				FrequencyCorrection = ibs.ReadBitsAsUInt16(16);
			}

			Valid = true;
		}

		public _0xa1_CorrectionMessageDescriptor(CorrectionMessageSlotType slotType, int burstTimeScaling, uint? burstTimeCorrection, int? powerCorrection, int? esN0, ushort frequencyCorrection)
		{
			SlotType = slotType;
			BurstTimeScaling = burstTimeScaling;
			BurstTimeCorrection = burstTimeCorrection;
			PowerCorrection = powerCorrection;
			EsN0 = esN0;
			FrequencyCorrection = frequencyCorrection;
		}

		public CorrectionMessageSlotType SlotType { get; }
		public int BurstTimeScaling { get; internal set; }
		public uint? BurstTimeCorrection { get; internal set; }
		public int? PowerCorrection { get; internal set; }
		public int? EsN0 { get; internal set; }
		public ushort FrequencyCorrection { get; internal set; }

		public override bool Equals(object obj)
		{
			return obj is _0xa1_CorrectionMessageDescriptor descriptor &&
				   SlotType == descriptor.SlotType &&
				   BurstTimeScaling == descriptor.BurstTimeScaling &&
				   BurstTimeCorrection == descriptor.BurstTimeCorrection &&
				   PowerCorrection == descriptor.PowerCorrection &&
				   EsN0 == descriptor.EsN0 &&
				   FrequencyCorrection == descriptor.FrequencyCorrection;
		}

        public bool Equals(_0xa1_CorrectionMessageDescriptor? other)
        {
            return other is not null &&
                   SlotType == other.SlotType &&
                   BurstTimeScaling == other.BurstTimeScaling &&
                   BurstTimeCorrection == other.BurstTimeCorrection &&
                   PowerCorrection == other.PowerCorrection &&
                   EsN0 == other.EsN0 &&
                   FrequencyCorrection == other.FrequencyCorrection;
        }

        public override int GetHashCode()
        {
            return HashCode.Combine(SlotType, BurstTimeScaling, BurstTimeCorrection, PowerCorrection, EsN0, FrequencyCorrection);
        }

        public static bool operator ==(_0xa1_CorrectionMessageDescriptor? left, _0xa1_CorrectionMessageDescriptor? right)
        {
            return EqualityComparer<_0xa1_CorrectionMessageDescriptor>.Default.Equals(left, right);
        }

        public static bool operator !=(_0xa1_CorrectionMessageDescriptor? left, _0xa1_CorrectionMessageDescriptor? right)
        {
            return !(left == right);
        }

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

			return this.Equals(that);
		}

		public override string ToString()
		{
			return String.Format("Correction for Slot {0}", SlotType);
		}
    }
}
