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

namespace QCRPG.TSL.BT.Packets;

public class LeAdvtTracking : PacketBase
{
	public class UserFieldsWrapper
	{
		public enum AdvertiserStateEnum
		{
			Advertiser_Found,
			Advertiser_Lost,
			InvalidAdvertiserStateValue
		}

		public static class AdvertiserStateInfo
		{
			public static AdvertiserStateEnum ValueToAdvertiserState(uint value)
			{
				return value switch
				{
					0u => AdvertiserStateEnum.Advertiser_Found, 
					1u => AdvertiserStateEnum.Advertiser_Lost, 
					_ => AdvertiserStateEnum.InvalidAdvertiserStateValue, 
				};
			}

			public static uint AdvertiserStateToValue(AdvertiserStateEnum enumItem)
			{
				return enumItem switch
				{
					AdvertiserStateEnum.Advertiser_Found => 0u, 
					AdvertiserStateEnum.Advertiser_Lost => 1u, 
					_ => uint.MaxValue, 
				};
			}

			public static string AdvertiserStateToString(AdvertiserStateEnum enumItem)
			{
				return enumItem switch
				{
					AdvertiserStateEnum.Advertiser_Found => "Advertiser Found", 
					AdvertiserStateEnum.Advertiser_Lost => "Advertiser Lost", 
					_ => "Invalid AdvertiserState Value", 
				};
			}

			public static string AdvertiserStateToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = Advertiser Found");
				stringBuilder.AppendLine("0x1 = Advertiser Lost");
				return stringBuilder.ToString();
			}
		}

		public enum AdvtInfoPresentEnum
		{
			Advertiser_info_Advt_Info_present,
			Advertiser_info_Advt_Info_not_present,
			InvalidAdvtInfoPresentValue
		}

		public static class AdvtInfoPresentInfo
		{
			public static AdvtInfoPresentEnum ValueToAdvtInfoPresent(uint value)
			{
				return value switch
				{
					0u => AdvtInfoPresentEnum.Advertiser_info_Advt_Info_present, 
					1u => AdvtInfoPresentEnum.Advertiser_info_Advt_Info_not_present, 
					_ => AdvtInfoPresentEnum.InvalidAdvtInfoPresentValue, 
				};
			}

			public static uint AdvtInfoPresentToValue(AdvtInfoPresentEnum enumItem)
			{
				return enumItem switch
				{
					AdvtInfoPresentEnum.Advertiser_info_Advt_Info_present => 0u, 
					AdvtInfoPresentEnum.Advertiser_info_Advt_Info_not_present => 1u, 
					_ => uint.MaxValue, 
				};
			}

			public static string AdvtInfoPresentToString(AdvtInfoPresentEnum enumItem)
			{
				return enumItem switch
				{
					AdvtInfoPresentEnum.Advertiser_info_Advt_Info_present => "Advertiser info(Advt_Info) present", 
					AdvtInfoPresentEnum.Advertiser_info_Advt_Info_not_present => "Advertiser info(Advt_Info) not present", 
					_ => "Invalid AdvtInfoPresent Value", 
				};
			}

