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

namespace QCRPG.TSL.BT.Packets;

public class HciSniffMode : PacketBase
{
	public class UserFieldsWrapper
	{
		public enum SniffMaxIntervalEnum
		{
			Sniff_Max_Interval,
			InvalidSniffMaxIntervalValue
		}

		public static class SniffMaxIntervalInfo
		{
			public static SniffMaxIntervalEnum ValueToSniffMaxInterval(uint value)
			{
				if (value >= 2 && value <= 65534)
				{
					return SniffMaxIntervalEnum.Sniff_Max_Interval;
				}
				return SniffMaxIntervalEnum.InvalidSniffMaxIntervalValue;
			}

			public static uint SniffMaxIntervalToValue(SniffMaxIntervalEnum enumItem)
			{
				if (enumItem == SniffMaxIntervalEnum.Sniff_Max_Interval)
				{
					return 2u;
				}
				return uint.MaxValue;
			}

			public static string SniffMaxIntervalToString(SniffMaxIntervalEnum enumItem)
			{
				if (enumItem == SniffMaxIntervalEnum.Sniff_Max_Interval)
				{
					return "Unit: Slots (0.625ms)";
				}
				return "Invalid SniffMaxInterval Value";
			}

			public static string SniffMaxIntervalToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x2-0xFFFE = Unit: Slots (0.625ms)");
				return stringBuilder.ToString();
			}
		}

		public enum SniffMinIntervalEnum
		{
			Sniff_Min_Interval,
			InvalidSniffMinIntervalValue
		}

		public static class SniffMinIntervalInfo
		{
			public static SniffMinIntervalEnum ValueToSniffMinInterval(uint value)
			{
				if (value >= 2 && value <= 65534)
				{
					return SniffMinIntervalEnum.Sniff_Min_Interval;
				}
				return SniffMinIntervalEnum.InvalidSniffMinIntervalValue;
			}

			public static uint SniffMinIntervalToValue(SniffMinIntervalEnum enumItem)
			{
				if (enumItem == SniffMinIntervalEnum.Sniff_Min_Interval)
				{
					return 2u;
				}
				return uint.MaxValue;
			}

			public static string SniffMinIntervalToString(SniffMinIntervalEnum enumItem)
			{
				if (enumItem == SniffMinIntervalEnum.Sniff_Min_Interval)
				{
					return "Unit: Slots (0.625ms)";
				}
				return "Invalid SniffMinInterval Value";
			}

