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

namespace QCRPG.TSL.BT.Packets;

public class SlcLogIdPollmgrResultType : 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 TypeEnum
		{
			ACL,
			ACL_INTERACTIVE,
			A2DP,
			BROADCAST,
			PAGE,
			INQUIRY,
			LE_ADV_FULL,
			LE_SCAN_FULL,
			LE_INITIATE_FULL,
			InvalidTypeValue
		}

		public static class TypeInfo
		{
			public static TypeEnum ValueToType(uint value)
			{
				return value switch
				{
					0u => TypeEnum.ACL, 
					1u => TypeEnum.ACL_INTERACTIVE, 
					2u => TypeEnum.A2DP, 
					3u => TypeEnum.BROADCAST, 
					4u => TypeEnum.PAGE, 
					5u => TypeEnum.INQUIRY, 
					32u => TypeEnum.LE_ADV_FULL, 
					33u => TypeEnum.LE_SCAN_FULL, 
					34u => TypeEnum.LE_INITIATE_FULL, 
					_ => TypeEnum.InvalidTypeValue, 
				};
			}

			public static uint TypeToValue(TypeEnum enumItem)
			{
				return enumItem switch
				{
					TypeEnum.ACL => 0u, 
					TypeEnum.ACL_INTERACTIVE => 1u, 
					TypeEnum.A2DP => 2u, 
					TypeEnum.BROADCAST => 3u, 
					TypeEnum.PAGE => 4u, 
					TypeEnum.INQUIRY => 5u, 
					TypeEnum.LE_ADV_FULL => 32u, 
					TypeEnum.LE_SCAN_FULL => 33u, 
					TypeEnum.LE_INITIATE_FULL => 34u, 
					_ => uint.MaxValue, 
				};
			}

			public static string TypeToString(TypeEnum enumItem)
			{
				return enumItem switch
				{
					TypeEnum.ACL => "ACL", 
					TypeEnum.ACL_INTERACTIVE => "ACL_INTERACTIVE", 
					TypeEnum.A2DP => "A2DP", 
					TypeEnum.BROADCAST => "BROADCAST", 
					TypeEnum.PAGE => "PAGE", 
					TypeEnum.INQUIRY => "INQUIRY", 
					TypeEnum.LE_ADV_FULL => "LE_ADV_FULL", 
					TypeEnum.LE_SCAN_FULL => "LE_SCAN_FULL", 
					TypeEnum.LE_INITIATE_FULL => "LE_INITIATE_FULL", 
					_ => "Invalid Type Value", 
				};
			}

			public static string TypeToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = ACL");
				stringBuilder.AppendLine("0x1 = ACL_INTERACTIVE");
				stringBuilder.AppendLine("0x2 = A2DP");
				stringBuilder.AppendLine("0x3 = BROADCAST");
				stringBuilder.AppendLine("0x4 = PAGE");
				stringBuilder.AppendLine("0x5 = INQUIRY");
				stringBuilder.AppendLine("0x20 = LE_ADV_FULL");
				stringBuilder.AppendLine("0x21 = LE_SCAN_FULL");
				stringBuilder.AppendLine("0x22 = LE_INITIATE_FULL");
				return stringBuilder.ToString();
			}
		}

		private const uint _SlcLogId = 23u;

		private uint _SeqNum;

		private uint _LogsLostDrop;

		private uint _ProdId;

		private uint _LogId;

		private uint _LogFormatLevel;

		private uint _Timestamp;

		private uint _SlcFmtSpecifier;

		private uint _Type;

		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 => 23u;

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

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

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

		public TypeEnum GetTypeAsTypeEnum()
		{
			return TypeInfo.ValueToType(_Type);
		}

		public void SetTypeAsTypeEnum(TypeEnum enumItem)
		{
			Type = TypeInfo.TypeToValue(enumItem);
		}
	}

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

	private PacketInfoBase info;

	private uint _AclheaderSeqnumPadding;

	private uint _LogformatlevelTimestampPadding;

	private uint _LogLength;

	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 SlcLogIdPollmgrResultTypeInfo(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 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.Type = 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.Type, 8);
		_LogLength = (uint)((bitBuilder.GetNumberOfBits() - numberOfBits - 16) / 8);
		if ((bitBuilder.GetNumberOfBits() - numberOfBits - 16) % 8 != 0)
		{
			_LogLength++;
		}
		bitBuilder.ChangeBitsAsUintLittleEndian(numberOfBits, _LogLength, 16);
		return bitBuilder.ToString();
	}
}
