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

namespace QCRPG.TSL.BT.Packets;

public class LeExtendedCreateConnection : PacketBase
{
	public class UserFieldsWrapper
	{
		public class InitiatingPhysEnumCollection
		{
			private EnableBitEnum _Le1mPhy;

			private EnableBitEnum _Le2mPhy;

			private EnableBitEnum _LeCodedPhy;

			public EnableBitEnum Le1mPhy
			{
				get
				{
					return _Le1mPhy;
				}
				set
				{
					_Le1mPhy = value;
				}
			}

			public EnableBitEnum Le2mPhy
			{
				get
				{
					return _Le2mPhy;
				}
				set
				{
					_Le2mPhy = value;
				}
			}

			public EnableBitEnum LeCodedPhy
			{
				get
				{
					return _LeCodedPhy;
				}
				set
				{
					_LeCodedPhy = value;
				}
			}
		}

		public static class InitiatingPhysInfo
		{
			public static InitiatingPhysEnumCollection ValueToInitiatingPhys(uint value)
			{
				InitiatingPhysEnumCollection initiatingPhysEnumCollection = new InitiatingPhysEnumCollection();
				initiatingPhysEnumCollection.Le1mPhy = EnableBitInfo.ValueToEnableBit(value & 1u);
				initiatingPhysEnumCollection.Le2mPhy = EnableBitInfo.ValueToEnableBit((value & 2) >> 1);
				initiatingPhysEnumCollection.LeCodedPhy = EnableBitInfo.ValueToEnableBit((value & 4) >> 2);
				return initiatingPhysEnumCollection;
			}

			public static uint InitiatingPhysToValue(InitiatingPhysEnumCollection enumCollection)
			{
				uint num = 0u;
				num |= EnableBitInfo.EnableBitToValue(enumCollection.Le1mPhy);
				num |= EnableBitInfo.EnableBitToValue(enumCollection.Le2mPhy) << 1;
				return num | (EnableBitInfo.EnableBitToValue(enumCollection.LeCodedPhy) << 2);
			}

			public static string InitiatingPhysToString(InitiatingPhysEnumCollection enumCollection)
			{
				string text = "";
				text = text + "LE 1M PHY: " + EnableBitInfo.EnableBitToString(enumCollection.Le1mPhy) + "\r\n";
				text = text + "LE 2M PHY: " + EnableBitInfo.EnableBitToString(enumCollection.Le2mPhy) + "\r\n";
				text = text + "LE Coded PHY: " + EnableBitInfo.EnableBitToString(enumCollection.LeCodedPhy) + "\r\n";
				return text.TrimEnd('\r', '\n');
			}

			public static string InitiatingPhysToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("Bit 0: LE 1M PHY");
				stringBuilder.AppendLine("Bit 1: LE 2M PHY");
				stringBuilder.AppendLine("Bit 2: LE Coded PHY");
				stringBuilder.AppendLine("Bits 7-3: Reserved for future use");
				return stringBuilder.ToString();
			}
		}

		private uint _InitiatingFilterPolicy;

		private uint _OwnAddressType;

		private uint _PeerAddressType;

		private ulong _PeerAddress;

		private uint _InitiatingPhys = 1u;

		private List<ParametersSubField> _ParametersList = new List<ParametersSubField>();

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

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

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

		public ulong PeerAddress
		{
			get
			{
				return _PeerAddress;
			}
			set
			{
				_PeerAddress = value;
			}
		}

		public uint InitiatingPhys
		{
			get
			{
				return _InitiatingPhys;
			}
			set
			{
				if (value > 255)
				{
					throw new Exception("Maximum possible value for InitiatingPhys is 0xFF");
				}
				_InitiatingPhys = value;
				uint num = 0u;
				if (_InitiatingPhys == 1)
				{
					num = 1u;
				}
				else if (_InitiatingPhys == 2)
				{
					num = 1u;
				}
				else if (_InitiatingPhys == 3)
				{
					num = 2u;
				}
				else if (_InitiatingPhys == 4)
				{
					num = 1u;
				}
				else if (_InitiatingPhys == 5)
				{
					num = 2u;
				}
				else if (_InitiatingPhys == 6)
				{
					num = 2u;
				}
				else if (_InitiatingPhys == 7)
				{
					num = 3u;
				}
				while (_ParametersList.Count < num)
				{
					_ParametersList.Add(new ParametersSubField());
				}
				while (_ParametersList.Count > num)
				{
					_ParametersList.RemoveAt(_ParametersList.Count - 1);
				}
			}
		}

