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

namespace QCRPG.TSL.BT.Packets;

public class CreatePhysicalLink : PacketBase
{
	public class UserFieldsWrapper
	{
		public enum DedicatedAmpKeyTypeEnum
		{
			Reserved,
			DEBUG_COMBINATION_KEY,
			UNAUTHENTICATED_COMBINATION_KEY,
			AUTHENTICATED_COMBINATION_KEY,
			InvalidDedicatedAmpKeyTypeValue
		}

		public static class DedicatedAmpKeyTypeInfo
		{
			public static DedicatedAmpKeyTypeEnum ValueToDedicatedAmpKeyType(uint value)
			{
				switch (value)
				{
				case 0u:
					return DedicatedAmpKeyTypeEnum.Reserved;
				case 1u:
					return DedicatedAmpKeyTypeEnum.Reserved;
				case 2u:
					return DedicatedAmpKeyTypeEnum.Reserved;
				case 3u:
					return DedicatedAmpKeyTypeEnum.DEBUG_COMBINATION_KEY;
				case 4u:
					return DedicatedAmpKeyTypeEnum.UNAUTHENTICATED_COMBINATION_KEY;
				case 5u:
					return DedicatedAmpKeyTypeEnum.AUTHENTICATED_COMBINATION_KEY;
				case 6u:
					return DedicatedAmpKeyTypeEnum.Reserved;
				default:
					if (value >= 7 && value <= 255)
					{
						return DedicatedAmpKeyTypeEnum.Reserved;
					}
					return DedicatedAmpKeyTypeEnum.InvalidDedicatedAmpKeyTypeValue;
				}
			}

			public static uint DedicatedAmpKeyTypeToValue(DedicatedAmpKeyTypeEnum enumItem)
			{
				if (enumItem == DedicatedAmpKeyTypeEnum.Reserved)
				{
					return 0u;
				}
				if (enumItem == DedicatedAmpKeyTypeEnum.Reserved)
				{
					return 1u;
				}
				switch (enumItem)
				{
				case DedicatedAmpKeyTypeEnum.Reserved:
					return 2u;
				case DedicatedAmpKeyTypeEnum.DEBUG_COMBINATION_KEY:
					return 3u;
				case DedicatedAmpKeyTypeEnum.UNAUTHENTICATED_COMBINATION_KEY:
					return 4u;
				case DedicatedAmpKeyTypeEnum.AUTHENTICATED_COMBINATION_KEY:
					return 5u;
				default:
					if (enumItem == DedicatedAmpKeyTypeEnum.Reserved)
					{
						return 6u;
					}
					if (enumItem == DedicatedAmpKeyTypeEnum.Reserved)
					{
						return 7u;
					}
					return uint.MaxValue;
				}
			}

			public static string DedicatedAmpKeyTypeToString(DedicatedAmpKeyTypeEnum enumItem)
			{
				if (enumItem == DedicatedAmpKeyTypeEnum.Reserved)
				{
					return "Reserved";
				}
				if (enumItem == DedicatedAmpKeyTypeEnum.Reserved)
				{
					return "Reserved";
				}
				switch (enumItem)
				{
				case DedicatedAmpKeyTypeEnum.Reserved:
					return "Reserved";
				case DedicatedAmpKeyTypeEnum.DEBUG_COMBINATION_KEY:
					return "Debug combination key";
				case DedicatedAmpKeyTypeEnum.UNAUTHENTICATED_COMBINATION_KEY:
					return "Unauthenticated combination key";
				case DedicatedAmpKeyTypeEnum.AUTHENTICATED_COMBINATION_KEY:
					return "Authenticated combination key";
				default:
					if (enumItem == DedicatedAmpKeyTypeEnum.Reserved)
					{
						return "Reserved";
					}
					if (enumItem == DedicatedAmpKeyTypeEnum.Reserved)
					{
						return "Reserved";
					}
					return "Invalid DedicatedAmpKeyType Value";
				}
			}

			public static string DedicatedAmpKeyTypeToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = Reserved");
				stringBuilder.AppendLine("0x1 = Reserved");
				stringBuilder.AppendLine("0x2 = Reserved");
				stringBuilder.AppendLine("0x3 = Debug combination key");
				stringBuilder.AppendLine("0x4 = Unauthenticated combination key");
				stringBuilder.AppendLine("0x5 = Authenticated combination key");
				stringBuilder.AppendLine("0x6 = Reserved");
				stringBuilder.AppendLine("0x7-0xFF = Reserved");
				return stringBuilder.ToString();
			}
		}

		private uint _PhysicalLinkHandle;

		private uint _DedicatedAmpKeyLength;

		private uint _DedicatedAmpKeyType;

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

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

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

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

		public List<uint> DedicatedAmpKeyList => _DedicatedAmpKeyList;

		public DedicatedAmpKeyTypeEnum GetDedicatedAmpKeyTypeAsDedicatedAmpKeyTypeEnum()
		{
			return DedicatedAmpKeyTypeInfo.ValueToDedicatedAmpKeyType(_DedicatedAmpKeyType);
		}

		public void SetDedicatedAmpKeyTypeAsDedicatedAmpKeyTypeEnum(DedicatedAmpKeyTypeEnum enumItem)
		{
			DedicatedAmpKeyType = DedicatedAmpKeyTypeInfo.DedicatedAmpKeyTypeToValue(enumItem);
		}
	}

	private const uint _Opcode = 1077u;

	private Type[] expectedResponseTypes = new Type[3]
	{
		typeof(CommandStatusForCreatePhysicalLink),
		typeof(ChannelSelected),
		typeof(PhysicalLinkComplete)
	};

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

	public uint Opcode => 1077u;

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

	public UserFieldsWrapper UserFields => _UserFields;

	public override void SetDefaultValues()
	{
		UserFields.DedicatedAmpKeyType = 5u;
	}

	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.PhysicalLinkHandle = bitBuilder.RemoveBitsAsUint(8);
		UserFields.DedicatedAmpKeyLength = bitBuilder.RemoveBitsAsUint(8);
		UserFields.DedicatedAmpKeyType = bitBuilder.RemoveBitsAsUint(8);
		for (int i = 0; i < UserFields.DedicatedAmpKeyList.Count; i++)
		{
			UserFields.DedicatedAmpKeyList[i] = 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.PhysicalLinkHandle, 8);
		bitBuilder.AddBitsAsUint(UserFields.DedicatedAmpKeyLength, 8);
		bitBuilder.AddBitsAsUint(UserFields.DedicatedAmpKeyType, 8);
		for (int i = 0; i < UserFields.DedicatedAmpKeyList.Count; i++)
		{
			if (UserFields.DedicatedAmpKeyList[i] > 255)
			{
				throw new Exception("UserFields.DedicatedAmpKeyList[i] is > 0xFF");
			}
			bitBuilder.AddBitsAsUint(UserFields.DedicatedAmpKeyList[i], 8);
		}
		_PayloadLength = (uint)((bitBuilder.GetNumberOfBits() - numberOfBits - 8) / 8);
		if ((bitBuilder.GetNumberOfBits() - numberOfBits - 8) % 8 != 0)
		{
			_PayloadLength++;
		}
		bitBuilder.ChangeBitsAsUint(numberOfBits, _PayloadLength, 8);
		return bitBuilder.ToString();
	}
}
