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

namespace QCRPG.TSL.BT.Packets;

public class SynchronousConnectionCompleteEvent : PacketBase
{
	public class UserFieldsWrapper
	{
		public enum LinkTypeEnum
		{
			SCO_Connection,
			Reserved,
			eSCO_Connection,
			InvalidLinkTypeValue
		}

		public static class LinkTypeInfo
		{
			public static LinkTypeEnum ValueToLinkType(uint value)
			{
				switch (value)
				{
				case 0u:
					return LinkTypeEnum.SCO_Connection;
				case 1u:
					return LinkTypeEnum.Reserved;
				case 2u:
					return LinkTypeEnum.eSCO_Connection;
				default:
					if (value >= 3 && value <= 255)
					{
						return LinkTypeEnum.Reserved;
					}
					return LinkTypeEnum.InvalidLinkTypeValue;
				}
			}

			public static uint LinkTypeToValue(LinkTypeEnum enumItem)
			{
				switch (enumItem)
				{
				case LinkTypeEnum.SCO_Connection:
					return 0u;
				case LinkTypeEnum.Reserved:
					return 1u;
				case LinkTypeEnum.eSCO_Connection:
					return 2u;
				default:
					if (enumItem == LinkTypeEnum.Reserved)
					{
						return 3u;
					}
					return uint.MaxValue;
				}
			}

			public static string LinkTypeToString(LinkTypeEnum enumItem)
			{
				switch (enumItem)
				{
				case LinkTypeEnum.SCO_Connection:
					return "SCO_Connection";
				case LinkTypeEnum.Reserved:
					return "Reserved";
				case LinkTypeEnum.eSCO_Connection:
					return "eSCO_Connection";
				default:
					if (enumItem == LinkTypeEnum.Reserved)
					{
						return "Reserved";
					}
					return "Invalid LinkType Value";
				}
			}

			public static string LinkTypeToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = SCO_Connection");
				stringBuilder.AppendLine("0x1 = Reserved");
				stringBuilder.AppendLine("0x2 = eSCO_Connection");
				stringBuilder.AppendLine("0x3-0xFF = Reserved");
				return stringBuilder.ToString();
			}
		}

		public enum AirModeEnum
		{
			u_law_log,
			A_law_log,
			CVSD,
			Transparent_Data,
			Reserved,
			InvalidAirModeValue
		}

		public static class AirModeInfo
		{
			public static AirModeEnum ValueToAirMode(uint value)
			{
				switch (value)
				{
				case 0u:
					return AirModeEnum.u_law_log;
				case 1u:
					return AirModeEnum.A_law_log;
				case 2u:
					return AirModeEnum.CVSD;
				case 3u:
					return AirModeEnum.Transparent_Data;
				default:
					if (value >= 4 && value <= 255)
					{
						return AirModeEnum.Reserved;
					}
					return AirModeEnum.InvalidAirModeValue;
				}
			}

			public static uint AirModeToValue(AirModeEnum enumItem)
			{
				return enumItem switch
				{
					AirModeEnum.u_law_log => 0u, 
					AirModeEnum.A_law_log => 1u, 
					AirModeEnum.CVSD => 2u, 
					AirModeEnum.Transparent_Data => 3u, 
					AirModeEnum.Reserved => 4u, 
					_ => uint.MaxValue, 
				};
			}

			public static string AirModeToString(AirModeEnum enumItem)
			{
				return enumItem switch
				{
					AirModeEnum.u_law_log => "u_law_log", 
					AirModeEnum.A_law_log => "A_law_log", 
					AirModeEnum.CVSD => "CVSD", 
					AirModeEnum.Transparent_Data => "Transparent_Data", 
					AirModeEnum.Reserved => "Reserved", 
					_ => "Invalid AirMode Value", 
				};
			}

			public static string AirModeToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = u_law_log");
				stringBuilder.AppendLine("0x1 = A_law_log");
				stringBuilder.AppendLine("0x2 = CVSD");
				stringBuilder.AppendLine("0x3 = Transparent_Data");
				stringBuilder.AppendLine("0x4-0xFF = Reserved");
				return stringBuilder.ToString();
			}
		}

		private uint _Status;

		private uint _ConnectionHandle;

		private ulong _BdAddr;

		private uint _LinkType;

		private uint _TransmissionInterval;

		private uint _RetransmissionWindow;

		private uint _RxPacketLength;

		private uint _TxPacketLength;

		private uint _AirMode;

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

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

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

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

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

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

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

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

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

		public ErrorCodeEnum GetStatusAsErrorCodeEnum()
		{
			return ErrorCodeInfo.ValueToErrorCode(_Status);
		}

		public void SetStatusAsErrorCodeEnum(ErrorCodeEnum enumItem)
		{
			Status = ErrorCodeInfo.ErrorCodeToValue(enumItem);
		}

		public LinkTypeEnum GetLinkTypeAsLinkTypeEnum()
		{
			return LinkTypeInfo.ValueToLinkType(_LinkType);
		}

		public void SetLinkTypeAsLinkTypeEnum(LinkTypeEnum enumItem)
		{
			LinkType = LinkTypeInfo.LinkTypeToValue(enumItem);
		}

		public AirModeEnum GetAirModeAsAirModeEnum()
		{
			return AirModeInfo.ValueToAirMode(_AirMode);
		}

		public void SetAirModeAsAirModeEnum(AirModeEnum enumItem)
		{
			AirMode = AirModeInfo.AirModeToValue(enumItem);
		}
	}

	private const uint _EventCode = 44u;

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

	public uint EventCode => 44u;

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

	public UserFieldsWrapper UserFields => _UserFields;

	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;
		}
		UserFields.Status = bitBuilder.RemoveBitsAsUint(8);
		UserFields.ConnectionHandle = bitBuilder.RemoveBitsAsUintLittleEndian(16);
		UserFields.BdAddr = bitBuilder.RemoveBitsAsUlongLittleEndian(48);
		UserFields.LinkType = bitBuilder.RemoveBitsAsUintLittleEndian(8);
		UserFields.TransmissionInterval = bitBuilder.RemoveBitsAsUint(8);
		UserFields.RetransmissionWindow = bitBuilder.RemoveBitsAsUint(8);
		UserFields.RxPacketLength = bitBuilder.RemoveBitsAsUintLittleEndian(16);
		UserFields.TxPacketLength = bitBuilder.RemoveBitsAsUintLittleEndian(16);
		UserFields.AirMode = bitBuilder.RemoveBitsAsUintLittleEndian(8);
		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.Status, 8);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.ConnectionHandle, 16);
		bitBuilder.AddBitsAsUlongLittleEndian(UserFields.BdAddr, 48);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.LinkType, 8);
		bitBuilder.AddBitsAsUint(UserFields.TransmissionInterval, 8);
		bitBuilder.AddBitsAsUint(UserFields.RetransmissionWindow, 8);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.RxPacketLength, 16);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.TxPacketLength, 16);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.AirMode, 8);
		_PayloadLength = (uint)((bitBuilder.GetNumberOfBits() - numberOfBits - 8) / 8);
		if ((bitBuilder.GetNumberOfBits() - numberOfBits - 8) % 8 != 0)
		{
			_PayloadLength++;
		}
		bitBuilder.ChangeBitsAsUint(numberOfBits, _PayloadLength, 8);
		return bitBuilder.ToString();
	}
}