			public static string SniffMinIntervalToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x2-0xFFFE = Unit: Slots (0.625ms)");
				return stringBuilder.ToString();
			}
		}

		public enum SniffAttemptEnum
		{
			Sniff_Attempt,
			InvalidSniffAttemptValue
		}

		public static class SniffAttemptInfo
		{
			public static SniffAttemptEnum ValueToSniffAttempt(uint value)
			{
				if (value >= 1 && value <= 32767)
				{
					return SniffAttemptEnum.Sniff_Attempt;
				}
				return SniffAttemptEnum.InvalidSniffAttemptValue;
			}

			public static uint SniffAttemptToValue(SniffAttemptEnum enumItem)
			{
				if (enumItem == SniffAttemptEnum.Sniff_Attempt)
				{
					return 1u;
				}
				return uint.MaxValue;
			}

			public static string SniffAttemptToString(SniffAttemptEnum enumItem)
			{
				if (enumItem == SniffAttemptEnum.Sniff_Attempt)
				{
					return "Unit: Slots (0.625ms)";
				}
				return "Invalid SniffAttempt Value";
			}

			public static string SniffAttemptToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x1-0x7FFF = Unit: Slots (0.625ms)");
				return stringBuilder.ToString();
			}
		}

		public enum SniffTimeoutEnum
		{
			Sniff_Timeout,
			InvalidSniffTimeoutValue
		}

		public static class SniffTimeoutInfo
		{
			public static SniffTimeoutEnum ValueToSniffTimeout(uint value)
			{
				if (value >= 1 && value <= 32767)
				{
					return SniffTimeoutEnum.Sniff_Timeout;
				}
				return SniffTimeoutEnum.InvalidSniffTimeoutValue;
			}

			public static uint SniffTimeoutToValue(SniffTimeoutEnum enumItem)
			{
				if (enumItem == SniffTimeoutEnum.Sniff_Timeout)
				{
					return 1u;
				}
				return uint.MaxValue;
			}

			public static string SniffTimeoutToString(SniffTimeoutEnum enumItem)
			{
				if (enumItem == SniffTimeoutEnum.Sniff_Timeout)
				{
					return "Unit: Slots (0.625ms)";
				}
				return "Invalid SniffTimeout Value";
			}

			public static string SniffTimeoutToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x1-0x7FFF = Unit: Slots (0.625ms)");
				return stringBuilder.ToString();
			}
		}

		private uint _ConnectionHandle;

		private uint _SniffMaxInterval;

		private uint _SniffMinInterval;

		private uint _SniffAttempt;

		private uint _SniffTimeout;

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

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

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

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

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

		public SniffMaxIntervalEnum GetSniffMaxIntervalAsSniffMaxIntervalEnum()
		{
			return SniffMaxIntervalInfo.ValueToSniffMaxInterval(_SniffMaxInterval);
		}

		public void SetSniffMaxIntervalAsSniffMaxIntervalEnum(SniffMaxIntervalEnum enumItem)
		{
			SniffMaxInterval = SniffMaxIntervalInfo.SniffMaxIntervalToValue(enumItem);
		}

		public SniffMinIntervalEnum GetSniffMinIntervalAsSniffMinIntervalEnum()
		{
			return SniffMinIntervalInfo.ValueToSniffMinInterval(_SniffMinInterval);
		}

		public void SetSniffMinIntervalAsSniffMinIntervalEnum(SniffMinIntervalEnum enumItem)
		{
			SniffMinInterval = SniffMinIntervalInfo.SniffMinIntervalToValue(enumItem);
		}

		public SniffAttemptEnum GetSniffAttemptAsSniffAttemptEnum()
		{
			return SniffAttemptInfo.ValueToSniffAttempt(_SniffAttempt);
		}

		public void SetSniffAttemptAsSniffAttemptEnum(SniffAttemptEnum enumItem)
		{
			SniffAttempt = SniffAttemptInfo.SniffAttemptToValue(enumItem);
		}

		public SniffTimeoutEnum GetSniffTimeoutAsSniffTimeoutEnum()
		{
			return SniffTimeoutInfo.ValueToSniffTimeout(_SniffTimeout);
		}

		public void SetSniffTimeoutAsSniffTimeoutEnum(SniffTimeoutEnum enumItem)
		{
			SniffTimeout = SniffTimeoutInfo.SniffTimeoutToValue(enumItem);
		}
	}

	private const uint _Opcode = 2051u;

	private Type[] expectedResponseTypes = new Type[3]
	{
		typeof(CommandStatusForHciSniffMode),
		typeof(HciModeChange),
		typeof(SniffSubratingEvent)
	};

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

	public uint Opcode => 2051u;

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

	public UserFieldsWrapper UserFields => _UserFields;

	public override void SetDefaultValues()
	{
		UserFields.SniffMaxInterval = 2048u;
		UserFields.SniffMinInterval = 2048u;
		UserFields.SniffAttempt = 8u;
		UserFields.SniffTimeout = 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.ConnectionHandle = bitBuilder.RemoveBitsAsUintLittleEndian(16);
		UserFields.SniffMaxInterval = bitBuilder.RemoveBitsAsUintLittleEndian(16);
		UserFields.SniffMinInterval = bitBuilder.RemoveBitsAsUintLittleEndian(16);
		UserFields.SniffAttempt = bitBuilder.RemoveBitsAsUintLittleEndian(16);
		UserFields.SniffTimeout = bitBuilder.RemoveBitsAsUintLittleEndian(16);
		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.AddBitsAsUintLittleEndian(UserFields.ConnectionHandle, 16);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.SniffMaxInterval, 16);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.SniffMinInterval, 16);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.SniffAttempt, 16);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.SniffTimeout, 16);
		_PayloadLength = (uint)((bitBuilder.GetNumberOfBits() - numberOfBits - 8) / 8);
		if ((bitBuilder.GetNumberOfBits() - numberOfBits - 8) % 8 != 0)
		{
			_PayloadLength++;
		}
		bitBuilder.ChangeBitsAsUint(numberOfBits, _PayloadLength, 8);
		return bitBuilder.ToString();
	}
}
