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

namespace QCRPG.TSL.BT.Packets;

public class LtQ2qTest : PacketBase
{
	public class UserFieldsWrapper
	{
		public enum Q2qTestModeEnum
		{
			QLL_NORMAL_EST,
			QLL_SRV_REQ_TO,
			QLL_SRV_RSP_TO,
			QLL_AUTH_REQ_TO,
			QLL_AUTH_RSP_TO,
			QLL_CONN_IND_TO,
			QLL_AUTH_FAIL_M,
			QLL_AUTH_FAIL_S,
			QLL_FEATURE_EXCHANGE,
			QLL_PHY_REJECT,
			QLL_PWR_CTRL_REQ_REJECT,
			QLL_PWR_CTRL_IND_REJECT,
			QLL_PWR_CTRL_INC,
			QLL_PWR_CTRL_DEC,
			QLMP_NORMAL_EST,
			QLMP_SRV_REQ_TO,
			QLMP_SRV_RSP_TO,
			QLMP_AUTH_REQ_TO,
			QLMP_AUTH_RSP_TO,
			QLMP_AUTH_FAIL_M,
			QLMP_AUTH_FAIL_S,
			QLMP_AUTH_DEBUG_KEY,
			QLMP_AUTH_AUTO,
			InvalidQ2qTestModeValue
		}

		public static class Q2qTestModeInfo
		{
			public static Q2qTestModeEnum ValueToQ2qTestMode(uint value)
			{
				return value switch
				{
					0u => Q2qTestModeEnum.QLL_NORMAL_EST, 
					1u => Q2qTestModeEnum.QLL_SRV_REQ_TO, 
					2u => Q2qTestModeEnum.QLL_SRV_RSP_TO, 
					3u => Q2qTestModeEnum.QLL_AUTH_REQ_TO, 
					4u => Q2qTestModeEnum.QLL_AUTH_RSP_TO, 
					5u => Q2qTestModeEnum.QLL_CONN_IND_TO, 
					6u => Q2qTestModeEnum.QLL_AUTH_FAIL_M, 
					7u => Q2qTestModeEnum.QLL_AUTH_FAIL_S, 
					8u => Q2qTestModeEnum.QLL_FEATURE_EXCHANGE, 
					9u => Q2qTestModeEnum.QLL_PHY_REJECT, 
					10u => Q2qTestModeEnum.QLL_PWR_CTRL_REQ_REJECT, 
					11u => Q2qTestModeEnum.QLL_PWR_CTRL_IND_REJECT, 
					12u => Q2qTestModeEnum.QLL_PWR_CTRL_INC, 
					13u => Q2qTestModeEnum.QLL_PWR_CTRL_DEC, 
					14u => Q2qTestModeEnum.QLMP_NORMAL_EST, 
					15u => Q2qTestModeEnum.QLMP_SRV_REQ_TO, 
					16u => Q2qTestModeEnum.QLMP_SRV_RSP_TO, 
					17u => Q2qTestModeEnum.QLMP_AUTH_REQ_TO, 
					18u => Q2qTestModeEnum.QLMP_AUTH_RSP_TO, 
					19u => Q2qTestModeEnum.QLMP_AUTH_FAIL_M, 
					20u => Q2qTestModeEnum.QLMP_AUTH_FAIL_S, 
					21u => Q2qTestModeEnum.QLMP_AUTH_DEBUG_KEY, 
					22u => Q2qTestModeEnum.QLMP_AUTH_AUTO, 
					_ => Q2qTestModeEnum.InvalidQ2qTestModeValue, 
				};
			}

