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

namespace QCRPG.TSL.BT.Packets;

public class A2dpWriteA2dpConfig : PacketBase
{
	public class UserFieldsWrapper
	{
		public enum TransportEnum
		{
			SLIMBUS,
			InvalidTransportValue
		}

		public static class TransportInfo
		{
			public static TransportEnum ValueToTransport(uint value)
			{
				if (value == 0)
				{
					return TransportEnum.SLIMBUS;
				}
				return TransportEnum.InvalidTransportValue;
			}

			public static uint TransportToValue(TransportEnum enumItem)
			{
				if (enumItem == TransportEnum.SLIMBUS)
				{
					return 0u;
				}
				return uint.MaxValue;
			}

			public static string TransportToString(TransportEnum enumItem)
			{
				if (enumItem == TransportEnum.SLIMBUS)
				{
					return "Slimbus";
				}
				return "Invalid Transport Value";
			}

			public static string TransportToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = Slimbus");
				return stringBuilder.ToString();
			}
		}

		public enum StartStreamEnum
		{
			StartPending,
			StartNow,
			InvalidStartStreamValue
		}

		public static class StartStreamInfo
		{
			public static StartStreamEnum ValueToStartStream(uint value)
			{
				return value switch
				{
					0u => StartStreamEnum.StartPending, 
					1u => StartStreamEnum.StartNow, 
					_ => StartStreamEnum.InvalidStartStreamValue, 
				};
			}

			public static uint StartStreamToValue(StartStreamEnum enumItem)
			{
				return enumItem switch
				{
					StartStreamEnum.StartPending => 0u, 
					StartStreamEnum.StartNow => 1u, 
					_ => uint.MaxValue, 
				};
			}

			public static string StartStreamToString(StartStreamEnum enumItem)
			{
				return enumItem switch
				{
					StartStreamEnum.StartPending => "Start Pending", 
					StartStreamEnum.StartNow => "Start Now", 
					_ => "Invalid StartStream Value", 
				};
			}