		public List<ParametersSubField> ParametersList => _ParametersList;

		public InitiatingFilterPolicyEnum GetInitiatingFilterPolicyAsInitiatingFilterPolicyEnum()
		{
			return InitiatingFilterPolicyInfo.ValueToInitiatingFilterPolicy(_InitiatingFilterPolicy);
		}

		public void SetInitiatingFilterPolicyAsInitiatingFilterPolicyEnum(InitiatingFilterPolicyEnum enumItem)
		{
			InitiatingFilterPolicy = InitiatingFilterPolicyInfo.InitiatingFilterPolicyToValue(enumItem);
		}

		public OwnAddressTypeEnum GetOwnAddressTypeAsOwnAddressTypeEnum()
		{
			return OwnAddressTypeInfo.ValueToOwnAddressType(_OwnAddressType);
		}

		public void SetOwnAddressTypeAsOwnAddressTypeEnum(OwnAddressTypeEnum enumItem)
		{
			OwnAddressType = OwnAddressTypeInfo.OwnAddressTypeToValue(enumItem);
		}

		public PeerResolvableAddressTypeEnum GetPeerAddressTypeAsPeerResolvableAddressTypeEnum()
		{
			return PeerResolvableAddressTypeInfo.ValueToPeerResolvableAddressType(_PeerAddressType);
		}

		public void SetPeerAddressTypeAsPeerResolvableAddressTypeEnum(PeerResolvableAddressTypeEnum enumItem)
		{
			PeerAddressType = PeerResolvableAddressTypeInfo.PeerResolvableAddressTypeToValue(enumItem);
		}

		public InitiatingPhysEnumCollection GetInitiatingPhysAsInitiatingPhysEnumCollection()
		{
			return InitiatingPhysInfo.ValueToInitiatingPhys(_InitiatingPhys);
		}