			public static uint Q2qTestModeToValue(Q2qTestModeEnum enumItem)
			{
				return enumItem switch
				{
					Q2qTestModeEnum.QLL_NORMAL_EST => 0u, 
					Q2qTestModeEnum.QLL_SRV_REQ_TO => 1u, 
					Q2qTestModeEnum.QLL_SRV_RSP_TO => 2u, 
					Q2qTestModeEnum.QLL_AUTH_REQ_TO => 3u, 
					Q2qTestModeEnum.QLL_AUTH_RSP_TO => 4u, 
					Q2qTestModeEnum.QLL_CONN_IND_TO => 5u, 
					Q2qTestModeEnum.QLL_AUTH_FAIL_M => 6u, 
					Q2qTestModeEnum.QLL_AUTH_FAIL_S => 7u, 
					Q2qTestModeEnum.QLL_FEATURE_EXCHANGE => 8u, 
					Q2qTestModeEnum.QLL_PHY_REJECT => 9u, 
					Q2qTestModeEnum.QLL_PWR_CTRL_REQ_REJECT => 10u, 
					Q2qTestModeEnum.QLL_PWR_CTRL_IND_REJECT => 11u, 
					Q2qTestModeEnum.QLL_PWR_CTRL_INC => 12u, 
					Q2qTestModeEnum.QLL_PWR_CTRL_DEC => 13u, 
					Q2qTestModeEnum.QLMP_NORMAL_EST => 14u, 
					Q2qTestModeEnum.QLMP_SRV_REQ_TO => 15u, 
					Q2qTestModeEnum.QLMP_SRV_RSP_TO => 16u, 
					Q2qTestModeEnum.QLMP_AUTH_REQ_TO => 17u, 
					Q2qTestModeEnum.QLMP_AUTH_RSP_TO => 18u, 
					Q2qTestModeEnum.QLMP_AUTH_FAIL_M => 19u, 
					Q2qTestModeEnum.QLMP_AUTH_FAIL_S => 20u, 
					Q2qTestModeEnum.QLMP_AUTH_DEBUG_KEY => 21u, 
					Q2qTestModeEnum.QLMP_AUTH_AUTO => 22u, 
					_ => uint.MaxValue, 
				};
			}

			public static string Q2qTestModeToString(Q2qTestModeEnum enumItem)
			{
				return enumItem switch
				{
					Q2qTestModeEnum.QLL_NORMAL_EST => "QLL Normal establishment test", 
					Q2qTestModeEnum.QLL_SRV_REQ_TO => "QLL: Test the case when service request time out", 
					Q2qTestModeEnum.QLL_SRV_RSP_TO => "QLL: Test the case when service response time out", 
					Q2qTestModeEnum.QLL_AUTH_REQ_TO => "QLL: Test the case when auth request time out", 
					Q2qTestModeEnum.QLL_AUTH_RSP_TO => "QLL: Test the case when auth response time out", 
					Q2qTestModeEnum.QLL_CONN_IND_TO => "QLL: Test the case when conn indication time out", 
					Q2qTestModeEnum.QLL_AUTH_FAIL_M => "QLL: Test the case when authentication failed for master", 
					Q2qTestModeEnum.QLL_AUTH_FAIL_S => "QLL: Test the case when authentication failed for slave", 
					Q2qTestModeEnum.QLL_FEATURE_EXCHANGE => "QLL: Test feature exchange procedure", 
					Q2qTestModeEnum.QLL_PHY_REJECT => "QLL: Test phy requeset rejection case", 
					Q2qTestModeEnum.QLL_PWR_CTRL_REQ_REJECT => "QLL: Test power control request requeset rejection case", 
					Q2qTestModeEnum.QLL_PWR_CTRL_IND_REJECT => "QLL: Test power control indication rejection case", 
					Q2qTestModeEnum.QLL_PWR_CTRL_INC => "QLL: Test power control with request increase", 
					Q2qTestModeEnum.QLL_PWR_CTRL_DEC => "QLL: Test power control with request decrease", 
					Q2qTestModeEnum.QLMP_NORMAL_EST => "QLMP Normal establishment test", 
					Q2qTestModeEnum.QLMP_SRV_REQ_TO => "QLMP: Test the case when service request time out", 
					Q2qTestModeEnum.QLMP_SRV_RSP_TO => "QLMP: Test the case when service response time out", 
					Q2qTestModeEnum.QLMP_AUTH_REQ_TO => "QLMP: Test the case when auth request time out", 
					Q2qTestModeEnum.QLMP_AUTH_RSP_TO => "QLMP: Test the case when auth response time out", 
					Q2qTestModeEnum.QLMP_AUTH_FAIL_M => "QLMP: Test the case when authentication failed for master", 
					Q2qTestModeEnum.QLMP_AUTH_FAIL_S => "QLMP: Test the case when authentication failed for slave", 
					Q2qTestModeEnum.QLMP_AUTH_DEBUG_KEY => "QLMP: Test the case when encryption using debug key (only for simple pairing)", 
					Q2qTestModeEnum.QLMP_AUTH_AUTO => "QLMP: Test the case when auto authentication enabled.(only for legacy authentication", 
					_ => "Invalid Q2qTestMode Value", 
				};
			}

