using System;
using System.Collections.Generic;
using System.Text;
using QCRPG.Framework;

namespace QCRPG.TSL.BT.Packets;

public class SetConnectionlessSlaveBroadcastReceive : PacketBase
{
	public class UserFieldsWrapper
	{
		public enum EnableEnum
		{
			Disabled,
			Enabled,
			RESERVED_FOR_FUTURE_USE,
			InvalidEnableValue
		}

		public static class EnableInfo
		{
			public static EnableEnum ValueToEnable(uint value)
			{
				switch (value)
				{
				case 0u:
					return EnableEnum.Disabled;
				case 1u:
					return EnableEnum.Enabled;
				default:
					if (value >= 2 && value <= 255)
					{
						return EnableEnum.RESERVED_FOR_FUTURE_USE;
					}
					return EnableEnum.InvalidEnableValue;
				}
			}

			public static uint EnableToValue(EnableEnum enumItem)
			{
				return enumItem switch
				{
					EnableEnum.Disabled => 0u, 
					EnableEnum.Enabled => 1u, 
					EnableEnum.RESERVED_FOR_FUTURE_USE => 2u, 
					_ => uint.MaxValue, 
				};
			}

			public static string EnableToString(EnableEnum enumItem)
			{
				return enumItem switch
				{
					EnableEnum.Disabled => "Disabled", 
					EnableEnum.Enabled => "Enabled", 
					EnableEnum.RESERVED_FOR_FUTURE_USE => "Reserved for future use", 
					_ => "Invalid Enable Value", 
				};
			}

			public static string EnableToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = Disabled");
				stringBuilder.AppendLine("0x1 = Enabled");
				stringBuilder.AppendLine("0x2-0xFF = Reserved for future use");
				return stringBuilder.ToString();
			}
		}

		public enum LtAddrEnum
		{
			LT_ADDR_OF_THE_CONNECTIONLESS_SLAVE_BROADCAST_MSG,
			RESERVED_FOR_FUTURE_USE,
			InvalidLtAddrValue
		}

		public static class LtAddrInfo
		{
			public static LtAddrEnum ValueToLtAddr(uint value)
			{
				if (value >= 1 && value <= 7)
				{
					return LtAddrEnum.LT_ADDR_OF_THE_CONNECTIONLESS_SLAVE_BROADCAST_MSG;
				}
				if (value == 0)
				{
					return LtAddrEnum.RESERVED_FOR_FUTURE_USE;
				}
				if (value >= 8 && value <= 255)
				{
					return LtAddrEnum.RESERVED_FOR_FUTURE_USE;
				}
				return LtAddrEnum.InvalidLtAddrValue;
			}

			public static uint LtAddrToValue(LtAddrEnum enumItem)
			{
				switch (enumItem)
				{
				case LtAddrEnum.LT_ADDR_OF_THE_CONNECTIONLESS_SLAVE_BROADCAST_MSG:
					return 1u;
				case LtAddrEnum.RESERVED_FOR_FUTURE_USE:
					return 0u;
				default:
					if (enumItem == LtAddrEnum.RESERVED_FOR_FUTURE_USE)
					{
						return 8u;
					}
					return uint.MaxValue;
				}
			}

			public static string LtAddrToString(LtAddrEnum enumItem)
			{
				switch (enumItem)
				{
				case LtAddrEnum.LT_ADDR_OF_THE_CONNECTIONLESS_SLAVE_BROADCAST_MSG:
					return "LT_ADDR to use for receiving Connectionless Slave Broadcast messages";
				case LtAddrEnum.RESERVED_FOR_FUTURE_USE:
					return "Reserved for future use";
				default:
					if (enumItem == LtAddrEnum.RESERVED_FOR_FUTURE_USE)
					{
						return "Reserved for future use";
					}
					return "Invalid LtAddr Value";
				}
			}

