using System;
using System.Collections.Generic;
using System.Text;
using QCRPG.Framework;

namespace QCRPG.TSL.BT.Packets;

public class ProdTestTxContinuous : PacketBase
{
	public class UserFieldsWrapper
	{
		public enum TransmitTypeEnum
		{
			CW_ONLY,
			ONE_PRBS9_GFSK,
			ONE_PRBS15_GFSK,
			ONE_PATTERN_GFSK,
			TWO_PRBS9_PI_DIV_4_DQPSK,
			TWO_PRBS15_PI_DIV_4_DQPSK,
			TWO_PATTERN_PI_DIV_4_DQPSK,
			THREE_PRBS9_8DPSK,
			THREE_PRBS15_8DPSK,
			THREE_PATTERN_8DPSK,
			InvalidTransmitTypeValue
		}

		public static class TransmitTypeInfo
		{
			public static TransmitTypeEnum ValueToTransmitType(uint value)
			{
				return value switch
				{
					4u => TransmitTypeEnum.CW_ONLY, 
					5u => TransmitTypeEnum.ONE_PRBS9_GFSK, 
					6u => TransmitTypeEnum.ONE_PRBS15_GFSK, 
					7u => TransmitTypeEnum.ONE_PATTERN_GFSK, 
					8u => TransmitTypeEnum.TWO_PRBS9_PI_DIV_4_DQPSK, 
					9u => TransmitTypeEnum.TWO_PRBS15_PI_DIV_4_DQPSK, 
					10u => TransmitTypeEnum.TWO_PATTERN_PI_DIV_4_DQPSK, 
					11u => TransmitTypeEnum.THREE_PRBS9_8DPSK, 
					12u => TransmitTypeEnum.THREE_PRBS15_8DPSK, 
					13u => TransmitTypeEnum.THREE_PATTERN_8DPSK, 
					_ => TransmitTypeEnum.InvalidTransmitTypeValue, 
				};
			}

			public static uint TransmitTypeToValue(TransmitTypeEnum enumItem)
			{
				return enumItem switch
				{
					TransmitTypeEnum.CW_ONLY => 4u, 
					TransmitTypeEnum.ONE_PRBS9_GFSK => 5u, 
					TransmitTypeEnum.ONE_PRBS15_GFSK => 6u, 
					TransmitTypeEnum.ONE_PATTERN_GFSK => 7u, 
					TransmitTypeEnum.TWO_PRBS9_PI_DIV_4_DQPSK => 8u, 
					TransmitTypeEnum.TWO_PRBS15_PI_DIV_4_DQPSK => 9u, 
					TransmitTypeEnum.TWO_PATTERN_PI_DIV_4_DQPSK => 10u, 
					TransmitTypeEnum.THREE_PRBS9_8DPSK => 11u, 
					TransmitTypeEnum.THREE_PRBS15_8DPSK => 12u, 
					TransmitTypeEnum.THREE_PATTERN_8DPSK => 13u, 
					_ => uint.MaxValue, 
				};
			}

			public static string TransmitTypeToString(TransmitTypeEnum enumItem)
			{
				return enumItem switch
				{
					TransmitTypeEnum.CW_ONLY => "Carrier (CW) only", 
					TransmitTypeEnum.ONE_PRBS9_GFSK => "1-PRBS9 (GFSK)", 
					TransmitTypeEnum.ONE_PRBS15_GFSK => "1-PRBS15 (GFSK)", 
					TransmitTypeEnum.ONE_PATTERN_GFSK => "1-Pattern (GFSK) as specified by Pattern Length", 
					TransmitTypeEnum.TWO_PRBS9_PI_DIV_4_DQPSK => "2-PRBS9 (Pi/4-DQPSK)", 
					TransmitTypeEnum.TWO_PRBS15_PI_DIV_4_DQPSK => "2-PRBS15 (Pi/4-DQPSK)", 
					TransmitTypeEnum.TWO_PATTERN_PI_DIV_4_DQPSK => "2-Pattern (Pi/4-DQPSK)", 
					TransmitTypeEnum.THREE_PRBS9_8DPSK => "3-PRBS9 (8DPSK)", 
					TransmitTypeEnum.THREE_PRBS15_8DPSK => "3-PRBS15 (8DPSK)", 
					TransmitTypeEnum.THREE_PATTERN_8DPSK => "3-Pattern (8DPSK)", 
					_ => "Invalid TransmitType Value", 
				};
			}

			public static string TransmitTypeToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x4 = Carrier (CW) only");
				stringBuilder.AppendLine("0x5 = 1-PRBS9 (GFSK)");
				stringBuilder.AppendLine("0x6 = 1-PRBS15 (GFSK)");
				stringBuilder.AppendLine("0x7 = 1-Pattern (GFSK) as specified by Pattern Length");
				stringBuilder.AppendLine("0x8 = 2-PRBS9 (Pi/4-DQPSK)");
				stringBuilder.AppendLine("0x9 = 2-PRBS15 (Pi/4-DQPSK)");
				stringBuilder.AppendLine("0xA = 2-Pattern (Pi/4-DQPSK)");
				stringBuilder.AppendLine("0xB = 3-PRBS9 (8DPSK)");
				stringBuilder.AppendLine("0xC = 3-PRBS15 (8DPSK)");
				stringBuilder.AppendLine("0xD = 3-Pattern (8DPSK)");
				return stringBuilder.ToString();
			}
		}

		private const uint _Command = 5u;

		private uint _ChannelNumber;

		private uint _TransmitOutputPower;

		private uint _TransmitType = 4u;

		private uint _PatternLength = 1u;

		private uint _BitPattern;

		public uint Command => 5u;

