using System;
using System.Text;
using QCRPG.Framework;

namespace QCRPG.TSL.BT.Packets;

public class ProdTestQhs : PacketBase
{
	public class UserFieldsWrapper
	{
		public enum SubopcodeEnum
		{
			PROD_TEST_QHS,
			InvalidSubopcodeValue
		}

		public static class SubopcodeInfo
		{
			public static SubopcodeEnum ValueToSubopcode(uint value)
			{
				if (value == 22)
				{
					return SubopcodeEnum.PROD_TEST_QHS;
				}
				return SubopcodeEnum.InvalidSubopcodeValue;
			}

			public static uint SubopcodeToValue(SubopcodeEnum enumItem)
			{
				if (enumItem == SubopcodeEnum.PROD_TEST_QHS)
				{
					return 22u;
				}
				return uint.MaxValue;
			}

			public static string SubopcodeToString(SubopcodeEnum enumItem)
			{
				if (enumItem == SubopcodeEnum.PROD_TEST_QHS)
				{
					return "PROD_TEST_QHS";
				}
				return "Invalid Subopcode Value";
			}

			public static string SubopcodeToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x16 = PROD_TEST_QHS");
				return stringBuilder.ToString();
			}
		}

		public enum TestModeEnum
		{
			QHS_Reserved,
			QHS_Tx_Test_Mode,
			QHS_Rx_Test_Mode,
			InvalidTestModeValue
		}

		public static class TestModeInfo
		{
			public static TestModeEnum ValueToTestMode(uint value)
			{
				if (value >= 0 && value <= 1)
				{
					return TestModeEnum.QHS_Reserved;
				}
				if (value == 2)
				{
					return TestModeEnum.QHS_Tx_Test_Mode;
				}
				if (value == 3)
				{
					return TestModeEnum.QHS_Rx_Test_Mode;
				}
				if (value >= 4 && value <= 255)
				{
					return TestModeEnum.QHS_Reserved;
				}
				return TestModeEnum.InvalidTestModeValue;
			}

			public static uint TestModeToValue(TestModeEnum enumItem)
			{
				switch (enumItem)
				{
				case TestModeEnum.QHS_Reserved:
					return 0u;
				case TestModeEnum.QHS_Tx_Test_Mode:
					return 2u;
				case TestModeEnum.QHS_Rx_Test_Mode:
					return 3u;
				default:
					if (enumItem == TestModeEnum.QHS_Reserved)
					{
						return 4u;
					}
					return uint.MaxValue;
				}
			}

			public static string TestModeToString(TestModeEnum enumItem)
			{
				switch (enumItem)
				{
				case TestModeEnum.QHS_Reserved:
					return "QHS_Reserved";
				case TestModeEnum.QHS_Tx_Test_Mode:
					return "QHS_Tx_Test_Mode";
				case TestModeEnum.QHS_Rx_Test_Mode:
					return "QHS_Rx_Test_Mode";
				default:
					if (enumItem == TestModeEnum.QHS_Reserved)
					{
						return "QHS_Reserved";
					}
					return "Invalid TestMode Value";
				}
			}