			public static string LtAddrToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x1-0x7 = LT_ADDR to use for receiving Connectionless Slave Broadcast messages");
				stringBuilder.AppendLine("0x0 = Reserved for future use");
				stringBuilder.AppendLine("0x8-0xFF = Reserved for future use");
				return stringBuilder.ToString();
			}
		}

		private uint _Enable;

		private ulong _BdAddr;

		private uint _LtAddr;

		private uint _Interval = 2u;

		private uint _ClockOffset;

		private uint _NextConnectionlessSlaveBroadcastClock;

		private uint _CsbSupervisionto = 2u;

		private uint _RemoteTimingAccuracy;

		private uint _Skip;

		private uint _PacketType;

		private List<uint> _AfhChannelMapList = new List<uint>(new uint[10]);

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

		public ulong BdAddr
		{
			get
			{
				return _BdAddr;
			}
			set
			{
				_BdAddr = value;
			}
		}

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

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

		public uint ClockOffset
		{
			get
			{
				return _ClockOffset;
			}
			set
			{
				_ClockOffset = value;
			}
		}

		public uint NextConnectionlessSlaveBroadcastClock
		{
			get
			{
				return _NextConnectionlessSlaveBroadcastClock;
			}
			set
			{
				_NextConnectionlessSlaveBroadcastClock = value;
			}
		}

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

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

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

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

		public List<uint> AfhChannelMapList => _AfhChannelMapList;

		public EnableEnum GetEnableAsEnableEnum()
		{
			return EnableInfo.ValueToEnable(_Enable);
		}

		public void SetEnableAsEnableEnum(EnableEnum enumItem)
		{
			Enable = EnableInfo.EnableToValue(enumItem);
		}

		public LtAddrEnum GetLtAddrAsLtAddrEnum()
		{
			return LtAddrInfo.ValueToLtAddr(_LtAddr);
		}

		public void SetLtAddrAsLtAddrEnum(LtAddrEnum enumItem)
		{
			LtAddr = LtAddrInfo.LtAddrToValue(enumItem);
		}

		public AclPacketTypeEnumCollection GetPacketTypeAsAclPacketTypeEnumCollection()
		{
			return AclPacketTypeInfo.ValueToAclPacketType(_PacketType);
		}

		public void SetPacketTypeAsAclPacketTypeEnumCollection(AclPacketTypeEnumCollection enumCollection)
		{
			PacketType = AclPacketTypeInfo.AclPacketTypeToValue(enumCollection);
		}
	}

	private const uint _Opcode = 1090u;

	private Type[] expectedResponseTypes = new Type[2]
	{
		typeof(CommandCompleteForSetConnectionlessSlaveBroadcastReceive),
		typeof(ConnectionlessSlaveBroadcastTimeout)
	};

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

	public uint Opcode => 1090u;

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

	public UserFieldsWrapper UserFields => _UserFields;

	public override void SetDefaultValues()
	{
		UserFields.Enable = 0u;
		UserFields.LtAddr = 1u;
		UserFields.Interval = 2u;
		UserFields.CsbSupervisionto = 2u;
		UserFields.PacketType = 1u;
	}

	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;
		}
		UserFields.Enable = bitBuilder.RemoveBitsAsUint(8);
		UserFields.BdAddr = bitBuilder.RemoveBitsAsUlongLittleEndian(48);
		UserFields.LtAddr = bitBuilder.RemoveBitsAsUint(8);
		UserFields.Interval = bitBuilder.RemoveBitsAsUintLittleEndian(16);
		UserFields.ClockOffset = bitBuilder.RemoveBitsAsUintLittleEndian(32);
		UserFields.NextConnectionlessSlaveBroadcastClock = bitBuilder.RemoveBitsAsUintLittleEndian(32);
		UserFields.CsbSupervisionto = bitBuilder.RemoveBitsAsUintLittleEndian(16);
		UserFields.RemoteTimingAccuracy = bitBuilder.RemoveBitsAsUint(8);
		UserFields.Skip = bitBuilder.RemoveBitsAsUint(8);
		UserFields.PacketType = bitBuilder.RemoveBitsAsUintLittleEndian(16);
		for (int num = UserFields.AfhChannelMapList.Count - 1; num >= 0; num--)
		{
			UserFields.AfhChannelMapList[num] = 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.Enable, 8);
		bitBuilder.AddBitsAsUlongLittleEndian(UserFields.BdAddr, 48);
		bitBuilder.AddBitsAsUint(UserFields.LtAddr, 8);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.Interval, 16);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.ClockOffset, 32);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.NextConnectionlessSlaveBroadcastClock, 32);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.CsbSupervisionto, 16);
		bitBuilder.AddBitsAsUint(UserFields.RemoteTimingAccuracy, 8);
		bitBuilder.AddBitsAsUint(UserFields.Skip, 8);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.PacketType, 16);
		for (int num = UserFields.AfhChannelMapList.Count - 1; num >= 0; num--)
		{
			if (UserFields.AfhChannelMapList[num] > 255)
			{
				throw new Exception("UserFields.AfhChannelMapList[i] is > 0xFF");
			}
			bitBuilder.AddBitsAsUint(UserFields.AfhChannelMapList[num], 8);
		}
		_PayloadLength = (uint)((bitBuilder.GetNumberOfBits() - numberOfBits - 8) / 8);
		if ((bitBuilder.GetNumberOfBits() - numberOfBits - 8) % 8 != 0)
		{
			_PayloadLength++;
		}
		bitBuilder.ChangeBitsAsUint(numberOfBits, _PayloadLength, 8);
		return bitBuilder.ToString();
	}

	public override List<string> GetWarnings()
	{
		List<string> list = new List<string>();
		if (UserFields.Interval < 2)
		{
			list.Add("Minimum allowed value for Interval is 0x2");
		}
		if (UserFields.Interval > 65534)
		{
			list.Add("Maximum allowed value for Interval is 0xFFFE");
		}
		if (UserFields.CsbSupervisionto < 2)
		{
			list.Add("Minimum allowed value for CSB_supervisionTO is 0x2");
		}
		if (UserFields.CsbSupervisionto > 65534)
		{
			list.Add("Maximum allowed value for CSB_supervisionTO is 0xFFFE");
		}
		return list;
	}
}
