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

namespace QCRPG.TSL.FM.Packets;

public class RdsAdvanceControl : PacketBase
{
	public class UserFieldsWrapper
	{
		public enum AutomaticAfSearchEnum
		{
			DO_NOT_SEARCH,
			AUTOMATICALLY_SEARCH,
			InvalidAutomaticAfSearchValue
		}

		public static class AutomaticAfSearchInfo
		{
			public static AutomaticAfSearchEnum ValueToAutomaticAfSearch(uint value)
			{
				return value switch
				{
					0u => AutomaticAfSearchEnum.DO_NOT_SEARCH, 
					1u => AutomaticAfSearchEnum.AUTOMATICALLY_SEARCH, 
					_ => AutomaticAfSearchEnum.InvalidAutomaticAfSearchValue, 
				};
			}

			public static uint AutomaticAfSearchToValue(AutomaticAfSearchEnum enumItem)
			{
				return enumItem switch
				{
					AutomaticAfSearchEnum.DO_NOT_SEARCH => 0u, 
					AutomaticAfSearchEnum.AUTOMATICALLY_SEARCH => 1u, 
					_ => uint.MaxValue, 
				};
			}

			public static string AutomaticAfSearchToString(AutomaticAfSearchEnum enumItem)
			{
				return enumItem switch
				{
					AutomaticAfSearchEnum.DO_NOT_SEARCH => "Do not automatically search for alternative frequency", 
					AutomaticAfSearchEnum.AUTOMATICALLY_SEARCH => "Automatically search for alternative frequencies, if available, when the signal qualities is degraded", 
					_ => "Invalid AutomaticAfSearch Value", 
				};
			}

			public static string AutomaticAfSearchToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = Do not automatically search for alternative frequency");
				stringBuilder.AppendLine("0x1 = Automatically search for alternative frequencies, if available, when the signal qualities is degraded");
				return stringBuilder.ToString();
			}
		}

		public enum ProcessAlternativeFrequencyListEnum
		{
			DO_NOT_PROCESS,
			PROCESS,
			InvalidProcessAlternativeFrequencyListValue
		}

		public static class ProcessAlternativeFrequencyListInfo
		{
			public static ProcessAlternativeFrequencyListEnum ValueToProcessAlternativeFrequencyList(uint value)
			{
				return value switch
				{
					0u => ProcessAlternativeFrequencyListEnum.DO_NOT_PROCESS, 
					1u => ProcessAlternativeFrequencyListEnum.PROCESS, 
					_ => ProcessAlternativeFrequencyListEnum.InvalidProcessAlternativeFrequencyListValue, 
				};
			}

			public static uint ProcessAlternativeFrequencyListToValue(ProcessAlternativeFrequencyListEnum enumItem)
			{
				return enumItem switch
				{
					ProcessAlternativeFrequencyListEnum.DO_NOT_PROCESS => 0u, 
					ProcessAlternativeFrequencyListEnum.PROCESS => 1u, 
					_ => uint.MaxValue, 
				};
			}

			public static string ProcessAlternativeFrequencyListToString(ProcessAlternativeFrequencyListEnum enumItem)
			{
				return enumItem switch
				{
					ProcessAlternativeFrequencyListEnum.DO_NOT_PROCESS => "Do not process RDS Alternative Frequency (AF) list", 
					ProcessAlternativeFrequencyListEnum.PROCESS => "Process RDS Alternative Frequency list", 
					_ => "Invalid ProcessAlternativeFrequencyList Value", 
				};
			}

			public static string ProcessAlternativeFrequencyListToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = Do not process RDS Alternative Frequency (AF) list");
				stringBuilder.AppendLine("0x1 = Process RDS Alternative Frequency list");
				return stringBuilder.ToString();
			}
		}

		public enum ProcessProgramServiceNameEnum
		{
			DO_NOT_PROCESS,
			PROCESS,
			InvalidProcessProgramServiceNameValue
		}

		public static class ProcessProgramServiceNameInfo
		{
			public static ProcessProgramServiceNameEnum ValueToProcessProgramServiceName(uint value)
			{
				return value switch
				{
					0u => ProcessProgramServiceNameEnum.DO_NOT_PROCESS, 
					1u => ProcessProgramServiceNameEnum.PROCESS, 
					_ => ProcessProgramServiceNameEnum.InvalidProcessProgramServiceNameValue, 
				};
			}

			public static uint ProcessProgramServiceNameToValue(ProcessProgramServiceNameEnum enumItem)
			{
				return enumItem switch
				{
					ProcessProgramServiceNameEnum.DO_NOT_PROCESS => 0u, 
					ProcessProgramServiceNameEnum.PROCESS => 1u, 
					_ => uint.MaxValue, 
				};
			}

			public static string ProcessProgramServiceNameToString(ProcessProgramServiceNameEnum enumItem)
			{
				return enumItem switch
				{
					ProcessProgramServiceNameEnum.DO_NOT_PROCESS => "Do not process RDS Program Service (PS) name", 
					ProcessProgramServiceNameEnum.PROCESS => "Process RDS Program Service name", 
					_ => "Invalid ProcessProgramServiceName Value", 
				};
			}

			public static string ProcessProgramServiceNameToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = Do not process RDS Program Service (PS) name");
				stringBuilder.AppendLine("0x1 = Process RDS Program Service name");
				return stringBuilder.ToString();
			}
		}

		public enum ProcessRadioTextEnum
		{
			DO_NOT_PROCESS,
			PROCESS,
			InvalidProcessRadioTextValue
		}

		public static class ProcessRadioTextInfo
		{
			public static ProcessRadioTextEnum ValueToProcessRadioText(uint value)
			{
				return value switch
				{
					0u => ProcessRadioTextEnum.DO_NOT_PROCESS, 
					1u => ProcessRadioTextEnum.PROCESS, 
					_ => ProcessRadioTextEnum.InvalidProcessRadioTextValue, 
				};
			}

			public static uint ProcessRadioTextToValue(ProcessRadioTextEnum enumItem)
			{
				return enumItem switch
				{
					ProcessRadioTextEnum.DO_NOT_PROCESS => 0u, 
					ProcessRadioTextEnum.PROCESS => 1u, 
					_ => uint.MaxValue, 
				};
			}

			public static string ProcessRadioTextToString(ProcessRadioTextEnum enumItem)
			{
				return enumItem switch
				{
					ProcessRadioTextEnum.DO_NOT_PROCESS => "Do not process RDS Radio Text (RT)", 
					ProcessRadioTextEnum.PROCESS => "Process RDS Radio Text", 
					_ => "Invalid ProcessRadioText Value", 
				};
			}

			public static string ProcessRadioTextToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = Do not process RDS Radio Text (RT)");
				stringBuilder.AppendLine("0x1 = Process RDS Radio Text");
				return stringBuilder.ToString();
			}
		}

		public enum PassBlockEEnum
		{
			FILTER_FROM_HOST,
			PASS_TO_HOST,
			InvalidPassBlockEValue
		}

		public static class PassBlockEInfo
		{
			public static PassBlockEEnum ValueToPassBlockE(uint value)
			{
				return value switch
				{
					0u => PassBlockEEnum.FILTER_FROM_HOST, 
					1u => PassBlockEEnum.PASS_TO_HOST, 
					_ => PassBlockEEnum.InvalidPassBlockEValue, 
				};
			}

			public static uint PassBlockEToValue(PassBlockEEnum enumItem)
			{
				return enumItem switch
				{
					PassBlockEEnum.FILTER_FROM_HOST => 0u, 
					PassBlockEEnum.PASS_TO_HOST => 1u, 
					_ => uint.MaxValue, 
				};
			}

			public static string PassBlockEToString(PassBlockEEnum enumItem)
			{
				return enumItem switch
				{
					PassBlockEEnum.FILTER_FROM_HOST => "Filters Block-E from the Host", 
					PassBlockEEnum.PASS_TO_HOST => "Passes Block-E to the Host", 
					_ => "Invalid PassBlockE Value", 
				};
			}

			public static string PassBlockEToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = Filters Block-E from the Host");
				stringBuilder.AppendLine("0x1 = Passes Block-E to the Host");
				return stringBuilder.ToString();
			}
		}

		public enum PassUncorrectableBlocksEnum
		{
			FILTER_FROM_HOST,
			PASS_TO_HOST,
			InvalidPassUncorrectableBlocksValue
		}

		public static class PassUncorrectableBlocksInfo
		{
			public static PassUncorrectableBlocksEnum ValueToPassUncorrectableBlocks(uint value)
			{
				return value switch
				{
					0u => PassUncorrectableBlocksEnum.FILTER_FROM_HOST, 
					1u => PassUncorrectableBlocksEnum.PASS_TO_HOST, 
					_ => PassUncorrectableBlocksEnum.InvalidPassUncorrectableBlocksValue, 
				};
			}

			public static uint PassUncorrectableBlocksToValue(PassUncorrectableBlocksEnum enumItem)
			{
				return enumItem switch
				{
					PassUncorrectableBlocksEnum.FILTER_FROM_HOST => 0u, 
					PassUncorrectableBlocksEnum.PASS_TO_HOST => 1u, 
					_ => uint.MaxValue, 
				};
			}

			public static string PassUncorrectableBlocksToString(PassUncorrectableBlocksEnum enumItem)
			{
				return enumItem switch
				{
					PassUncorrectableBlocksEnum.FILTER_FROM_HOST => "Filters uncorrectable blocks from the Host", 
					PassUncorrectableBlocksEnum.PASS_TO_HOST => "Passes uncorrectable blocks to the Host", 
					_ => "Invalid PassUncorrectableBlocks Value", 
				};
			}

			public static string PassUncorrectableBlocksToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = Filters uncorrectable blocks from the Host");
				stringBuilder.AppendLine("0x1 = Passes uncorrectable blocks to the Host");
				return stringBuilder.ToString();
			}
		}

		public enum ChangeFilterEnum
		{
			BYPASS_CHANGE_FILTER,
			USE_CHANGE_FILTER,
			InvalidChangeFilterValue
		}

		public static class ChangeFilterInfo
		{
			public static ChangeFilterEnum ValueToChangeFilter(uint value)
			{
				return value switch
				{
					0u => ChangeFilterEnum.BYPASS_CHANGE_FILTER, 
					1u => ChangeFilterEnum.USE_CHANGE_FILTER, 
					_ => ChangeFilterEnum.InvalidChangeFilterValue, 
				};
			}

			public static uint ChangeFilterToValue(ChangeFilterEnum enumItem)
			{
				return enumItem switch
				{
					ChangeFilterEnum.BYPASS_CHANGE_FILTER => 0u, 
					ChangeFilterEnum.USE_CHANGE_FILTER => 1u, 
					_ => uint.MaxValue, 
				};
			}

			public static string ChangeFilterToString(ChangeFilterEnum enumItem)
			{
				return enumItem switch
				{
					ChangeFilterEnum.BYPASS_CHANGE_FILTER => "Bypass RDS change filter", 
					ChangeFilterEnum.USE_CHANGE_FILTER => "Only place RDS group data into buffer if differs from previous data of the same group type", 
					_ => "Invalid ChangeFilter Value", 
				};
			}

			public static string ChangeFilterToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = Bypass RDS change filter");
				stringBuilder.AppendLine("0x1 = Only place RDS group data into buffer if differs from previous data of the same group type");
				return stringBuilder.ToString();
			}
		}

		private const uint _RegisterAddress = 11u;

		private const uint _Undefined = 0u;

		private uint _AutomaticAfSearch;

		private uint _ProcessAlternativeFrequencyList;

		private uint _ProcessProgramServiceName;

		private uint _ProcessRadioText;

		private uint _PassBlockE;

		private uint _PassUncorrectableBlocks;

		private uint _ChangeFilter;

		public uint RegisterAddress => 11u;

		public uint Undefined => 0u;

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

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

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

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

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

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

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

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

		public AutomaticAfSearchEnum GetAutomaticAfSearchAsAutomaticAfSearchEnum()
		{
			return AutomaticAfSearchInfo.ValueToAutomaticAfSearch(_AutomaticAfSearch);
		}

		public void SetAutomaticAfSearchAsAutomaticAfSearchEnum(AutomaticAfSearchEnum enumItem)
		{
			AutomaticAfSearch = AutomaticAfSearchInfo.AutomaticAfSearchToValue(enumItem);
		}

		public ProcessAlternativeFrequencyListEnum GetProcessAlternativeFrequencyListAsProcessAlternativeFrequencyListEnum()
		{
			return ProcessAlternativeFrequencyListInfo.ValueToProcessAlternativeFrequencyList(_ProcessAlternativeFrequencyList);
		}

		public void SetProcessAlternativeFrequencyListAsProcessAlternativeFrequencyListEnum(ProcessAlternativeFrequencyListEnum enumItem)
		{
			ProcessAlternativeFrequencyList = ProcessAlternativeFrequencyListInfo.ProcessAlternativeFrequencyListToValue(enumItem);
		}

		public ProcessProgramServiceNameEnum GetProcessProgramServiceNameAsProcessProgramServiceNameEnum()
		{
			return ProcessProgramServiceNameInfo.ValueToProcessProgramServiceName(_ProcessProgramServiceName);
		}

		public void SetProcessProgramServiceNameAsProcessProgramServiceNameEnum(ProcessProgramServiceNameEnum enumItem)
		{
			ProcessProgramServiceName = ProcessProgramServiceNameInfo.ProcessProgramServiceNameToValue(enumItem);
		}

		public ProcessRadioTextEnum GetProcessRadioTextAsProcessRadioTextEnum()
		{
			return ProcessRadioTextInfo.ValueToProcessRadioText(_ProcessRadioText);
		}

		public void SetProcessRadioTextAsProcessRadioTextEnum(ProcessRadioTextEnum enumItem)
		{
			ProcessRadioText = ProcessRadioTextInfo.ProcessRadioTextToValue(enumItem);
		}

		public PassBlockEEnum GetPassBlockEAsPassBlockEEnum()
		{
			return PassBlockEInfo.ValueToPassBlockE(_PassBlockE);
		}

		public void SetPassBlockEAsPassBlockEEnum(PassBlockEEnum enumItem)
		{
			PassBlockE = PassBlockEInfo.PassBlockEToValue(enumItem);
		}

		public PassUncorrectableBlocksEnum GetPassUncorrectableBlocksAsPassUncorrectableBlocksEnum()
		{
			return PassUncorrectableBlocksInfo.ValueToPassUncorrectableBlocks(_PassUncorrectableBlocks);
		}

		public void SetPassUncorrectableBlocksAsPassUncorrectableBlocksEnum(PassUncorrectableBlocksEnum enumItem)
		{
			PassUncorrectableBlocks = PassUncorrectableBlocksInfo.PassUncorrectableBlocksToValue(enumItem);
		}

		public ChangeFilterEnum GetChangeFilterAsChangeFilterEnum()
		{
			return ChangeFilterInfo.ValueToChangeFilter(_ChangeFilter);
		}

		public void SetChangeFilterAsChangeFilterEnum(ChangeFilterEnum enumItem)
		{
			ChangeFilter = ChangeFilterInfo.ChangeFilterToValue(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 RdsAdvanceControlInfo(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(1) != UserFields.Undefined)
		{
			return false;
		}
		UserFields.AutomaticAfSearch = bitBuilder.RemoveBitsAsUint(1);
		UserFields.ProcessAlternativeFrequencyList = bitBuilder.RemoveBitsAsUint(1);
		UserFields.ProcessProgramServiceName = bitBuilder.RemoveBitsAsUint(1);
		UserFields.ProcessRadioText = bitBuilder.RemoveBitsAsUint(1);
		UserFields.PassBlockE = bitBuilder.RemoveBitsAsUint(1);
		UserFields.PassUncorrectableBlocks = bitBuilder.RemoveBitsAsUint(1);
		UserFields.ChangeFilter = bitBuilder.RemoveBitsAsUint(1);
		if (bitBuilder.GetNumberOfBits() > 7)
		{
			return false;
		}
		return true;
	}

	public override string ToBitString()
	{
		BitBuilder bitBuilder = new BitBuilder();
		bitBuilder.AddBitsAsUint(UserFields.RegisterAddress, 8);
		bitBuilder.AddBitsAsUint(UserFields.Undefined, 1);
		bitBuilder.AddBitsAsUint(UserFields.AutomaticAfSearch, 1);
		bitBuilder.AddBitsAsUint(UserFields.ProcessAlternativeFrequencyList, 1);
		bitBuilder.AddBitsAsUint(UserFields.ProcessProgramServiceName, 1);
		bitBuilder.AddBitsAsUint(UserFields.ProcessRadioText, 1);
		bitBuilder.AddBitsAsUint(UserFields.PassBlockE, 1);
		bitBuilder.AddBitsAsUint(UserFields.PassUncorrectableBlocks, 1);
		bitBuilder.AddBitsAsUint(UserFields.ChangeFilter, 1);
		return bitBuilder.ToString();
	}
}