		public uint ChannelNumber
		{
			get
			{
				return _ChannelNumber;
			}
			set
			{
				if (value > 255)
				{
					throw new Exception("Maximum possible value for ChannelNumber is 0xFF");
				}
				_ChannelNumber = value;
			}
		}

		public uint TransmitOutputPower
		{
			get
			{
				return _TransmitOutputPower;
			}
			set
			{
				if (value > 255)
				{
					throw new Exception("Maximum possible value for TransmitOutputPower is 0xFF");
				}
				_TransmitOutputPower = value;
			}
		}

		public uint TransmitType
		{
			get
			{
				return _TransmitType;
			}
			set
			{
				if (value > 255)
				{
					throw new Exception("Maximum possible value for TransmitType is 0xFF");
				}
				_TransmitType = value;
			}
		}

		public uint PatternLength
		{
			get
			{
				return _PatternLength;
			}
			set
			{
				if (value > 255)
				{
					throw new Exception("Maximum possible value for PatternLength is 0xFF");
				}
				_PatternLength = value;
			}
		}

		public uint BitPattern
		{
			get
			{
				return _BitPattern;
			}
			set
			{
				_BitPattern = value;
			}
		}

		public TransmitTypeEnum GetTransmitTypeAsTransmitTypeEnum()
		{
			return TransmitTypeInfo.ValueToTransmitType(_TransmitType);
		}

		public void SetTransmitTypeAsTransmitTypeEnum(TransmitTypeEnum enumItem)
		{
			TransmitType = TransmitTypeInfo.TransmitTypeToValue(enumItem);
		}
	}

	private const uint _Opcode = 64516u;

	private Type[] expectedResponseTypes = new Type[1] { typeof(CommandCompleteForProdTest) };

	private PacketInfoBase info;

	private uint _PayloadLength;

	public UserFieldsWrapper _UserFields = new UserFieldsWrapper();

	public override PacketType Type => PacketType.Command;

	public override Type[] ExpectedResponseTypes => expectedResponseTypes;

	public override PacketInfoBase Info
	{
		get
		{
			if (info == null)
			{
				info = new ProdTestTxContinuousInfo(this);
			}
			return info;
		}
	}

	public uint Opcode => 64516u;

	public uint PayloadLength
	{
		get
		{
			ToBitString();
			return _PayloadLength;
		}
	}

	public UserFieldsWrapper UserFields => _UserFields;

	public override void SetDefaultValues()
	{
		UserFields.TransmitType = 4u;
		UserFields.PatternLength = 1u;
	}

	protected override bool FromBitBuilder(ref BitBuilder bitBuilder)
	{
		if (bitBuilder.RemoveBitsAsUintLittleEndian(16) != Opcode)
		{
			return false;
		}
		_PayloadLength = bitBuilder.RemoveBitsAsUint(8);
		int numberOfBits = bitBuilder.GetNumberOfBits();
		if (numberOfBits > _PayloadLength * 8 + 7)
		{
			return false;
		}
		if (numberOfBits < _PayloadLength * 8)
		{
			return false;
		}
		if (bitBuilder.RemoveBitsAsUint(8) != UserFields.Command)
		{
			return false;
		}
		UserFields.ChannelNumber = bitBuilder.RemoveBitsAsUint(8);
		UserFields.TransmitOutputPower = bitBuilder.RemoveBitsAsUint(8);
		UserFields.TransmitType = bitBuilder.RemoveBitsAsUint(8);
		UserFields.PatternLength = bitBuilder.RemoveBitsAsUint(8);
		UserFields.BitPattern = bitBuilder.RemoveBitsAsUintLittleEndian(32);
		if (bitBuilder.GetNumberOfBits() > 7)
		{
			return false;
		}
		return true;
	}

	public override string ToBitString()
	{
		BitBuilder bitBuilder = new BitBuilder();
		bitBuilder.AddBitsAsUintLittleEndian(Opcode, 16);
		int numberOfBits = bitBuilder.GetNumberOfBits();
		bitBuilder.AddBitsAsUint(0u, 8);
		bitBuilder.AddBitsAsUint(UserFields.Command, 8);
		bitBuilder.AddBitsAsUint(UserFields.ChannelNumber, 8);
		bitBuilder.AddBitsAsUint(UserFields.TransmitOutputPower, 8);
		bitBuilder.AddBitsAsUint(UserFields.TransmitType, 8);
		bitBuilder.AddBitsAsUint(UserFields.PatternLength, 8);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.BitPattern, 32);
		_PayloadLength = (uint)((bitBuilder.GetNumberOfBits() - numberOfBits - 8) / 8);
		if ((bitBuilder.GetNumberOfBits() - numberOfBits - 8) % 8 != 0)
		{
			_PayloadLength++;
		}
		bitBuilder.ChangeBitsAsUint(numberOfBits, _PayloadLength, 8);
		return bitBuilder.ToString();
	}

	public override List<string> GetWarnings()
	{
		List<string> list = new List<string>();
		if (UserFields.ChannelNumber > 78)
		{
			list.Add("Maximum allowed value for Channel Number is 0x4E");
		}
		if (UserFields.TransmitOutputPower > 9)
		{
			list.Add("Maximum allowed value for Transmit Output Power is 0x9");
		}
		if (UserFields.TransmitType < 4)
		{
			list.Add("Minimum allowed value for Transmit Type is 0x4");
		}
		if (UserFields.TransmitType > 13)
		{
			list.Add("Maximum allowed value for Transmit Type is 0xD");
		}
		if (UserFields.PatternLength < 1)
		{
			list.Add("Minimum allowed value for Pattern Length is 0x1");
		}
		if (UserFields.PatternLength > 32)
		{
			list.Add("Maximum allowed value for Pattern Length is 0x20");
		}
		return list;
	}
}
