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

namespace QCRPG.TSL.BT.Packets;

public class VsWsim : PacketBase
{
	public class UserFieldsWrapper
	{
		public enum CommandNumberEnum
		{
			WSIM_BUS_SYNC,
			WSIM_SYS_WAKE,
			WSIM_SYS_SLEEP,
			WSIM_READ_REMOTE_STATUS,
			WSIM_REMOTE_RESET,
			WSIM_ENABLE_BT_GPM,
			WSIM_SET_CONT_NACK,
			WSIM_CLR_CONT_NACK,
			WSIM_SEND_GPM,
			WSIM_READ_GPM_FIFO,
			WSIM_SEND_SCHD_INFO,
			WSIM_READ_NON_GPM_FIFO,
			WSIM_SEND_LNA_TAKE,
			WSIM_SEND_LNA_TRANS,
			WSIM_SEND_WCI2_SYNC_REQ,
			InvalidCommandNumberValue
		}

		public static class CommandNumberInfo
		{
			public static CommandNumberEnum ValueToCommandNumber(uint value)
			{
				return value switch
				{
					0u => CommandNumberEnum.WSIM_BUS_SYNC, 
					1u => CommandNumberEnum.WSIM_SYS_WAKE, 
					2u => CommandNumberEnum.WSIM_SYS_SLEEP, 
					3u => CommandNumberEnum.WSIM_READ_REMOTE_STATUS, 
					4u => CommandNumberEnum.WSIM_REMOTE_RESET, 
					5u => CommandNumberEnum.WSIM_ENABLE_BT_GPM, 
					6u => CommandNumberEnum.WSIM_SET_CONT_NACK, 
					7u => CommandNumberEnum.WSIM_CLR_CONT_NACK, 
					8u => CommandNumberEnum.WSIM_SEND_GPM, 
					9u => CommandNumberEnum.WSIM_READ_GPM_FIFO, 
					10u => CommandNumberEnum.WSIM_SEND_SCHD_INFO, 
					11u => CommandNumberEnum.WSIM_READ_NON_GPM_FIFO, 
					12u => CommandNumberEnum.WSIM_SEND_LNA_TAKE, 
					13u => CommandNumberEnum.WSIM_SEND_LNA_TRANS, 
					14u => CommandNumberEnum.WSIM_SEND_WCI2_SYNC_REQ, 
					_ => CommandNumberEnum.InvalidCommandNumberValue, 
				};
			}

			public static uint CommandNumberToValue(CommandNumberEnum enumItem)
			{
				return enumItem switch
				{
					CommandNumberEnum.WSIM_BUS_SYNC => 0u, 
					CommandNumberEnum.WSIM_SYS_WAKE => 1u, 
					CommandNumberEnum.WSIM_SYS_SLEEP => 2u, 
					CommandNumberEnum.WSIM_READ_REMOTE_STATUS => 3u, 
					CommandNumberEnum.WSIM_REMOTE_RESET => 4u, 
					CommandNumberEnum.WSIM_ENABLE_BT_GPM => 5u, 
					CommandNumberEnum.WSIM_SET_CONT_NACK => 6u, 
					CommandNumberEnum.WSIM_CLR_CONT_NACK => 7u, 
					CommandNumberEnum.WSIM_SEND_GPM => 8u, 
					CommandNumberEnum.WSIM_READ_GPM_FIFO => 9u, 
					CommandNumberEnum.WSIM_SEND_SCHD_INFO => 10u, 
					CommandNumberEnum.WSIM_READ_NON_GPM_FIFO => 11u, 
					CommandNumberEnum.WSIM_SEND_LNA_TAKE => 12u, 
					CommandNumberEnum.WSIM_SEND_LNA_TRANS => 13u, 
					CommandNumberEnum.WSIM_SEND_WCI2_SYNC_REQ => 14u, 
					_ => uint.MaxValue, 
				};
			}

