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

namespace QCRPG.TSL.BT.Packets;

public class SlcLogIdTxVerbose : PacketBase
{
	public class UserFieldsWrapper
	{
		public enum LogIdEnum
		{
			SLC_LOG,
			InvalidLogIdValue
		}

		public static class LogIdInfo
		{
			public static LogIdEnum ValueToLogId(uint value)
			{
				if (value == 0)
				{
					return LogIdEnum.SLC_LOG;
				}
				return LogIdEnum.InvalidLogIdValue;
			}

			public static uint LogIdToValue(LogIdEnum enumItem)
			{
				if (enumItem == LogIdEnum.SLC_LOG)
				{
					return 0u;
				}
				return uint.MaxValue;
			}

			public static string LogIdToString(LogIdEnum enumItem)
			{
				if (enumItem == LogIdEnum.SLC_LOG)
				{
					return "SLC_LOG";
				}
				return "Invalid LogId Value";
			}

			public static string LogIdToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = SLC_LOG");
				return stringBuilder.ToString();
			}
		}

		public enum SlcLogIdEnum
		{
			TX,
			InvalidSlcLogIdValue
		}

		public static class SlcLogIdInfo
		{
			public static SlcLogIdEnum ValueToSlcLogId(uint value)
			{
				if (value == 16)
				{
					return SlcLogIdEnum.TX;
				}
				return SlcLogIdEnum.InvalidSlcLogIdValue;
			}

			public static uint SlcLogIdToValue(SlcLogIdEnum enumItem)
			{
				if (enumItem == SlcLogIdEnum.TX)
				{
					return 16u;
				}
				return uint.MaxValue;
			}

			public static string SlcLogIdToString(SlcLogIdEnum enumItem)
			{
				if (enumItem == SlcLogIdEnum.TX)
				{
					return "TX";
				}
				return "Invalid SlcLogId Value";
			}

