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

namespace QCRPG.TSL.FMHCI.Packets;

public class ToneConfiguration : PacketBase
{
	public class UserFieldsWrapper
	{
		public enum LeftChannelControlEnum
		{
			DISABLE_INTERNAL_TONE,
			ENABLE_INTERNAL_TONE,
			InvalidLeftChannelControlValue
		}

		public static class LeftChannelControlInfo
		{
			public static LeftChannelControlEnum ValueToLeftChannelControl(uint value)
			{
				return value switch
				{
					0u => LeftChannelControlEnum.DISABLE_INTERNAL_TONE, 
					1u => LeftChannelControlEnum.ENABLE_INTERNAL_TONE, 
					_ => LeftChannelControlEnum.InvalidLeftChannelControlValue, 
				};
			}

			public static uint LeftChannelControlToValue(LeftChannelControlEnum enumItem)
			{
				return enumItem switch
				{
					LeftChannelControlEnum.DISABLE_INTERNAL_TONE => 0u, 
					LeftChannelControlEnum.ENABLE_INTERNAL_TONE => 1u, 
					_ => uint.MaxValue, 
				};
			}

			public static string LeftChannelControlToString(LeftChannelControlEnum enumItem)
			{
				return enumItem switch
				{
					LeftChannelControlEnum.DISABLE_INTERNAL_TONE => "Disable left channel internal tone", 
					LeftChannelControlEnum.ENABLE_INTERNAL_TONE => "Enable left channel internal tone", 
					_ => "Invalid LeftChannelControl Value", 
				};
			}

			public static string LeftChannelControlToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = Disable left channel internal tone");
				stringBuilder.AppendLine("0x1 = Enable left channel internal tone");
				return stringBuilder.ToString();
			}
		}

		public enum RightChannelControlEnum
		{
			DISABLE_INTERNAL_TONE,
			ENABLE_INTERNAL_TONE,
			InvalidRightChannelControlValue
		}

		public static class RightChannelControlInfo
		{
			public static RightChannelControlEnum ValueToRightChannelControl(uint value)
			{
				return value switch
				{
					0u => RightChannelControlEnum.DISABLE_INTERNAL_TONE, 
					1u => RightChannelControlEnum.ENABLE_INTERNAL_TONE, 
					_ => RightChannelControlEnum.InvalidRightChannelControlValue, 
				};
			}

			public static uint RightChannelControlToValue(RightChannelControlEnum enumItem)
			{
				return enumItem switch
				{
					RightChannelControlEnum.DISABLE_INTERNAL_TONE => 0u, 
					RightChannelControlEnum.ENABLE_INTERNAL_TONE => 1u, 
					_ => uint.MaxValue, 
				};
			}

			public static string RightChannelControlToString(RightChannelControlEnum enumItem)
			{
				return enumItem switch
				{
					RightChannelControlEnum.DISABLE_INTERNAL_TONE => "Disable right channel internal tone", 
					RightChannelControlEnum.ENABLE_INTERNAL_TONE => "Enable right channel internal tone", 
					_ => "Invalid RightChannelControl Value", 
				};
			}

			public static string RightChannelControlToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = Disable right channel internal tone");
				stringBuilder.AppendLine("0x1 = Enable right channel internal tone");
				return stringBuilder.ToString();
			}
		}

		private uint _LeftChannelControl;

		private uint _RightChannelControl;

		private uint _ToneScalingFactorIndex;

		private uint _LeftChannelFrequency;

		private uint _RightChannelFrequency;

		private uint _LeftChannelPhase;

		private uint _RightChannelPhase;

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

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

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

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

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

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

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

		public LeftChannelControlEnum GetLeftChannelControlAsLeftChannelControlEnum()
		{
			return LeftChannelControlInfo.ValueToLeftChannelControl(_LeftChannelControl);
		}

		public void SetLeftChannelControlAsLeftChannelControlEnum(LeftChannelControlEnum enumItem)
		{
			LeftChannelControl = LeftChannelControlInfo.LeftChannelControlToValue(enumItem);
		}

		public RightChannelControlEnum GetRightChannelControlAsRightChannelControlEnum()
		{
			return RightChannelControlInfo.ValueToRightChannelControl(_RightChannelControl);
		}

		public void SetRightChannelControlAsRightChannelControlEnum(RightChannelControlEnum enumItem)
		{
			RightChannelControl = RightChannelControlInfo.RightChannelControlToValue(enumItem);
		}
	}

	private const uint _Opcode = 23562u;

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

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

	public uint Opcode => 23562u;

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

	public UserFieldsWrapper UserFields => _UserFields;

	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.LeftChannelControl = bitBuilder.RemoveBitsAsUint(8);
		UserFields.RightChannelControl = bitBuilder.RemoveBitsAsUint(8);
		UserFields.ToneScalingFactorIndex = bitBuilder.RemoveBitsAsUint(8);
		UserFields.LeftChannelFrequency = bitBuilder.RemoveBitsAsUint(8);
		UserFields.RightChannelFrequency = bitBuilder.RemoveBitsAsUint(8);
		UserFields.LeftChannelPhase = bitBuilder.RemoveBitsAsUint(8);
		UserFields.RightChannelPhase = 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.LeftChannelControl, 8);
		bitBuilder.AddBitsAsUint(UserFields.RightChannelControl, 8);
		bitBuilder.AddBitsAsUint(UserFields.ToneScalingFactorIndex, 8);
		bitBuilder.AddBitsAsUint(UserFields.LeftChannelFrequency, 8);
		bitBuilder.AddBitsAsUint(UserFields.RightChannelFrequency, 8);
		bitBuilder.AddBitsAsUint(UserFields.LeftChannelPhase, 8);
		bitBuilder.AddBitsAsUint(UserFields.RightChannelPhase, 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.LeftChannelControl > 1)
		{
			list.Add("Maximum allowed value for Left Channel Control is 0x1");
		}
		if (UserFields.RightChannelControl > 1)
		{
			list.Add("Maximum allowed value for Right Channel Control is 0x1");
		}
		if (UserFields.ToneScalingFactorIndex > 12)
		{
			list.Add("Maximum allowed value for Tone Scaling Factor Index is 0xC");
		}
		return list;
	}
}