			public static string TestModeToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0-0x1 = QHS_Reserved");
				stringBuilder.AppendLine("0x2 = QHS_Tx_Test_Mode");
				stringBuilder.AppendLine("0x3 = QHS_Rx_Test_Mode");
				stringBuilder.AppendLine("0x4-0xFF = QHS_Reserved");
				return stringBuilder.ToString();
			}
		}

		public enum PhyRateEnum
		{
			QHS2P_2Mbps_PSK_Modulation,
			QHS2P_3Mbps_PSK_Modulation,
			QHS2P_4Mbps_PSK_Modulation,
			QHS2P_5Mbps_PSK_Modulation,
			QHS2P_6Mbps_PSK_Modulation,
			InvalidPhyRateValue
		}

		public static class PhyRateInfo
		{
			public static PhyRateEnum ValueToPhyRate(uint value)
			{
				return value switch
				{
					6u => PhyRateEnum.QHS2P_2Mbps_PSK_Modulation, 
					7u => PhyRateEnum.QHS2P_3Mbps_PSK_Modulation, 
					8u => PhyRateEnum.QHS2P_4Mbps_PSK_Modulation, 
					9u => PhyRateEnum.QHS2P_5Mbps_PSK_Modulation, 
					10u => PhyRateEnum.QHS2P_6Mbps_PSK_Modulation, 
					_ => PhyRateEnum.InvalidPhyRateValue, 
				};
			}

			public static uint PhyRateToValue(PhyRateEnum enumItem)
			{
				return enumItem switch
				{
					PhyRateEnum.QHS2P_2Mbps_PSK_Modulation => 6u, 
					PhyRateEnum.QHS2P_3Mbps_PSK_Modulation => 7u, 
					PhyRateEnum.QHS2P_4Mbps_PSK_Modulation => 8u, 
					PhyRateEnum.QHS2P_5Mbps_PSK_Modulation => 9u, 
					PhyRateEnum.QHS2P_6Mbps_PSK_Modulation => 10u, 
					_ => uint.MaxValue, 
				};
			}

			public static string PhyRateToString(PhyRateEnum enumItem)
			{
				return enumItem switch
				{
					PhyRateEnum.QHS2P_2Mbps_PSK_Modulation => "QHS2P_2Mbps_PSK_Modulation", 
					PhyRateEnum.QHS2P_3Mbps_PSK_Modulation => "QHS2P_3Mbps_PSK_Modulation", 
					PhyRateEnum.QHS2P_4Mbps_PSK_Modulation => "QHS2P_4Mbps_PSK_Modulation", 
					PhyRateEnum.QHS2P_5Mbps_PSK_Modulation => "QHS2P_5Mbps_PSK_Modulation", 
					PhyRateEnum.QHS2P_6Mbps_PSK_Modulation => "QHS2P_6Mbps_PSK_Modulation", 
					_ => "Invalid PhyRate Value", 
				};
			}

			public static string PhyRateToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x6 = QHS2P_2Mbps_PSK_Modulation");
				stringBuilder.AppendLine("0x7 = QHS2P_3Mbps_PSK_Modulation");
				stringBuilder.AppendLine("0x8 = QHS2P_4Mbps_PSK_Modulation");
				stringBuilder.AppendLine("0x9 = QHS2P_5Mbps_PSK_Modulation");
				stringBuilder.AppendLine("0xA = QHS2P_6Mbps_PSK_Modulation");
				return stringBuilder.ToString();
			}
		}

		public enum TxPowerIndexEnum
		{
			Tx_Lowest_Power,
			Tx_Power_Index,
			Tx_Highest_Power,
			InvalidTxPowerIndexValue
		}

		public static class TxPowerIndexInfo
		{
			public static TxPowerIndexEnum ValueToTxPowerIndex(uint value)
			{
				if (value == 0)
				{
					return TxPowerIndexEnum.Tx_Lowest_Power;
				}
				if (value >= 1 && value <= 8)
				{
					return TxPowerIndexEnum.Tx_Power_Index;
				}
				if (value == 9)
				{
					return TxPowerIndexEnum.Tx_Highest_Power;
				}
				return TxPowerIndexEnum.InvalidTxPowerIndexValue;
			}

			public static uint TxPowerIndexToValue(TxPowerIndexEnum enumItem)
			{
				return enumItem switch
				{
					TxPowerIndexEnum.Tx_Lowest_Power => 0u, 
					TxPowerIndexEnum.Tx_Power_Index => 1u, 
					TxPowerIndexEnum.Tx_Highest_Power => 9u, 
					_ => uint.MaxValue, 
				};
			}

			public static string TxPowerIndexToString(TxPowerIndexEnum enumItem)
			{
				return enumItem switch
				{
					TxPowerIndexEnum.Tx_Lowest_Power => "Tx_Lowest_Power", 
					TxPowerIndexEnum.Tx_Power_Index => "Tx_Power_Index", 
					TxPowerIndexEnum.Tx_Highest_Power => "Tx_Highest_Power", 
					_ => "Invalid TxPowerIndex Value", 
				};
			}

			public static string TxPowerIndexToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = Tx_Lowest_Power");
				stringBuilder.AppendLine("0x1-0x8 = Tx_Power_Index");
				stringBuilder.AppendLine("0x9 = Tx_Highest_Power");
				return stringBuilder.ToString();
			}
		}

		private const uint _Subopcode = 22u;

		private uint _TestMode;

		private uint _Channel;

		private uint _PayloadLength;

		private uint _PayloadPattern;

		private uint _PhyRate;

		private uint _TxPowerIndex;

		private uint _MaxPackets;

		public uint Subopcode => 22u;

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

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

		public uint PayloadLength
		{
			get
			{
				return _PayloadLength;
			}
			set
			{
				if (value > 65535)
				{
					throw new Exception("Maximum possible value for PayloadLength is 0xFFFF");
				}
				_PayloadLength = value;
			}
		}

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

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

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

		public uint MaxPackets
		{
			get
			{
				return _MaxPackets;
			}
			set
			{
				if (value > 65535)
				{
					throw new Exception("Maximum possible value for MaxPackets is 0xFFFF");
				}
				_MaxPackets = value;
			}
		}

		public SubopcodeEnum GetSubopcodeAsSubopcodeEnum()
		{
			return SubopcodeInfo.ValueToSubopcode(22u);
		}

		public TestModeEnum GetTestModeAsTestModeEnum()
		{
			return TestModeInfo.ValueToTestMode(_TestMode);
		}

		public void SetTestModeAsTestModeEnum(TestModeEnum enumItem)
		{
			TestMode = TestModeInfo.TestModeToValue(enumItem);
		}

		public PayloadPatternEnum GetPayloadPatternAsPayloadPatternEnum()
		{
			return PayloadPatternInfo.ValueToPayloadPattern(_PayloadPattern);
		}

		public void SetPayloadPatternAsPayloadPatternEnum(PayloadPatternEnum enumItem)
		{
			PayloadPattern = PayloadPatternInfo.PayloadPatternToValue(enumItem);
		}

		public PhyRateEnum GetPhyRateAsPhyRateEnum()
		{
			return PhyRateInfo.ValueToPhyRate(_PhyRate);
		}

		public void SetPhyRateAsPhyRateEnum(PhyRateEnum enumItem)
		{
			PhyRate = PhyRateInfo.PhyRateToValue(enumItem);
		}

		public TxPowerIndexEnum GetTxPowerIndexAsTxPowerIndexEnum()
		{
			return TxPowerIndexInfo.ValueToTxPowerIndex(_TxPowerIndex);
		}

		public void SetTxPowerIndexAsTxPowerIndexEnum(TxPowerIndexEnum enumItem)
		{
			TxPowerIndex = TxPowerIndexInfo.TxPowerIndexToValue(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 ProdTestQhsInfo(this);
			}
			return info;
		}
	}

	public uint Opcode => 64516u;

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

	public UserFieldsWrapper UserFields => _UserFields;

	public override void SetDefaultValues()
	{
		UserFields.TestMode = 2u;
		UserFields.PhyRate = 6u;
		UserFields.TxPowerIndex = 9u;
	}

	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.Subopcode)
		{
			return false;
		}
		UserFields.TestMode = bitBuilder.RemoveBitsAsUint(8);
		UserFields.Channel = bitBuilder.RemoveBitsAsUint(8);
		UserFields.PayloadLength = bitBuilder.RemoveBitsAsUintLittleEndian(16);
		UserFields.PayloadPattern = bitBuilder.RemoveBitsAsUint(8);
		UserFields.PhyRate = bitBuilder.RemoveBitsAsUint(8);
		UserFields.TxPowerIndex = bitBuilder.RemoveBitsAsUint(8);
		UserFields.MaxPackets = bitBuilder.RemoveBitsAsUint(16);
		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.Subopcode, 8);
		bitBuilder.AddBitsAsUint(UserFields.TestMode, 8);
		bitBuilder.AddBitsAsUint(UserFields.Channel, 8);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.PayloadLength, 16);
		bitBuilder.AddBitsAsUint(UserFields.PayloadPattern, 8);
		bitBuilder.AddBitsAsUint(UserFields.PhyRate, 8);
		bitBuilder.AddBitsAsUint(UserFields.TxPowerIndex, 8);
		bitBuilder.AddBitsAsUint(UserFields.MaxPackets, 16);
		_PayloadLength = (uint)((bitBuilder.GetNumberOfBits() - numberOfBits - 8) / 8);
		if ((bitBuilder.GetNumberOfBits() - numberOfBits - 8) % 8 != 0)
		{
			_PayloadLength++;
		}
		bitBuilder.ChangeBitsAsUint(numberOfBits, _PayloadLength, 8);
		return bitBuilder.ToString();
	}
}