		public void SetInitiatingPhysAsInitiatingPhysEnumCollection(InitiatingPhysEnumCollection enumCollection)
		{
			InitiatingPhys = InitiatingPhysInfo.InitiatingPhysToValue(enumCollection);
		}
	}

	public class ParametersSubField
	{
		private uint _ScanInterval = 4u;

		private uint _ScanWindow = 4u;

		private uint _ConnIntervalMin = 6u;

		private uint _ConnIntervalMax = 6u;

		private uint _ConnLatency;

		private uint _SupervisionTimeout = 10u;

		private uint _MinimumCeLength;

		private uint _MaximumCeLength;

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

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

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

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

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

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

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

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

		public void SetDefaultValues()
		{
			ScanInterval = 4u;
			ScanWindow = 4u;
			ConnIntervalMin = 6u;
			ConnIntervalMax = 6u;
			ConnLatency = 0u;
			SupervisionTimeout = 1000u;
			MinimumCeLength = 0u;
			MaximumCeLength = 0u;
		}

		public bool FromBitBuilder(ref BitBuilder bitBuilder)
		{
			ScanInterval = bitBuilder.RemoveBitsAsUintLittleEndian(16);
			ScanWindow = bitBuilder.RemoveBitsAsUintLittleEndian(16);
			ConnIntervalMin = bitBuilder.RemoveBitsAsUintLittleEndian(16);
			ConnIntervalMax = bitBuilder.RemoveBitsAsUintLittleEndian(16);
			ConnLatency = bitBuilder.RemoveBitsAsUintLittleEndian(16);
			SupervisionTimeout = bitBuilder.RemoveBitsAsUintLittleEndian(16);
			MinimumCeLength = bitBuilder.RemoveBitsAsUintLittleEndian(16);
			MaximumCeLength = bitBuilder.RemoveBitsAsUintLittleEndian(16);
			return true;
		}

		public string ToBitString()
		{
			BitBuilder bitBuilder = new BitBuilder();
			bitBuilder.AddBitsAsUintLittleEndian(ScanInterval, 16);
			bitBuilder.AddBitsAsUintLittleEndian(ScanWindow, 16);
			bitBuilder.AddBitsAsUintLittleEndian(ConnIntervalMin, 16);
			bitBuilder.AddBitsAsUintLittleEndian(ConnIntervalMax, 16);
			bitBuilder.AddBitsAsUintLittleEndian(ConnLatency, 16);
			bitBuilder.AddBitsAsUintLittleEndian(SupervisionTimeout, 16);
			bitBuilder.AddBitsAsUintLittleEndian(MinimumCeLength, 16);
			bitBuilder.AddBitsAsUintLittleEndian(MaximumCeLength, 16);
			return bitBuilder.ToString();
		}

		public List<string> GetWarnings()
		{
			List<string> list = new List<string>();
			if (ScanInterval < 4)
			{
				list.Add("Minimum allowed value for Scan_Interval is 0x4");
			}
			if (ScanInterval > 65535)
			{
				list.Add("Maximum allowed value for Scan_Interval is 0xFFFF");
			}
			if (ScanWindow < 4)
			{
				list.Add("Minimum allowed value for Scan_Window is 0x4");
			}
			if (ScanWindow > 65535)
			{
				list.Add("Maximum allowed value for Scan_Window is 0xFFFF");
			}
			if (ConnIntervalMin < 6)
			{
				list.Add("Minimum allowed value for Conn_Interval_Min is 0x6");
			}
			if (ConnIntervalMin > 3200)
			{
				list.Add("Maximum allowed value for Conn_Interval_Min is 0xC80");
			}
			if (ConnIntervalMax < 6)
			{
				list.Add("Minimum allowed value for Conn_Interval_Max is 0x6");
			}
			if (ConnIntervalMax > 3200)
			{
				list.Add("Maximum allowed value for Conn_Interval_Max is 0xC80");
			}
			if (ConnLatency < 0)
			{
				list.Add("Minimum allowed value for Conn_Latency is 0x0");
			}
			if (ConnLatency > 499)
			{
				list.Add("Maximum allowed value for Conn_Latency is 0x1F3");
			}
			if (SupervisionTimeout < 10)
			{
				list.Add("Minimum allowed value for Supervision_Timeout is 0xA");
			}
			if (SupervisionTimeout > 3200)
			{
				list.Add("Maximum allowed value for Supervision_Timeout is 0xC80");
			}
			if (MinimumCeLength < 0)
			{
				list.Add("Minimum allowed value for Minimum_CE_Length is 0x0");
			}
			if (MinimumCeLength > 65535)
			{
				list.Add("Maximum allowed value for Minimum_CE_Length is 0xFFFF");
			}
			if (MaximumCeLength < 0)
			{
				list.Add("Minimum allowed value for Maximum_CE_Length is 0x0");
			}
			if (MaximumCeLength > 65535)
			{
				list.Add("Maximum allowed value for Maximum_CE_Length is 0xFFFF");
			}
			return list;
		}
	}

	private const uint _Opcode = 8259u;

	private Type[] expectedResponseTypes = new Type[1] { typeof(CommandStatusForLeExtendedCreateConnection) };

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

	public uint Opcode => 8259u;

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

	public UserFieldsWrapper UserFields => _UserFields;

	public override void SetDefaultValues()
	{
		UserFields.InitiatingPhys = 1u;
		for (int i = 0; i < UserFields.ParametersList.Count; i++)
		{
			UserFields.ParametersList[i].SetDefaultValues();
		}
	}

	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.InitiatingFilterPolicy = bitBuilder.RemoveBitsAsUint(8);
		UserFields.OwnAddressType = bitBuilder.RemoveBitsAsUint(8);
		UserFields.PeerAddressType = bitBuilder.RemoveBitsAsUint(8);
		UserFields.PeerAddress = bitBuilder.RemoveBitsAsUlongLittleEndian(48);
		UserFields.InitiatingPhys = bitBuilder.RemoveBitsAsUint(8);
		for (int i = 0; i < UserFields.ParametersList.Count; i++)
		{
			UserFields.ParametersList[i].FromBitBuilder(ref bitBuilder);
		}
		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.InitiatingFilterPolicy, 8);
		bitBuilder.AddBitsAsUint(UserFields.OwnAddressType, 8);
		bitBuilder.AddBitsAsUint(UserFields.PeerAddressType, 8);
		bitBuilder.AddBitsAsUlongLittleEndian(UserFields.PeerAddress, 48);
		bitBuilder.AddBitsAsUint(UserFields.InitiatingPhys, 8);
		for (int i = 0; i < UserFields.ParametersList.Count; i++)
		{
			bitBuilder.AddBitsAsString(UserFields.ParametersList[i].ToBitString());
		}
		_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.InitiatingPhys < 1)
		{
			list.Add("Minimum allowed value for Initiating_PHYs is 0x1");
		}
		for (int i = 0; i < UserFields.ParametersList.Count; i++)
		{
			list.AddRange(UserFields.ParametersList[i].GetWarnings());
		}
		return list;
	}
}
