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

namespace QCRPG.TSL.BT.Packets;

public class QllAcoSwitchRsp : PacketBase
{
	public class UserFieldsWrapper
	{
		public enum LogIdEnum
		{
			OTA_QLL_CTRL_RX_PDU,
			OTA_QLL_CTRL_TX_PDU,
			InvalidLogIdValue
		}

		public static class LogIdInfo
		{
			public static LogIdEnum ValueToLogId(uint value)
			{
				return value switch
				{
					772u => LogIdEnum.OTA_QLL_CTRL_RX_PDU, 
					773u => LogIdEnum.OTA_QLL_CTRL_TX_PDU, 
					_ => LogIdEnum.InvalidLogIdValue, 
				};
			}

			public static uint LogIdToValue(LogIdEnum enumItem)
			{
				return enumItem switch
				{
					LogIdEnum.OTA_QLL_CTRL_RX_PDU => 772u, 
					LogIdEnum.OTA_QLL_CTRL_TX_PDU => 773u, 
					_ => uint.MaxValue, 
				};
			}

			public static string LogIdToString(LogIdEnum enumItem)
			{
				return enumItem switch
				{
					LogIdEnum.OTA_QLL_CTRL_RX_PDU => "OTA_QLL_CTRL_RX_PDU", 
					LogIdEnum.OTA_QLL_CTRL_TX_PDU => "OTA_QLL_CTRL_TX_PDU", 
					_ => "Invalid LogId Value", 
				};
			}

			public static string LogIdToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x304 = OTA_QLL_CTRL_RX_PDU");
				stringBuilder.AppendLine("0x305 = OTA_QLL_CTRL_TX_PDU");
				return stringBuilder.ToString();
			}
		}

		public enum ChannelEnum
		{
			Link_Layer_Master,
			Link_Layer_Slave,
			InvalidChannelValue
		}

		public static class ChannelInfo
		{
			public static ChannelEnum ValueToChannel(uint value)
			{
				return value switch
				{
					2u => ChannelEnum.Link_Layer_Master, 
					3u => ChannelEnum.Link_Layer_Slave, 
					_ => ChannelEnum.InvalidChannelValue, 
				};
			}

			public static uint ChannelToValue(ChannelEnum enumItem)
			{
				return enumItem switch
				{
					ChannelEnum.Link_Layer_Master => 2u, 
					ChannelEnum.Link_Layer_Slave => 3u, 
					_ => uint.MaxValue, 
				};
			}

			public static string ChannelToString(ChannelEnum enumItem)
			{
				return enumItem switch
				{
					ChannelEnum.Link_Layer_Master => "Link_Layer_Master", 
					ChannelEnum.Link_Layer_Slave => "Link_Layer_Slave", 
					_ => "Invalid Channel Value", 
				};
			}