			public static string Q2qTestModeToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = QLL Normal establishment test");
				stringBuilder.AppendLine("0x1 = QLL: Test the case when service request time out");
				stringBuilder.AppendLine("0x2 = QLL: Test the case when service response time out");
				stringBuilder.AppendLine("0x3 = QLL: Test the case when auth request time out");
				stringBuilder.AppendLine("0x4 = QLL: Test the case when auth response time out");
				stringBuilder.AppendLine("0x5 = QLL: Test the case when conn indication time out");
				stringBuilder.AppendLine("0x6 = QLL: Test the case when authentication failed for master");
				stringBuilder.AppendLine("0x7 = QLL: Test the case when authentication failed for slave");
				stringBuilder.AppendLine("0x8 = QLL: Test feature exchange procedure");
				stringBuilder.AppendLine("0x9 = QLL: Test phy requeset rejection case");
				stringBuilder.AppendLine("0xA = QLL: Test power control request requeset rejection case");
				stringBuilder.AppendLine("0xB = QLL: Test power control indication rejection case");
				stringBuilder.AppendLine("0xC = QLL: Test power control with request increase");
				stringBuilder.AppendLine("0xD = QLL: Test power control with request decrease");
				stringBuilder.AppendLine("0xE = QLMP Normal establishment test");
				stringBuilder.AppendLine("0xF = QLMP: Test the case when service request time out");
				stringBuilder.AppendLine("0x10 = QLMP: Test the case when service response time out");
				stringBuilder.AppendLine("0x11 = QLMP: Test the case when auth request time out");
				stringBuilder.AppendLine("0x12 = QLMP: Test the case when auth response time out");
				stringBuilder.AppendLine("0x13 = QLMP: Test the case when authentication failed for master");
				stringBuilder.AppendLine("0x14 = QLMP: Test the case when authentication failed for slave");
				stringBuilder.AppendLine("0x15 = QLMP: Test the case when encryption using debug key (only for simple pairing)");
				stringBuilder.AppendLine("0x16 = QLMP: Test the case when auto authentication enabled.(only for legacy authentication");
				return stringBuilder.ToString();
			}
		}

		private const uint _SubOpcode = 16u;

		private uint _Q2qTestMode;

		public uint SubOpcode => 16u;

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

		public Q2qTestModeEnum GetQ2qTestModeAsQ2qTestModeEnum()
		{
			return Q2qTestModeInfo.ValueToQ2qTestMode(_Q2qTestMode);
		}

		public void SetQ2qTestModeAsQ2qTestModeEnum(Q2qTestModeEnum enumItem)
		{
			Q2qTestMode = Q2qTestModeInfo.Q2qTestModeToValue(enumItem);
		}
	}

	private const uint _Opcode = 64536u;

	private Type[] expectedResponseTypes = new Type[2]
	{
		typeof(CommandCompleteForLowerTester),
		typeof(CommandCompleteForNop)
	};

	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 LtQ2qTestInfo(this);
			}
			return info;
		}
	}

	public uint Opcode => 64536u;

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

	public UserFieldsWrapper UserFields => _UserFields;

	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.Q2qTestMode = bitBuilder.RemoveBitsAsUint(8);
		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.Q2qTestMode, 8);
		_PayloadLength = (uint)((bitBuilder.GetNumberOfBits() - numberOfBits - 8) / 8);
		if ((bitBuilder.GetNumberOfBits() - numberOfBits - 8) % 8 != 0)
		{
			_PayloadLength++;
		}
		bitBuilder.ChangeBitsAsUint(numberOfBits, _PayloadLength, 8);
		return bitBuilder.ToString();
	}
}