			public static string AdvtInfoPresentToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = Advertiser info(Advt_Info) present");
				stringBuilder.AppendLine("0x1 = Advertiser info(Advt_Info) not present");
				return stringBuilder.ToString();
			}
		}

		private const uint _SubEventCode = 86u;

		private uint _ApcfFilterIndex;

		private uint _AdvertiserState;

		private uint _AdvtInfoPresent;

		private ulong _AdvertiserAddress;

		private uint _AdvertiserAddressType;

		private uint _AdvtInfoCount;

		private List<AdvtInfoSubField> _AdvtInfoList = new List<AdvtInfoSubField>();

		public uint SubEventCode => 86u;

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

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

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

		public ulong AdvertiserAddress
		{
			get
			{
				return _AdvertiserAddress;
			}
			set
			{
				_AdvertiserAddress = value;
			}
		}

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

		public uint AdvtInfoCount
		{
			get
			{
				return _AdvtInfoCount;
			}
			set
			{
				if (value > 255)
				{
					throw new Exception("Maximum possible value for AdvtInfoCount is 0xFF");
				}
				_AdvtInfoCount = value;
				while (_AdvtInfoList.Count < _AdvtInfoCount)
				{
					_AdvtInfoList.Add(new AdvtInfoSubField());
				}
				while (_AdvtInfoList.Count > _AdvtInfoCount)
				{
					_AdvtInfoList.RemoveAt(_AdvtInfoList.Count - 1);
				}
			}
		}

		public List<AdvtInfoSubField> AdvtInfoList => _AdvtInfoList;

		public AdvertiserStateEnum GetAdvertiserStateAsAdvertiserStateEnum()
		{
			return AdvertiserStateInfo.ValueToAdvertiserState(_AdvertiserState);
		}

		public void SetAdvertiserStateAsAdvertiserStateEnum(AdvertiserStateEnum enumItem)
		{
			AdvertiserState = AdvertiserStateInfo.AdvertiserStateToValue(enumItem);
		}

		public AdvtInfoPresentEnum GetAdvtInfoPresentAsAdvtInfoPresentEnum()
		{
			return AdvtInfoPresentInfo.ValueToAdvtInfoPresent(_AdvtInfoPresent);
		}

		public void SetAdvtInfoPresentAsAdvtInfoPresentEnum(AdvtInfoPresentEnum enumItem)
		{
			AdvtInfoPresent = AdvtInfoPresentInfo.AdvtInfoPresentToValue(enumItem);
		}

		public DeviceAddressTypeEnum GetAdvertiserAddressTypeAsDeviceAddressTypeEnum()
		{
			return DeviceAddressTypeInfo.ValueToDeviceAddressType(_AdvertiserAddressType);
		}

		public void SetAdvertiserAddressTypeAsDeviceAddressTypeEnum(DeviceAddressTypeEnum enumItem)
		{
			AdvertiserAddressType = DeviceAddressTypeInfo.DeviceAddressTypeToValue(enumItem);
		}
	}

	public class AdvtInfoSubField
	{
		public enum AdvPacketLenEnum
		{
			Length_of_the_Data_field_for_each_device_which_responded,
			RESERVED_FOR_FUTURE_USE,
			InvalidAdvPacketLenValue
		}

		public static class AdvPacketLenInfo
		{
			public static AdvPacketLenEnum ValueToAdvPacketLen(uint value)
			{
				if (value >= 0 && value <= 31)
				{
					return AdvPacketLenEnum.Length_of_the_Data_field_for_each_device_which_responded;
				}
				if (value >= 32 && value <= 255)
				{
					return AdvPacketLenEnum.RESERVED_FOR_FUTURE_USE;
				}
				return AdvPacketLenEnum.InvalidAdvPacketLenValue;
			}

			public static uint AdvPacketLenToValue(AdvPacketLenEnum enumItem)
			{
				return enumItem switch
				{
					AdvPacketLenEnum.Length_of_the_Data_field_for_each_device_which_responded => 0u, 
					AdvPacketLenEnum.RESERVED_FOR_FUTURE_USE => 32u, 
					_ => uint.MaxValue, 
				};
			}

			public static string AdvPacketLenToString(AdvPacketLenEnum enumItem)
			{
				return enumItem switch
				{
					AdvPacketLenEnum.Length_of_the_Data_field_for_each_device_which_responded => "Length of the Data[i] field for each device which responded", 
					AdvPacketLenEnum.RESERVED_FOR_FUTURE_USE => "Reserved for future use", 
					_ => "Invalid AdvPacketLen Value", 
				};
			}

			public static string AdvPacketLenToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0-0x1F = Length of the Data[i] field for each device which responded");
				stringBuilder.AppendLine("0x20-0xFF = Reserved for future use");
				return stringBuilder.ToString();
			}
		}

		public enum ScanDataRespLenEnum
		{
			Length_of_the_Data_field_for_each_device_which_responded,
			RESERVED_FOR_FUTURE_USE,
			InvalidScanDataRespLenValue
		}

		public static class ScanDataRespLenInfo
		{
			public static ScanDataRespLenEnum ValueToScanDataRespLen(uint value)
			{
				if (value >= 0 && value <= 31)
				{
					return ScanDataRespLenEnum.Length_of_the_Data_field_for_each_device_which_responded;
				}
				if (value >= 32 && value <= 255)
				{
					return ScanDataRespLenEnum.RESERVED_FOR_FUTURE_USE;
				}
				return ScanDataRespLenEnum.InvalidScanDataRespLenValue;
			}

			public static uint ScanDataRespLenToValue(ScanDataRespLenEnum enumItem)
			{
				return enumItem switch
				{
					ScanDataRespLenEnum.Length_of_the_Data_field_for_each_device_which_responded => 0u, 
					ScanDataRespLenEnum.RESERVED_FOR_FUTURE_USE => 32u, 
					_ => uint.MaxValue, 
				};
			}

			public static string ScanDataRespLenToString(ScanDataRespLenEnum enumItem)
			{
				return enumItem switch
				{
					ScanDataRespLenEnum.Length_of_the_Data_field_for_each_device_which_responded => "Length of the Data[i] field for each device which responded", 
					ScanDataRespLenEnum.RESERVED_FOR_FUTURE_USE => "Reserved for future use", 
					_ => "Invalid ScanDataRespLen Value", 
				};
			}

			public static string ScanDataRespLenToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0-0x1F = Length of the Data[i] field for each device which responded");
				stringBuilder.AppendLine("0x20-0xFF = Reserved for future use");
				return stringBuilder.ToString();
			}
		}

		private uint _TxPwr;

		private uint _Rssi;

		private uint _Timestamp;

		private uint _AdvPacketLen;

		private List<uint> _AdvPacketList = new List<uint>();

		private uint _ScanDataRespLen;

		private List<uint> _ScanDataRespList = new List<uint>();

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

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

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

		public uint AdvPacketLen
		{
			get
			{
				return _AdvPacketLen;
			}
			set
			{
				if (value > 255)
				{
					throw new Exception("Maximum possible value for AdvPacketLen is 0xFF");
				}
				_AdvPacketLen = value;
				while (_AdvPacketList.Count < _AdvPacketLen)
				{
					_AdvPacketList.Add(0u);
				}
				while (_AdvPacketList.Count > _AdvPacketLen)
				{
					_AdvPacketList.RemoveAt(_AdvPacketList.Count - 1);
				}
			}
		}

		public List<uint> AdvPacketList => _AdvPacketList;

		public uint ScanDataRespLen
		{
			get
			{
				return _ScanDataRespLen;
			}
			set
			{
				if (value > 255)
				{
					throw new Exception("Maximum possible value for ScanDataRespLen is 0xFF");
				}
				_ScanDataRespLen = value;
				while (_ScanDataRespList.Count < _ScanDataRespLen)
				{
					_ScanDataRespList.Add(0u);
				}
				while (_ScanDataRespList.Count > _ScanDataRespLen)
				{
					_ScanDataRespList.RemoveAt(_ScanDataRespList.Count - 1);
				}
			}
		}

		public List<uint> ScanDataRespList => _ScanDataRespList;

		public AdvPacketLenEnum GetAdvPacketLenAsAdvPacketLenEnum()
		{
			return AdvPacketLenInfo.ValueToAdvPacketLen(_AdvPacketLen);
		}

		public void SetAdvPacketLenAsAdvPacketLenEnum(AdvPacketLenEnum enumItem)
		{
			AdvPacketLen = AdvPacketLenInfo.AdvPacketLenToValue(enumItem);
		}

		public ScanDataRespLenEnum GetScanDataRespLenAsScanDataRespLenEnum()
		{
			return ScanDataRespLenInfo.ValueToScanDataRespLen(_ScanDataRespLen);
		}

		public void SetScanDataRespLenAsScanDataRespLenEnum(ScanDataRespLenEnum enumItem)
		{
			ScanDataRespLen = ScanDataRespLenInfo.ScanDataRespLenToValue(enumItem);
		}

		public bool FromBitBuilder(ref BitBuilder bitBuilder)
		{
			TxPwr = bitBuilder.RemoveBitsAsUint(8);
			Rssi = bitBuilder.RemoveBitsAsUint(8);
			Timestamp = bitBuilder.RemoveBitsAsUintLittleEndian(16);
			AdvPacketLen = bitBuilder.RemoveBitsAsUint(8);
			for (int num = AdvPacketList.Count - 1; num >= 0; num--)
			{
				AdvPacketList[num] = bitBuilder.RemoveBitsAsUint(8);
			}
			ScanDataRespLen = bitBuilder.RemoveBitsAsUint(8);
			for (int num2 = ScanDataRespList.Count - 1; num2 >= 0; num2--)
			{
				ScanDataRespList[num2] = bitBuilder.RemoveBitsAsUint(8);
			}
			return true;
		}

		public string ToBitString()
		{
			BitBuilder bitBuilder = new BitBuilder();
			bitBuilder.AddBitsAsUint(TxPwr, 8);
			bitBuilder.AddBitsAsUint(Rssi, 8);
			bitBuilder.AddBitsAsUintLittleEndian(Timestamp, 16);
			bitBuilder.AddBitsAsUint(AdvPacketLen, 8);
			for (int num = AdvPacketList.Count - 1; num >= 0; num--)
			{
				if (AdvPacketList[num] > 255)
				{
					throw new Exception("AdvPacketList[i] is > 0xFF");
				}
				bitBuilder.AddBitsAsUint(AdvPacketList[num], 8);
			}
			bitBuilder.AddBitsAsUint(ScanDataRespLen, 8);
			for (int num2 = ScanDataRespList.Count - 1; num2 >= 0; num2--)
			{
				if (ScanDataRespList[num2] > 255)
				{
					throw new Exception("ScanDataRespList[i] is > 0xFF");
				}
				bitBuilder.AddBitsAsUint(ScanDataRespList[num2], 8);
			}
			return bitBuilder.ToString();
		}
	}

	private const uint _EventCode = 255u;

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

	private PacketInfoBase info;

	private uint _PayloadLength;

	public UserFieldsWrapper _UserFields = new UserFieldsWrapper();

	public override PacketType Type => PacketType.Notification;

	public override Type[] ExpectedResponseTypes => expectedResponseTypes;

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

	public uint EventCode => 255u;

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

	public UserFieldsWrapper UserFields => _UserFields;

	public override void SetDefaultValues()
	{
		UserFields.AdvtInfoCount = 1u;
	}

	protected override bool FromBitBuilder(ref BitBuilder bitBuilder)
	{
		if (bitBuilder.RemoveBitsAsUint(8) != EventCode)
		{
			return false;
		}
		_PayloadLength = bitBuilder.RemoveBitsAsUint(8);
		int numberOfBits = bitBuilder.GetNumberOfBits();
		if (numberOfBits > _PayloadLength * 8 + 7)
		{
			return false;
		}
		if (numberOfBits < _PayloadLength * 8)
		{
			return false;
		}
		if (bitBuilder.RemoveBitsAsUint(8) != UserFields.SubEventCode)
		{
			return false;
		}
		UserFields.ApcfFilterIndex = bitBuilder.RemoveBitsAsUint(8);
		UserFields.AdvertiserState = bitBuilder.RemoveBitsAsUint(8);
		UserFields.AdvtInfoPresent = bitBuilder.RemoveBitsAsUint(8);
		UserFields.AdvertiserAddress = bitBuilder.RemoveBitsAsUlongLittleEndian(48);
		UserFields.AdvertiserAddressType = bitBuilder.RemoveBitsAsUint(8);
		UserFields.AdvtInfoCount = (uint)(bitBuilder.GetNumberOfBits() / 8);
		for (int i = 0; i < UserFields.AdvtInfoList.Count; i++)
		{
			UserFields.AdvtInfoList[i].FromBitBuilder(ref bitBuilder);
		}
		if (bitBuilder.GetNumberOfBits() > 7)
		{
			return false;
		}
		return true;
	}

	public override string ToBitString()
	{
		BitBuilder bitBuilder = new BitBuilder();
		bitBuilder.AddBitsAsUint(EventCode, 8);
		int numberOfBits = bitBuilder.GetNumberOfBits();
		bitBuilder.AddBitsAsUint(0u, 8);
		bitBuilder.AddBitsAsUint(UserFields.SubEventCode, 8);
		bitBuilder.AddBitsAsUint(UserFields.ApcfFilterIndex, 8);
		bitBuilder.AddBitsAsUint(UserFields.AdvertiserState, 8);
		bitBuilder.AddBitsAsUint(UserFields.AdvtInfoPresent, 8);
		bitBuilder.AddBitsAsUlongLittleEndian(UserFields.AdvertiserAddress, 48);
		bitBuilder.AddBitsAsUint(UserFields.AdvertiserAddressType, 8);
		for (int i = 0; i < UserFields.AdvtInfoList.Count; i++)
		{
			bitBuilder.AddBitsAsString(UserFields.AdvtInfoList[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();
	}
}
