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

namespace QCRPG.TSL.FMHCI.Packets;

public class TxTest : PacketBase
{
	public class UserFieldsWrapper
	{
		public enum EnableRdsEnum
		{
			DISABLED,
			ENABLED,
			InvalidEnableRdsValue
		}

		public static class EnableRdsInfo
		{
			public static EnableRdsEnum ValueToEnableRds(uint value)
			{
				return value switch
				{
					0u => EnableRdsEnum.DISABLED, 
					1u => EnableRdsEnum.ENABLED, 
					_ => EnableRdsEnum.InvalidEnableRdsValue, 
				};
			}

			public static uint EnableRdsToValue(EnableRdsEnum enumItem)
			{
				return enumItem switch
				{
					EnableRdsEnum.DISABLED => 0u, 
					EnableRdsEnum.ENABLED => 1u, 
					_ => uint.MaxValue, 
				};
			}

			public static string EnableRdsToString(EnableRdsEnum enumItem)
			{
				return enumItem switch
				{
					EnableRdsEnum.DISABLED => "Disable RDS", 
					EnableRdsEnum.ENABLED => "Enable RDS", 
					_ => "Invalid EnableRds Value", 
				};
			}

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

		public enum PreEmphasisEnum
		{
			TIME_CONSTANT_75US,
			TIME_CONSTANT_50US,
			InvalidPreEmphasisValue
		}

		public static class PreEmphasisInfo
		{
			public static PreEmphasisEnum ValueToPreEmphasis(uint value)
			{
				return value switch
				{
					0u => PreEmphasisEnum.TIME_CONSTANT_75US, 
					1u => PreEmphasisEnum.TIME_CONSTANT_50US, 
					_ => PreEmphasisEnum.InvalidPreEmphasisValue, 
				};
			}

			public static uint PreEmphasisToValue(PreEmphasisEnum enumItem)
			{
				return enumItem switch
				{
					PreEmphasisEnum.TIME_CONSTANT_75US => 0u, 
					PreEmphasisEnum.TIME_CONSTANT_50US => 1u, 
					_ => uint.MaxValue, 
				};
			}

			public static string PreEmphasisToString(PreEmphasisEnum enumItem)
			{
				return enumItem switch
				{
					PreEmphasisEnum.TIME_CONSTANT_75US => "75us time constant (the pre-emphasis/de-emphasis timing typically used in the US and Japan)", 
					PreEmphasisEnum.TIME_CONSTANT_50US => "50us time constant (the pre-emphasis/de-emphasis timing typically used outside of the US and Japan)", 
					_ => "Invalid PreEmphasis Value", 
				};
			}

			public static string PreEmphasisToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = 75us time constant (the pre-emphasis/de-emphasis timing typically used in the US and Japan)");
				stringBuilder.AppendLine("0x1 = 50us time constant (the pre-emphasis/de-emphasis timing typically used outside of the US and Japan)");
				return stringBuilder.ToString();
			}
		}

		public enum StereoEnum
		{
			FORCE_MONO_TRANSMISSION,
			ENABLE_TX_STEREO_MODE,
			InvalidStereoValue
		}

		public static class StereoInfo
		{
			public static StereoEnum ValueToStereo(uint value)
			{
				return value switch
				{
					0u => StereoEnum.FORCE_MONO_TRANSMISSION, 
					1u => StereoEnum.ENABLE_TX_STEREO_MODE, 
					_ => StereoEnum.InvalidStereoValue, 
				};
			}

			public static uint StereoToValue(StereoEnum enumItem)
			{
				return enumItem switch
				{
					StereoEnum.FORCE_MONO_TRANSMISSION => 0u, 
					StereoEnum.ENABLE_TX_STEREO_MODE => 1u, 
					_ => uint.MaxValue, 
				};
			}

			public static string StereoToString(StereoEnum enumItem)
			{
				return enumItem switch
				{
					StereoEnum.FORCE_MONO_TRANSMISSION => "Force mono transmission", 
					StereoEnum.ENABLE_TX_STEREO_MODE => "Enable TX stereo mode", 
					_ => "Invalid Stereo Value", 
				};
			}

			public static string StereoToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = Force mono transmission");
				stringBuilder.AppendLine("0x1 = Enable TX stereo mode");
				return stringBuilder.ToString();
			}
		}

		public enum EnablePreEmphasisEnum
		{
			DISABLED,
			ENABLED,
			InvalidEnablePreEmphasisValue
		}

		public static class EnablePreEmphasisInfo
		{
			public static EnablePreEmphasisEnum ValueToEnablePreEmphasis(uint value)
			{
				return value switch
				{
					0u => EnablePreEmphasisEnum.DISABLED, 
					1u => EnablePreEmphasisEnum.ENABLED, 
					_ => EnablePreEmphasisEnum.InvalidEnablePreEmphasisValue, 
				};
			}

			public static uint EnablePreEmphasisToValue(EnablePreEmphasisEnum enumItem)
			{
				return enumItem switch
				{
					EnablePreEmphasisEnum.DISABLED => 0u, 
					EnablePreEmphasisEnum.ENABLED => 1u, 
					_ => uint.MaxValue, 
				};
			}