			public static string CommandNumberToString(CommandNumberEnum enumItem)
			{
				return enumItem switch
				{
					CommandNumberEnum.WSIM_BUS_SYNC => "WSIM_BUS_SYNC", 
					CommandNumberEnum.WSIM_SYS_WAKE => "WSIM_SYS_WAKE", 
					CommandNumberEnum.WSIM_SYS_SLEEP => "WSIM_SYS_SLEEP", 
					CommandNumberEnum.WSIM_READ_REMOTE_STATUS => "WSIM_READ_REMOTE_STATUS", 
					CommandNumberEnum.WSIM_REMOTE_RESET => "WSIM_REMOTE_RESET", 
					CommandNumberEnum.WSIM_ENABLE_BT_GPM => "WSIM_ENABLE_BT_GPM", 
					CommandNumberEnum.WSIM_SET_CONT_NACK => "WSIM_SET_CONT_NACK", 
					CommandNumberEnum.WSIM_CLR_CONT_NACK => "WSIM_CLR_CONT_NACK", 
					CommandNumberEnum.WSIM_SEND_GPM => "WSIM_SEND_GPM", 
					CommandNumberEnum.WSIM_READ_GPM_FIFO => "WSIM_READ_GPM_FIFO", 
					CommandNumberEnum.WSIM_SEND_SCHD_INFO => "WSIM_SEND_SCHD_INFO", 
					CommandNumberEnum.WSIM_READ_NON_GPM_FIFO => "WSIM_READ_NON_GPM_FIFO", 
					CommandNumberEnum.WSIM_SEND_LNA_TAKE => "WSIM_SEND_LNA_TAKE", 
					CommandNumberEnum.WSIM_SEND_LNA_TRANS => "WSIM_SEND_LNA_TRANS", 
					CommandNumberEnum.WSIM_SEND_WCI2_SYNC_REQ => "WSIM_SEND_WCI2_SYNC_REQ", 
					_ => "Invalid CommandNumber Value", 
				};
			}

			public static string CommandNumberToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = WSIM_BUS_SYNC");
				stringBuilder.AppendLine("0x1 = WSIM_SYS_WAKE");
				stringBuilder.AppendLine("0x2 = WSIM_SYS_SLEEP");
				stringBuilder.AppendLine("0x3 = WSIM_READ_REMOTE_STATUS");
				stringBuilder.AppendLine("0x4 = WSIM_REMOTE_RESET");
				stringBuilder.AppendLine("0x5 = WSIM_ENABLE_BT_GPM");
				stringBuilder.AppendLine("0x6 = WSIM_SET_CONT_NACK");
				stringBuilder.AppendLine("0x7 = WSIM_CLR_CONT_NACK");
				stringBuilder.AppendLine("0x8 = WSIM_SEND_GPM");
				stringBuilder.AppendLine("0x9 = WSIM_READ_GPM_FIFO");
				stringBuilder.AppendLine("0xA = WSIM_SEND_SCHD_INFO");
				stringBuilder.AppendLine("0xB = WSIM_READ_NON_GPM_FIFO");
				stringBuilder.AppendLine("0xC = WSIM_SEND_LNA_TAKE");
				stringBuilder.AppendLine("0xD = WSIM_SEND_LNA_TRANS");
				stringBuilder.AppendLine("0xE = WSIM_SEND_WCI2_SYNC_REQ");
				return stringBuilder.ToString();
			}
		}

		private const uint _Subopcode = 62u;

		private uint _CommandNumber;

		public uint Subopcode => 62u;

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

		public CommandNumberEnum GetCommandNumberAsCommandNumberEnum()
		{
			return CommandNumberInfo.ValueToCommandNumber(_CommandNumber);
		}

		public void SetCommandNumberAsCommandNumberEnum(CommandNumberEnum enumItem)
		{
			CommandNumber = CommandNumberInfo.CommandNumberToValue(enumItem);
		}
	}

	private const uint _Opcode = 64524u;

	private Type[] expectedResponseTypes = new Type[2]
	{
		typeof(CommandCompleteForVsWsim),
		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 VsWsimInfo(this);
			}
			return info;
		}
	}

	public uint Opcode => 64524u;

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