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

namespace QCRPG.TSL.FM.Packets;

public class RdsControl : PacketBase
{
	public class UserFieldsWrapper
	{
		public enum SynchronizationEnum
		{
			AUTO_SYNCHRONIZATION,
			FORCE_NEW_SYNCHRONIZATION,
			InvalidSynchronizationValue
		}

		public static class SynchronizationInfo
		{
			public static SynchronizationEnum ValueToSynchronization(uint value)
			{
				return value switch
				{
					0u => SynchronizationEnum.AUTO_SYNCHRONIZATION, 
					1u => SynchronizationEnum.FORCE_NEW_SYNCHRONIZATION, 
					_ => SynchronizationEnum.InvalidSynchronizationValue, 
				};
			}

			public static uint SynchronizationToValue(SynchronizationEnum enumItem)
			{
				return enumItem switch
				{
					SynchronizationEnum.AUTO_SYNCHRONIZATION => 0u, 
					SynchronizationEnum.FORCE_NEW_SYNCHRONIZATION => 1u, 
					_ => uint.MaxValue, 
				};
			}

			public static string SynchronizationToString(SynchronizationEnum enumItem)
			{
				return enumItem switch
				{
					SynchronizationEnum.AUTO_SYNCHRONIZATION => "Auto synchronization", 
					SynchronizationEnum.FORCE_NEW_SYNCHRONIZATION => "Force new synchronization", 
					_ => "Invalid Synchronization Value", 
				};
			}

			public static string SynchronizationToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = Auto synchronization");
				stringBuilder.AppendLine("0x1 = Force new synchronization");
				return stringBuilder.ToString();
			}
		}

		public enum StandardEnum
		{
			RBDS_US_STANDARD,
			RDS_EUROPEAN_STANDARD,
			InvalidStandardValue
		}

		public static class StandardInfo
		{
			public static StandardEnum ValueToStandard(uint value)
			{
				return value switch
				{
					0u => StandardEnum.RBDS_US_STANDARD, 
					1u => StandardEnum.RDS_EUROPEAN_STANDARD, 
					_ => StandardEnum.InvalidStandardValue, 
				};
			}

			public static uint StandardToValue(StandardEnum enumItem)
			{
				return enumItem switch
				{
					StandardEnum.RBDS_US_STANDARD => 0u, 
					StandardEnum.RDS_EUROPEAN_STANDARD => 1u, 
					_ => uint.MaxValue, 
				};
			}

			public static string StandardToString(StandardEnum enumItem)
			{
				return enumItem switch
				{
					StandardEnum.RBDS_US_STANDARD => "RBDS (US standard)", 
					StandardEnum.RDS_EUROPEAN_STANDARD => "RDS (European standard)", 
					_ => "Invalid Standard Value", 
				};
			}

			public static string StandardToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = RBDS (US standard)");
				stringBuilder.AppendLine("0x1 = RDS (European standard)");
				return stringBuilder.ToString();
			}
		}

		public enum ControlEnum
		{
			OFF,
			ON,
			InvalidControlValue
		}

		public static class ControlInfo
		{
			public static ControlEnum ValueToControl(uint value)
			{
				return value switch
				{
					0u => ControlEnum.OFF, 
					1u => ControlEnum.ON, 
					_ => ControlEnum.InvalidControlValue, 
				};
			}

			public static uint ControlToValue(ControlEnum enumItem)
			{
				return enumItem switch
				{
					ControlEnum.OFF => 0u, 
					ControlEnum.ON => 1u, 
					_ => uint.MaxValue, 
				};
			}

			public static string ControlToString(ControlEnum enumItem)
			{
				return enumItem switch
				{
					ControlEnum.OFF => "RDS off", 
					ControlEnum.ON => "RDS on", 
					_ => "Invalid Control Value", 
				};
			}

			public static string ControlToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = RDS off");
				stringBuilder.AppendLine("0x1 = RDS on");
				return stringBuilder.ToString();
			}
		}

		private const uint _RegisterAddress = 10u;

		private const uint _Undefined = 0u;

		private uint _Synchronization;

		private uint _Standard;

		private uint _Control;

		public uint RegisterAddress => 10u;

		public uint Undefined => 0u;

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

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

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

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

		public SynchronizationEnum GetSynchronizationAsSynchronizationEnum()
		{
			return SynchronizationInfo.ValueToSynchronization(_Synchronization);
		}

		public void SetSynchronizationAsSynchronizationEnum(SynchronizationEnum enumItem)
		{
			Synchronization = SynchronizationInfo.SynchronizationToValue(enumItem);
		}

		public StandardEnum GetStandardAsStandardEnum()
		{
			return StandardInfo.ValueToStandard(_Standard);
		}

		public void SetStandardAsStandardEnum(StandardEnum enumItem)
		{
			Standard = StandardInfo.StandardToValue(enumItem);
		}

		public ControlEnum GetControlAsControlEnum()
		{
			return ControlInfo.ValueToControl(_Control);
		}

		public void SetControlAsControlEnum(ControlEnum enumItem)
		{
			Control = ControlInfo.ControlToValue(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 RdsControlInfo(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(5) != UserFields.Undefined)
		{
			return false;
		}
		UserFields.Synchronization = bitBuilder.RemoveBitsAsUint(1);
		UserFields.Standard = bitBuilder.RemoveBitsAsUint(1);
		UserFields.Control = 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, 5);
		bitBuilder.AddBitsAsUint(UserFields.Synchronization, 1);
		bitBuilder.AddBitsAsUint(UserFields.Standard, 1);
		bitBuilder.AddBitsAsUint(UserFields.Control, 1);
		return bitBuilder.ToString();
	}
}