			public static string EnablePreEmphasisToString(EnablePreEmphasisEnum enumItem)
			{
				return enumItem switch
				{
					EnablePreEmphasisEnum.DISABLED => "Disable Pre-Emphasis", 
					EnablePreEmphasisEnum.ENABLED => "Enable Pre-Emphasis", 
					_ => "Invalid EnablePreEmphasis Value", 
				};
			}

			public static string EnablePreEmphasisToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = Disable Pre-Emphasis");
				stringBuilder.AppendLine("0x1 = Enable Pre-Emphasis");
				return stringBuilder.ToString();
			}
		}

		private uint _EnableRds;

		private uint _PreEmphasis;

		private uint _Stereo;

		private uint _EnablePreEmphasis;

		private uint _TuneFrequency;

		private uint _ModulationMultiplierForStereo;

		private uint _ModulationMultiplierForPilot;

		private uint _ModulationMultiplierForRds;

		private uint _ModulationMultiplierForMono;

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

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

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

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

		public uint TuneFrequency
		{
			get
			{
				return _TuneFrequency;
			}
			set
			{
				_TuneFrequency = value;
			}
		}

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

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

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

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

		public EnableRdsEnum GetEnableRdsAsEnableRdsEnum()
		{
			return EnableRdsInfo.ValueToEnableRds(_EnableRds);
		}

		public void SetEnableRdsAsEnableRdsEnum(EnableRdsEnum enumItem)
		{
			EnableRds = EnableRdsInfo.EnableRdsToValue(enumItem);
		}

		public PreEmphasisEnum GetPreEmphasisAsPreEmphasisEnum()
		{
			return PreEmphasisInfo.ValueToPreEmphasis(_PreEmphasis);
		}

		public void SetPreEmphasisAsPreEmphasisEnum(PreEmphasisEnum enumItem)
		{
			PreEmphasis = PreEmphasisInfo.PreEmphasisToValue(enumItem);
		}

		public StereoEnum GetStereoAsStereoEnum()
		{
			return StereoInfo.ValueToStereo(_Stereo);
		}

		public void SetStereoAsStereoEnum(StereoEnum enumItem)
		{
			Stereo = StereoInfo.StereoToValue(enumItem);
		}

		public EnablePreEmphasisEnum GetEnablePreEmphasisAsEnablePreEmphasisEnum()
		{
			return EnablePreEmphasisInfo.ValueToEnablePreEmphasis(_EnablePreEmphasis);
		}

		public void SetEnablePreEmphasisAsEnablePreEmphasisEnum(EnablePreEmphasisEnum enumItem)
		{
			EnablePreEmphasis = EnablePreEmphasisInfo.EnablePreEmphasisToValue(enumItem);
		}
	}

	private const uint _Opcode = 23555u;

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

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

	public uint Opcode => 23555u;

	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.EnableRds = bitBuilder.RemoveBitsAsUint(8);
		UserFields.PreEmphasis = bitBuilder.RemoveBitsAsUint(8);
		UserFields.Stereo = bitBuilder.RemoveBitsAsUint(8);
		UserFields.EnablePreEmphasis = bitBuilder.RemoveBitsAsUint(8);
		UserFields.TuneFrequency = bitBuilder.RemoveBitsAsUintLittleEndian(32);
		UserFields.ModulationMultiplierForStereo = bitBuilder.RemoveBitsAsUint(8);
		UserFields.ModulationMultiplierForPilot = bitBuilder.RemoveBitsAsUint(8);
		UserFields.ModulationMultiplierForRds = bitBuilder.RemoveBitsAsUint(8);
		UserFields.ModulationMultiplierForMono = 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.EnableRds, 8);
		bitBuilder.AddBitsAsUint(UserFields.PreEmphasis, 8);
		bitBuilder.AddBitsAsUint(UserFields.Stereo, 8);
		bitBuilder.AddBitsAsUint(UserFields.EnablePreEmphasis, 8);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.TuneFrequency, 32);
		bitBuilder.AddBitsAsUint(UserFields.ModulationMultiplierForStereo, 8);
		bitBuilder.AddBitsAsUint(UserFields.ModulationMultiplierForPilot, 8);
		bitBuilder.AddBitsAsUint(UserFields.ModulationMultiplierForRds, 8);
		bitBuilder.AddBitsAsUint(UserFields.ModulationMultiplierForMono, 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.EnableRds > 1)
		{
			list.Add("Maximum allowed value for Enable RDS is 0x1");
		}
		if (UserFields.PreEmphasis > 1)
		{
			list.Add("Maximum allowed value for Pre Emphasis is 0x1");
		}
		if (UserFields.Stereo > 1)
		{
			list.Add("Maximum allowed value for Stereo is 0x1");
		}
		if (UserFields.EnablePreEmphasis > 1)
		{
			list.Add("Maximum allowed value for Enable Pre Emphasis is 0x1");
		}
		return list;
	}
}
