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

namespace QCRPG.TSL.FM.Packets;

public class AudioControl : PacketBase
{
	public class UserFieldsWrapper
	{
		public enum RxToBluetoothEnum
		{
			AUDIO_TO_BT_OFF,
			AUDIO_TO_BT_ON,
			InvalidRxToBluetoothValue
		}

		public static class RxToBluetoothInfo
		{
			public static RxToBluetoothEnum ValueToRxToBluetooth(uint value)
			{
				return value switch
				{
					0u => RxToBluetoothEnum.AUDIO_TO_BT_OFF, 
					1u => RxToBluetoothEnum.AUDIO_TO_BT_ON, 
					_ => RxToBluetoothEnum.InvalidRxToBluetoothValue, 
				};
			}

			public static uint RxToBluetoothToValue(RxToBluetoothEnum enumItem)
			{
				return enumItem switch
				{
					RxToBluetoothEnum.AUDIO_TO_BT_OFF => 0u, 
					RxToBluetoothEnum.AUDIO_TO_BT_ON => 1u, 
					_ => uint.MaxValue, 
				};
			}

			public static string RxToBluetoothToString(RxToBluetoothEnum enumItem)
			{
				return enumItem switch
				{
					RxToBluetoothEnum.AUDIO_TO_BT_OFF => "Audio output to Bluetooth off", 
					RxToBluetoothEnum.AUDIO_TO_BT_ON => "Audio output to Bluetooth on", 
					_ => "Invalid RxToBluetooth Value", 
				};
			}

			public static string RxToBluetoothToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = Audio output to Bluetooth off");
				stringBuilder.AppendLine("0x1 = Audio output to Bluetooth on");
				return stringBuilder.ToString();
			}
		}

		public enum I2sControlEnum
		{
			SLAVE,
			MASTER,
			InvalidI2sControlValue
		}

		public static class I2sControlInfo
		{
			public static I2sControlEnum ValueToI2sControl(uint value)
			{
				return value switch
				{
					0u => I2sControlEnum.SLAVE, 
					1u => I2sControlEnum.MASTER, 
					_ => I2sControlEnum.InvalidI2sControlValue, 
				};
			}

			public static uint I2sControlToValue(I2sControlEnum enumItem)
			{
				return enumItem switch
				{
					I2sControlEnum.SLAVE => 0u, 
					I2sControlEnum.MASTER => 1u, 
					_ => uint.MaxValue, 
				};
			}

			public static string I2sControlToString(I2sControlEnum enumItem)
			{
				return enumItem switch
				{
					I2sControlEnum.SLAVE => "FM core is I2S slave", 
					I2sControlEnum.MASTER => "FM core is I2S master", 
					_ => "Invalid I2sControl Value", 
				};
			}