			public static string SlcLogIdToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x10 = TX");
				return stringBuilder.ToString();
			}
		}

		public enum L2capflowEnum
		{
			OFF,
			ON,
			InvalidL2capflowValue
		}

		public static class L2capflowInfo
		{
			public static L2capflowEnum ValueToL2capflow(uint value)
			{
				return value switch
				{
					0u => L2capflowEnum.OFF, 
					1u => L2capflowEnum.ON, 
					_ => L2capflowEnum.InvalidL2capflowValue, 
				};
			}

			public static uint L2capflowToValue(L2capflowEnum enumItem)
			{
				return enumItem switch
				{
					L2capflowEnum.OFF => 0u, 
					L2capflowEnum.ON => 1u, 
					_ => uint.MaxValue, 
				};
			}

			public static string L2capflowToString(L2capflowEnum enumItem)
			{
				return enumItem switch
				{
					L2capflowEnum.OFF => "OFF", 
					L2capflowEnum.ON => "ON", 
					_ => "Invalid L2capflow Value", 
				};
			}

			public static string L2capflowToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = OFF");
				stringBuilder.AppendLine("0x1 = ON");
				return stringBuilder.ToString();
			}
		}

		public enum ArqnEnum
		{
			NACK,
			ACK,
			InvalidArqnValue
		}

		public static class ArqnInfo
		{
			public static ArqnEnum ValueToArqn(uint value)
			{
				return value switch
				{
					0u => ArqnEnum.NACK, 
					1u => ArqnEnum.ACK, 
					_ => ArqnEnum.InvalidArqnValue, 
				};
			}

			public static uint ArqnToValue(ArqnEnum enumItem)
			{
				return enumItem switch
				{
					ArqnEnum.NACK => 0u, 
					ArqnEnum.ACK => 1u, 
					_ => uint.MaxValue, 
				};
			}

			public static string ArqnToString(ArqnEnum enumItem)
			{
				return enumItem switch
				{
					ArqnEnum.NACK => "NACK", 
					ArqnEnum.ACK => "ACK", 
					_ => "Invalid Arqn Value", 
				};
			}

			public static string ArqnToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = NACK");
				stringBuilder.AppendLine("0x1 = ACK");
				return stringBuilder.ToString();
			}
		}

		public enum PacketFlowEnum
		{
			OFF,
			ON,
			InvalidPacketFlowValue
		}

		public static class PacketFlowInfo
		{
			public static PacketFlowEnum ValueToPacketFlow(uint value)
			{
				return value switch
				{
					0u => PacketFlowEnum.OFF, 
					1u => PacketFlowEnum.ON, 
					_ => PacketFlowEnum.InvalidPacketFlowValue, 
				};
			}

			public static uint PacketFlowToValue(PacketFlowEnum enumItem)
			{
				return enumItem switch
				{
					PacketFlowEnum.OFF => 0u, 
					PacketFlowEnum.ON => 1u, 
					_ => uint.MaxValue, 
				};
			}

			public static string PacketFlowToString(PacketFlowEnum enumItem)
			{
				return enumItem switch
				{
					PacketFlowEnum.OFF => "OFF", 
					PacketFlowEnum.ON => "ON", 
					_ => "Invalid PacketFlow Value", 
				};
			}

			public static string PacketFlowToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = OFF");
				stringBuilder.AppendLine("0x1 = ON");
				return stringBuilder.ToString();
			}
		}

		private const uint _SlcLogId = 16u;

		private uint _SeqNum;

		private uint _LogsLostDrop;

		private uint _ProdId;

		private uint _LogId;

		private uint _LogFormatLevel;

		private uint _Timestamp;

		private uint _SlcFmtSpecifier;

		private uint _LtAddress;

		private uint _PacketType;

		private uint _L2capflow;

		private uint _LateCommand;

		private uint _CxmDenial;

		private uint _CxmAbort;

		private uint _SlcSeqNum;

		private uint _Arqn;

		private uint _PacketFlow;

		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 SlcFmtSpecifier
		{
			get
			{
				return _SlcFmtSpecifier;
			}
			set
			{
				if (value > 3)
				{
					throw new Exception("Maximum possible value for SlcFmtSpecifier is 0x3");
				}
				_SlcFmtSpecifier = value;
			}
		}

		public uint SlcLogId => 16u;

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

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

		public uint L2capflow
		{
			get
			{
				return _L2capflow;
			}
			set
			{
				if (value > 3)
				{
					throw new Exception("Maximum possible value for L2capflow is 0x3");
				}
				_L2capflow = value;
			}
		}

		public uint LateCommand
		{
			get
			{
				return _LateCommand;
			}
			set
			{
				if (value > 1)
				{
					throw new Exception("Maximum possible value for LateCommand is 0x1");
				}
				_LateCommand = value;
			}
		}

		public uint CxmDenial
		{
			get
			{
				return _CxmDenial;
			}
			set
			{
				if (value > 1)
				{
					throw new Exception("Maximum possible value for CxmDenial is 0x1");
				}
				_CxmDenial = value;
			}
		}

		public uint CxmAbort
		{
			get
			{
				return _CxmAbort;
			}
			set
			{
				if (value > 1)
				{
					throw new Exception("Maximum possible value for CxmAbort is 0x1");
				}
				_CxmAbort = value;
			}
		}

		public uint SlcSeqNum
		{
			get
			{
				return _SlcSeqNum;
			}
			set
			{
				if (value > 1)
				{
					throw new Exception("Maximum possible value for SlcSeqNum is 0x1");
				}
				_SlcSeqNum = value;
			}
		}

		public uint Arqn
		{
			get
			{
				return _Arqn;
			}
			set
			{
				if (value > 1)
				{
					throw new Exception("Maximum possible value for Arqn is 0x1");
				}
				_Arqn = value;
			}
		}

		public uint PacketFlow
		{
			get
			{
				return _PacketFlow;
			}
			set
			{
				if (value > 1)
				{
					throw new Exception("Maximum possible value for PacketFlow is 0x1");
				}
				_PacketFlow = value;
			}
		}

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

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

		public SlcLogIdEnum GetSlcLogIdAsSlcLogIdEnum()
		{
			return SlcLogIdInfo.ValueToSlcLogId(16u);
		}

		public L2capflowEnum GetL2capflowAsL2capflowEnum()
		{
			return L2capflowInfo.ValueToL2capflow(_L2capflow);
		}

		public void SetL2capflowAsL2capflowEnum(L2capflowEnum enumItem)
		{
			L2capflow = L2capflowInfo.L2capflowToValue(enumItem);
		}

		public ArqnEnum GetArqnAsArqnEnum()
		{
			return ArqnInfo.ValueToArqn(_Arqn);
		}

		public void SetArqnAsArqnEnum(ArqnEnum enumItem)
		{
			Arqn = ArqnInfo.ArqnToValue(enumItem);
		}

		public PacketFlowEnum GetPacketFlowAsPacketFlowEnum()
		{
			return PacketFlowInfo.ValueToPacketFlow(_PacketFlow);
		}

		public void SetPacketFlowAsPacketFlowEnum(PacketFlowEnum enumItem)
		{
			PacketFlow = PacketFlowInfo.PacketFlowToValue(enumItem);
		}
	}

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

	private PacketInfoBase info;

	private uint _AclheaderSeqnumPadding;

	private uint _LogformatlevelTimestampPadding;

	private uint _LogLength;

	private uint _Rfu;

	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 SlcLogIdTxVerboseInfo(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 Rfu
	{
		get
		{
			return _Rfu;
		}
		set
		{
			if (value > 255)
			{
				throw new Exception("Maximum possible value for Rfu is 0xFF");
			}
			_Rfu = 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.SlcFmtSpecifier = bitBuilder.RemoveBitsAsUint(2);
		if (bitBuilder.RemoveBitsAsUint(6) != UserFields.SlcLogId)
		{
			return false;
		}
		UserFields.LtAddress = bitBuilder.RemoveBitsAsUint(8);
		UserFields.PacketType = bitBuilder.RemoveBitsAsUint(8);
		UserFields.L2capflow = bitBuilder.RemoveBitsAsUint(2);
		UserFields.LateCommand = bitBuilder.RemoveBitsAsUint(1);
		UserFields.CxmDenial = bitBuilder.RemoveBitsAsUint(1);
		UserFields.CxmAbort = bitBuilder.RemoveBitsAsUint(1);
		UserFields.SlcSeqNum = bitBuilder.RemoveBitsAsUint(1);
		UserFields.Arqn = bitBuilder.RemoveBitsAsUint(1);
		UserFields.PacketFlow = bitBuilder.RemoveBitsAsUint(1);
		Rfu = bitBuilder.RemoveBitsAsUint(8);
		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.SlcFmtSpecifier, 2);
		bitBuilder.AddBitsAsUint(UserFields.SlcLogId, 6);
		bitBuilder.AddBitsAsUint(UserFields.LtAddress, 8);
		bitBuilder.AddBitsAsUint(UserFields.PacketType, 8);
		bitBuilder.AddBitsAsUint(UserFields.L2capflow, 2);
		bitBuilder.AddBitsAsUint(UserFields.LateCommand, 1);
		bitBuilder.AddBitsAsUint(UserFields.CxmDenial, 1);
		bitBuilder.AddBitsAsUint(UserFields.CxmAbort, 1);
		bitBuilder.AddBitsAsUint(UserFields.SlcSeqNum, 1);
		bitBuilder.AddBitsAsUint(UserFields.Arqn, 1);
		bitBuilder.AddBitsAsUint(UserFields.PacketFlow, 1);
		bitBuilder.AddBitsAsUint(Rfu, 8);
		_LogLength = (uint)((bitBuilder.GetNumberOfBits() - numberOfBits - 16) / 8);
		if ((bitBuilder.GetNumberOfBits() - numberOfBits - 16) % 8 != 0)
		{
			_LogLength++;
		}
		bitBuilder.ChangeBitsAsUintLittleEndian(numberOfBits, _LogLength, 16);
		return bitBuilder.ToString();
	}
}