			public static string ChannelToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x2 = Link_Layer_Master");
				stringBuilder.AppendLine("0x3 = Link_Layer_Slave");
				return stringBuilder.ToString();
			}
		}

		public enum OpcodeEnum
		{
			QLL_ACO_SWITCH_RSP,
			InvalidOpcodeValue
		}

		public static class OpcodeInfo
		{
			public static OpcodeEnum ValueToOpcode(uint value)
			{
				if (value == 173)
				{
					return OpcodeEnum.QLL_ACO_SWITCH_RSP;
				}
				return OpcodeEnum.InvalidOpcodeValue;
			}

			public static uint OpcodeToValue(OpcodeEnum enumItem)
			{
				if (enumItem == OpcodeEnum.QLL_ACO_SWITCH_RSP)
				{
					return 173u;
				}
				return uint.MaxValue;
			}

			public static string OpcodeToString(OpcodeEnum enumItem)
			{
				if (enumItem == OpcodeEnum.QLL_ACO_SWITCH_RSP)
				{
					return "QLL_ACO_SWITCH_RSP";
				}
				return "Invalid Opcode Value";
			}

			public static string OpcodeToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0xAD = QLL_ACO_SWITCH_RSP");
				return stringBuilder.ToString();
			}
		}

		private const uint _Opcode = 173u;

		private uint _SeqNum;

		private uint _LogsLostDrop;

		private uint _ProdId;

		private uint _LogId;

		private uint _LogFormatLevel;

		private uint _Timestamp;

		private uint _Handle;

		private uint _PduLength;

		private uint _Channel;

		private uint _EventCounter;

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

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

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

		public uint LogId
		{
			get
			{
				return _LogId;
			}
			set
			{
				if (value > 65535)
				{
					throw new Exception("Maximum possible value for LogId is 0xFFFF");
				}
				if (LogIdInfo.ValueToLogId(value) == LogIdEnum.InvalidLogIdValue)
				{
					throw new Exception("Invalid LogId value");
				}
				_LogId = value;
			}
		}

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

		public uint Timestamp
		{
			get
			{
				return _Timestamp;
			}
			set
			{
				_Timestamp = value;
			}
		}

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

		public uint PduLength
		{
			get
			{
				return _PduLength;
			}
			set
			{
				if (value > 255)
				{
					throw new Exception("Maximum possible value for PduLength is 0xFF");
				}
				_PduLength = 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 Opcode => 173u;

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

		public LogIdEnum GetLogIdAsLogIdEnum()
		{
			return LogIdInfo.ValueToLogId(_LogId);
		}

		public void SetLogIdAsLogIdEnum(LogIdEnum enumItem)
		{
			LogId = LogIdInfo.LogIdToValue(enumItem);
		}

		public ChannelEnum GetChannelAsChannelEnum()
		{
			return ChannelInfo.ValueToChannel(_Channel);
		}

		public void SetChannelAsChannelEnum(ChannelEnum enumItem)
		{
			Channel = ChannelInfo.ChannelToValue(enumItem);
		}

		public OpcodeEnum GetOpcodeAsOpcodeEnum()
		{
			return OpcodeInfo.ValueToOpcode(173u);
		}
	}

	private Type[] expectedResponseTypes = new Type[0];

	private PacketInfoBase info;

	private uint _AclheaderSeqnumPadding;

	private uint _LogformatlevelTimestampPadding;

	private uint _LogLength;

	private uint _Reserved1;

	public UserFieldsWrapper _UserFields = new UserFieldsWrapper();

	public override PacketType Type => PacketType.EnhancedLog;

	public override Type[] ExpectedResponseTypes => expectedResponseTypes;

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

	public uint AclheaderSeqnumPadding
	{
		get
		{
			return _AclheaderSeqnumPadding;
		}
		set
		{
			if (value > 16777215)
			{
				throw new Exception("Maximum possible value for AclheaderSeqnumPadding is 0xFFFFFF");
			}
			_AclheaderSeqnumPadding = value;
		}
	}

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

	public uint LogLength
	{
		get
		{
			ToBitString();
			return _LogLength;
		}
	}

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

	public UserFieldsWrapper UserFields => _UserFields;

	protected override bool FromBitBuilder(ref BitBuilder bitBuilder)
	{
		AclheaderSeqnumPadding = bitBuilder.RemoveBitsAsUint(24);
		UserFields.SeqNum = bitBuilder.RemoveBitsAsUint(8);
		UserFields.LogsLostDrop = bitBuilder.RemoveBitsAsUint(8);
		UserFields.ProdId = bitBuilder.RemoveBitsAsUint(8);
		UserFields.LogId = bitBuilder.RemoveBitsAsUintLittleEndian(16);
		UserFields.LogFormatLevel = bitBuilder.RemoveBitsAsUint(8);
		LogformatlevelTimestampPadding = bitBuilder.RemoveBitsAsUint(8);
		UserFields.Timestamp = bitBuilder.RemoveBitsAsUintLittleEndian(32);
		_LogLength = bitBuilder.RemoveBitsAsUintLittleEndian(16);
		int numberOfBits = bitBuilder.GetNumberOfBits();
		if (numberOfBits > _LogLength * 8 + 7)
		{
			return false;
		}
		if (numberOfBits < _LogLength * 8)
		{
			return false;
		}
		UserFields.Handle = bitBuilder.RemoveBitsAsUint(8);
		Reserved1 = bitBuilder.RemoveBitsAsUint(16);
		UserFields.PduLength = bitBuilder.RemoveBitsAsUint(8);
		UserFields.Channel = bitBuilder.RemoveBitsAsUint(8);
		if (bitBuilder.RemoveBitsAsUint(8) != UserFields.Opcode)
		{
			return false;
		}
		UserFields.EventCounter = bitBuilder.RemoveBitsAsUintLittleEndian(16);
		if (bitBuilder.GetNumberOfBits() > 7)
		{
			return false;
		}
		return true;
	}

	public override string ToBitString()
	{
		BitBuilder bitBuilder = new BitBuilder();
		bitBuilder.AddBitsAsUint(AclheaderSeqnumPadding, 24);
		bitBuilder.AddBitsAsUint(UserFields.SeqNum, 8);
		bitBuilder.AddBitsAsUint(UserFields.LogsLostDrop, 8);
		bitBuilder.AddBitsAsUint(UserFields.ProdId, 8);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.LogId, 16);
		bitBuilder.AddBitsAsUint(UserFields.LogFormatLevel, 8);
		bitBuilder.AddBitsAsUint(LogformatlevelTimestampPadding, 8);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.Timestamp, 32);
		int numberOfBits = bitBuilder.GetNumberOfBits();
		bitBuilder.AddBitsAsUintLittleEndian(0u, 16);
		bitBuilder.AddBitsAsUint(UserFields.Handle, 8);
		bitBuilder.AddBitsAsUint(Reserved1, 16);
		bitBuilder.AddBitsAsUint(UserFields.PduLength, 8);
		bitBuilder.AddBitsAsUint(UserFields.Channel, 8);
		bitBuilder.AddBitsAsUint(UserFields.Opcode, 8);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.EventCounter, 16);
		_LogLength = (uint)((bitBuilder.GetNumberOfBits() - numberOfBits - 16) / 8);
		if ((bitBuilder.GetNumberOfBits() - numberOfBits - 16) % 8 != 0)
		{
			_LogLength++;
		}
		bitBuilder.ChangeBitsAsUintLittleEndian(numberOfBits, _LogLength, 16);
		return bitBuilder.ToString();
	}
}