			public static string I2sControlToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = FM core is I2S slave");
				stringBuilder.AppendLine("0x1 = FM core is I2S master");
				return stringBuilder.ToString();
			}
		}

		public enum AudioTxEnum
		{
			AUDIO_INPUT_OFF,
			DIGITAL_I2S_INPUT,
			InvalidAudioTxValue
		}

		public static class AudioTxInfo
		{
			public static AudioTxEnum ValueToAudioTx(uint value)
			{
				return value switch
				{
					0u => AudioTxEnum.AUDIO_INPUT_OFF, 
					1u => AudioTxEnum.DIGITAL_I2S_INPUT, 
					_ => AudioTxEnum.InvalidAudioTxValue, 
				};
			}

			public static uint AudioTxToValue(AudioTxEnum enumItem)
			{
				return enumItem switch
				{
					AudioTxEnum.AUDIO_INPUT_OFF => 0u, 
					AudioTxEnum.DIGITAL_I2S_INPUT => 1u, 
					_ => uint.MaxValue, 
				};
			}

			public static string AudioTxToString(AudioTxEnum enumItem)
			{
				return enumItem switch
				{
					AudioTxEnum.AUDIO_INPUT_OFF => "Audio input off", 
					AudioTxEnum.DIGITAL_I2S_INPUT => "Digital I2S input", 
					_ => "Invalid AudioTx Value", 
				};
			}

			public static string AudioTxToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = Audio input off");
				stringBuilder.AppendLine("0x1 = Digital I2S input");
				return stringBuilder.ToString();
			}
		}

		public enum AudioRxEnum
		{
			AUDIO_OUTPUT_OFF,
			ANALOG_STEREO_OUTPUTS,
			DIGITAL_I2S_OUTPUT,
			ANALOG_AND_DIGITAL_OUTPUTS,
			InvalidAudioRxValue
		}

		public static class AudioRxInfo
		{
			public static AudioRxEnum ValueToAudioRx(uint value)
			{
				return value switch
				{
					0u => AudioRxEnum.AUDIO_OUTPUT_OFF, 
					1u => AudioRxEnum.ANALOG_STEREO_OUTPUTS, 
					2u => AudioRxEnum.DIGITAL_I2S_OUTPUT, 
					3u => AudioRxEnum.ANALOG_AND_DIGITAL_OUTPUTS, 
					_ => AudioRxEnum.InvalidAudioRxValue, 
				};
			}

			public static uint AudioRxToValue(AudioRxEnum enumItem)
			{
				return enumItem switch
				{
					AudioRxEnum.AUDIO_OUTPUT_OFF => 0u, 
					AudioRxEnum.ANALOG_STEREO_OUTPUTS => 1u, 
					AudioRxEnum.DIGITAL_I2S_OUTPUT => 2u, 
					AudioRxEnum.ANALOG_AND_DIGITAL_OUTPUTS => 3u, 
					_ => uint.MaxValue, 
				};
			}

			public static string AudioRxToString(AudioRxEnum enumItem)
			{
				return enumItem switch
				{
					AudioRxEnum.AUDIO_OUTPUT_OFF => "Audio output off", 
					AudioRxEnum.ANALOG_STEREO_OUTPUTS => "Analog stereo outputs", 
					AudioRxEnum.DIGITAL_I2S_OUTPUT => "Digital I2S output", 
					AudioRxEnum.ANALOG_AND_DIGITAL_OUTPUTS => "Analog and digital outputs", 
					_ => "Invalid AudioRx Value", 
				};
			}

			public static string AudioRxToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = Audio output off");
				stringBuilder.AppendLine("0x1 = Analog stereo outputs");
				stringBuilder.AppendLine("0x2 = Digital I2S output");
				stringBuilder.AppendLine("0x3 = Analog and digital outputs");
				return stringBuilder.ToString();
			}
		}

		private const uint _RegisterAddress = 12u;

		private const uint _Unused = 0u;

		private uint _RxToBluetooth;

		private uint _I2sControl;

		private uint _AudioTx;

		private uint _AudioRx;

		public uint RegisterAddress => 12u;

		public uint Unused => 0u;

		public uint RxToBluetooth
		{
			get
			{
				return _RxToBluetooth;
			}
			set
			{
				if (value > 1)
				{
					throw new Exception("Maximum possible value for RxToBluetooth is 0x1");
				}
				_RxToBluetooth = value;
			}
		}

		public uint I2sControl
		{
			get
			{
				return _I2sControl;
			}
			set
			{
				if (value > 1)
				{
					throw new Exception("Maximum possible value for I2sControl is 0x1");
				}
				_I2sControl = value;
			}
		}

		public uint AudioTx
		{
			get
			{
				return _AudioTx;
			}
			set
			{
				if (value > 1)
				{
					throw new Exception("Maximum possible value for AudioTx is 0x1");
				}
				_AudioTx = value;
			}
		}

		public uint AudioRx
		{
			get
			{
				return _AudioRx;
			}
			set
			{
				if (value > 3)
				{
					throw new Exception("Maximum possible value for AudioRx is 0x3");
				}
				_AudioRx = value;
			}
		}

		public RegisterMapEnum GetRegisterAddressAsRegisterMapEnum()
		{
			return RegisterMapInfo.ValueToRegisterMap(12u);
		}

		public RxToBluetoothEnum GetRxToBluetoothAsRxToBluetoothEnum()
		{
			return RxToBluetoothInfo.ValueToRxToBluetooth(_RxToBluetooth);
		}

		public void SetRxToBluetoothAsRxToBluetoothEnum(RxToBluetoothEnum enumItem)
		{
			RxToBluetooth = RxToBluetoothInfo.RxToBluetoothToValue(enumItem);
		}

		public I2sControlEnum GetI2sControlAsI2sControlEnum()
		{
			return I2sControlInfo.ValueToI2sControl(_I2sControl);
		}

		public void SetI2sControlAsI2sControlEnum(I2sControlEnum enumItem)
		{
			I2sControl = I2sControlInfo.I2sControlToValue(enumItem);
		}

		public AudioTxEnum GetAudioTxAsAudioTxEnum()
		{
			return AudioTxInfo.ValueToAudioTx(_AudioTx);
		}

		public void SetAudioTxAsAudioTxEnum(AudioTxEnum enumItem)
		{
			AudioTx = AudioTxInfo.AudioTxToValue(enumItem);
		}

		public AudioRxEnum GetAudioRxAsAudioRxEnum()
		{
			return AudioRxInfo.ValueToAudioRx(_AudioRx);
		}

		public void SetAudioRxAsAudioRxEnum(AudioRxEnum enumItem)
		{
			AudioRx = AudioRxInfo.AudioRxToValue(enumItem);
		}
	}

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

	private PacketInfoBase info;

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

	public UserFieldsWrapper UserFields => _UserFields;

	protected override bool FromBitBuilder(ref BitBuilder bitBuilder)
	{
		if (bitBuilder.RemoveBitsAsUint(8) != UserFields.RegisterAddress)
		{
			return false;
		}
		if (bitBuilder.RemoveBitsAsUint(3) != UserFields.Unused)
		{
			return false;
		}
		UserFields.RxToBluetooth = bitBuilder.RemoveBitsAsUint(1);
		UserFields.I2sControl = bitBuilder.RemoveBitsAsUint(1);
		UserFields.AudioTx = bitBuilder.RemoveBitsAsUint(1);
		UserFields.AudioRx = bitBuilder.RemoveBitsAsUint(2);
		if (bitBuilder.GetNumberOfBits() > 7)
		{
			return false;
		}
		return true;
	}

	public override string ToBitString()
	{
		BitBuilder bitBuilder = new BitBuilder();
		bitBuilder.AddBitsAsUint(UserFields.RegisterAddress, 8);
		bitBuilder.AddBitsAsUint(UserFields.Unused, 3);
		bitBuilder.AddBitsAsUint(UserFields.RxToBluetooth, 1);
		bitBuilder.AddBitsAsUint(UserFields.I2sControl, 1);
		bitBuilder.AddBitsAsUint(UserFields.AudioTx, 1);
		bitBuilder.AddBitsAsUint(UserFields.AudioRx, 2);
		return bitBuilder.ToString();
	}
}