			public static string StartStreamToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = Start Pending");
				stringBuilder.AppendLine("0x1 = Start Now");
				return stringBuilder.ToString();
			}
		}

		public enum TwsEnableEnum
		{
			TWS_Disable,
			TWS_Enable,
			InvalidTwsEnableValue
		}

		public static class TwsEnableInfo
		{
			public static TwsEnableEnum ValueToTwsEnable(uint value)
			{
				return value switch
				{
					0u => TwsEnableEnum.TWS_Disable, 
					1u => TwsEnableEnum.TWS_Enable, 
					_ => TwsEnableEnum.InvalidTwsEnableValue, 
				};
			}

			public static uint TwsEnableToValue(TwsEnableEnum enumItem)
			{
				return enumItem switch
				{
					TwsEnableEnum.TWS_Disable => 0u, 
					TwsEnableEnum.TWS_Enable => 1u, 
					_ => uint.MaxValue, 
				};
			}

			public static string TwsEnableToString(TwsEnableEnum enumItem)
			{
				return enumItem switch
				{
					TwsEnableEnum.TWS_Disable => "TWS Disable (Legacy)", 
					TwsEnableEnum.TWS_Enable => "TWS Enable", 
					_ => "Invalid TwsEnable Value", 
				};
			}

			public static string TwsEnableToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = TWS Disable (Legacy)");
				stringBuilder.AppendLine("0x1 = TWS Enable");
				return stringBuilder.ToString();
			}
		}

		public enum ChannelModeEnum
		{
			LEFT_CHANNEL,
			RIGHT_CHANNEL,
			STEREO,
			InvalidChannelModeValue
		}

		public static class ChannelModeInfo
		{
			public static ChannelModeEnum ValueToChannelMode(uint value)
			{
				return value switch
				{
					1u => ChannelModeEnum.LEFT_CHANNEL, 
					2u => ChannelModeEnum.RIGHT_CHANNEL, 
					3u => ChannelModeEnum.STEREO, 
					_ => ChannelModeEnum.InvalidChannelModeValue, 
				};
			}

			public static uint ChannelModeToValue(ChannelModeEnum enumItem)
			{
				return enumItem switch
				{
					ChannelModeEnum.LEFT_CHANNEL => 1u, 
					ChannelModeEnum.RIGHT_CHANNEL => 2u, 
					ChannelModeEnum.STEREO => 3u, 
					_ => uint.MaxValue, 
				};
			}

			public static string ChannelModeToString(ChannelModeEnum enumItem)
			{
				return enumItem switch
				{
					ChannelModeEnum.LEFT_CHANNEL => "Left Channel", 
					ChannelModeEnum.RIGHT_CHANNEL => "Right Channel", 
					ChannelModeEnum.STEREO => "Stereo", 
					_ => "Invalid ChannelMode Value", 
				};
			}

			public static string ChannelModeToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x1 = Left Channel");
				stringBuilder.AppendLine("0x2 = Right Channel");
				stringBuilder.AppendLine("0x3 = Stereo");
				return stringBuilder.ToString();
			}
		}

		private const uint _SubOpcode = 10u;

		private uint _Codec;

		private uint _Transport;

		private uint _TransportStreamType;

		private uint _StreamHandle;

		private uint _MaxLatency;

		private uint _DelayReportEnable;

		private uint _ScmsTEnable;

		private uint _ScmsTHeader;

		private uint _SamplingFrequency;

		private uint _ConnectionHandle;

		private uint _L2capCid;

		private uint _L2capMtuSize;

		private uint _StartStream;

		private uint _TwsEnable;

		private uint _ChannelMode;

		private uint _TtpOffset;

		private List<uint> _CodecInfoList = new List<uint>(new uint[20]);

		public uint SubOpcode => 10u;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

		public List<uint> CodecInfoList => _CodecInfoList;

		public CodecTypesEnum GetCodecAsCodecTypesEnum()
		{
			return CodecTypesInfo.ValueToCodecTypes(_Codec);
		}

		public void SetCodecAsCodecTypesEnum(CodecTypesEnum enumItem)
		{
			Codec = CodecTypesInfo.CodecTypesToValue(enumItem);
		}

		public TransportEnum GetTransportAsTransportEnum()
		{
			return TransportInfo.ValueToTransport(_Transport);
		}

		public void SetTransportAsTransportEnum(TransportEnum enumItem)
		{
			Transport = TransportInfo.TransportToValue(enumItem);
		}

		public CodecTypesEnum GetTransportStreamTypeAsCodecTypesEnum()
		{
			return CodecTypesInfo.ValueToCodecTypes(_TransportStreamType);
		}

		public void SetTransportStreamTypeAsCodecTypesEnum(CodecTypesEnum enumItem)
		{
			TransportStreamType = CodecTypesInfo.CodecTypesToValue(enumItem);
		}

		public StartStreamEnum GetStartStreamAsStartStreamEnum()
		{
			return StartStreamInfo.ValueToStartStream(_StartStream);
		}

		public void SetStartStreamAsStartStreamEnum(StartStreamEnum enumItem)
		{
			StartStream = StartStreamInfo.StartStreamToValue(enumItem);
		}

		public TwsEnableEnum GetTwsEnableAsTwsEnableEnum()
		{
			return TwsEnableInfo.ValueToTwsEnable(_TwsEnable);
		}

		public void SetTwsEnableAsTwsEnableEnum(TwsEnableEnum enumItem)
		{
			TwsEnable = TwsEnableInfo.TwsEnableToValue(enumItem);
		}

		public ChannelModeEnum GetChannelModeAsChannelModeEnum()
		{
			return ChannelModeInfo.ValueToChannelMode(_ChannelMode);
		}

		public void SetChannelModeAsChannelModeEnum(ChannelModeEnum enumItem)
		{
			ChannelMode = ChannelModeInfo.ChannelModeToValue(enumItem);
		}
	}

	private const uint _Opcode = 64522u;

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

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

	public uint Opcode => 64522u;

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

	public UserFieldsWrapper UserFields => _UserFields;

	public override void SetDefaultValues()
	{
		UserFields.Codec = 0u;
		UserFields.Transport = 0u;
		UserFields.TransportStreamType = 0u;
		UserFields.StreamHandle = 0u;
		UserFields.MaxLatency = 0u;
		UserFields.DelayReportEnable = 0u;
		UserFields.ScmsTEnable = 0u;
		UserFields.ScmsTHeader = 2u;
		UserFields.SamplingFrequency = 48000u;
		UserFields.ConnectionHandle = 0u;
		UserFields.L2capCid = 0u;
		UserFields.L2capMtuSize = 0u;
		UserFields.StartStream = 0u;
		UserFields.TwsEnable = 0u;
		UserFields.ChannelMode = 1u;
		UserFields.TtpOffset = 50u;
	}

	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;
		}
		if (bitBuilder.RemoveBitsAsUint(8) != UserFields.SubOpcode)
		{
			return false;
		}
		UserFields.Codec = bitBuilder.RemoveBitsAsUint(8);
		UserFields.Transport = bitBuilder.RemoveBitsAsUint(8);
		UserFields.TransportStreamType = bitBuilder.RemoveBitsAsUint(8);
		UserFields.StreamHandle = bitBuilder.RemoveBitsAsUint(8);
		UserFields.MaxLatency = bitBuilder.RemoveBitsAsUint(8);
		UserFields.DelayReportEnable = bitBuilder.RemoveBitsAsUint(8);
		UserFields.ScmsTEnable = bitBuilder.RemoveBitsAsUint(8);
		UserFields.ScmsTHeader = bitBuilder.RemoveBitsAsUint(8);
		UserFields.SamplingFrequency = bitBuilder.RemoveBitsAsUintLittleEndian(16);
		UserFields.ConnectionHandle = bitBuilder.RemoveBitsAsUintLittleEndian(16);
		UserFields.L2capCid = bitBuilder.RemoveBitsAsUintLittleEndian(16);
		UserFields.L2capMtuSize = bitBuilder.RemoveBitsAsUintLittleEndian(16);
		UserFields.StartStream = bitBuilder.RemoveBitsAsUint(8);
		UserFields.TwsEnable = bitBuilder.RemoveBitsAsUint(8);
		UserFields.ChannelMode = bitBuilder.RemoveBitsAsUint(8);
		UserFields.TtpOffset = bitBuilder.RemoveBitsAsUintLittleEndian(16);
		for (int num = UserFields.CodecInfoList.Count - 1; num >= 0; num--)
		{
			UserFields.CodecInfoList[num] = 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.SubOpcode, 8);
		bitBuilder.AddBitsAsUint(UserFields.Codec, 8);
		bitBuilder.AddBitsAsUint(UserFields.Transport, 8);
		bitBuilder.AddBitsAsUint(UserFields.TransportStreamType, 8);
		bitBuilder.AddBitsAsUint(UserFields.StreamHandle, 8);
		bitBuilder.AddBitsAsUint(UserFields.MaxLatency, 8);
		bitBuilder.AddBitsAsUint(UserFields.DelayReportEnable, 8);
		bitBuilder.AddBitsAsUint(UserFields.ScmsTEnable, 8);
		bitBuilder.AddBitsAsUint(UserFields.ScmsTHeader, 8);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.SamplingFrequency, 16);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.ConnectionHandle, 16);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.L2capCid, 16);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.L2capMtuSize, 16);
		bitBuilder.AddBitsAsUint(UserFields.StartStream, 8);
		bitBuilder.AddBitsAsUint(UserFields.TwsEnable, 8);
		bitBuilder.AddBitsAsUint(UserFields.ChannelMode, 8);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.TtpOffset, 16);
		for (int num = UserFields.CodecInfoList.Count - 1; num >= 0; num--)
		{
			if (UserFields.CodecInfoList[num] > 255)
			{
				throw new Exception("UserFields.CodecInfoList[i] is > 0xFF");
			}
			bitBuilder.AddBitsAsUint(UserFields.CodecInfoList[num], 8);
		}
		_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.StreamHandle > 1)
		{
			list.Add("Maximum allowed value for Stream Handle is 0x1");
		}
		if (UserFields.StartStream > 1)
		{
			list.Add("Maximum allowed value for Start Stream is 0x1");
		}
		if (UserFields.TwsEnable > 1)
		{
			list.Add("Maximum allowed value for TWS Enable is 0x1");
		}
		if (UserFields.ChannelMode > 3)
		{
			list.Add("Maximum allowed value for Channel Mode is 0x3");
		}
		return list;
	}
}
