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

namespace QCRPG.TSL.FMHCI.Packets;

public class RdsRxData : PacketBase
{
	public class UserFieldsWrapper
	{
		private uint _NumberOfRdsGroups;

		private List<RdsGroupListSubField> _RdsGroupListList = new List<RdsGroupListSubField>();

		public uint NumberOfRdsGroups
		{
			get
			{
				return _NumberOfRdsGroups;
			}
			set
			{
				if (value > 255)
				{
					throw new Exception("Maximum possible value for NumberOfRdsGroups is 0xFF");
				}
				_NumberOfRdsGroups = value;
				while (_RdsGroupListList.Count < _NumberOfRdsGroups)
				{
					_RdsGroupListList.Add(new RdsGroupListSubField());
				}
				while (_RdsGroupListList.Count > _NumberOfRdsGroups)
				{
					_RdsGroupListList.RemoveAt(_RdsGroupListList.Count - 1);
				}
			}
		}

		public List<RdsGroupListSubField> RdsGroupListList => _RdsGroupListList;
	}

	public class RdsGroupListSubField
	{
		public enum RdsGroupBlockStatusCorrectableErrorsEnum
		{
			UNCORRECTABLE_BLOCK,
			NO_ERROR_CORRECTED_INDETERMINATE,
			ONE_ERROR_CORRECTED,
			TWO_ERRORS_CORRECTED,
			THREE_ERRORS_CORRECTED,
			FOUR_ERRORS_CORRECTED,
			FIVE_ERRORS_CORRECTED,
			UNDEFINED,
			NO_ERROR_DETECTED,
			InvalidRdsGroupBlockStatusCorrectableErrorsValue
		}

		public static class RdsGroupBlockStatusCorrectableErrorsInfo
		{
			public static RdsGroupBlockStatusCorrectableErrorsEnum ValueToRdsGroupBlockStatusCorrectableErrors(uint value)
			{
				if (value >= 0 && value <= 7)
				{
					return RdsGroupBlockStatusCorrectableErrorsEnum.UNCORRECTABLE_BLOCK;
				}
				return value switch
				{
					8u => RdsGroupBlockStatusCorrectableErrorsEnum.NO_ERROR_CORRECTED_INDETERMINATE, 
					9u => RdsGroupBlockStatusCorrectableErrorsEnum.ONE_ERROR_CORRECTED, 
					10u => RdsGroupBlockStatusCorrectableErrorsEnum.TWO_ERRORS_CORRECTED, 
					11u => RdsGroupBlockStatusCorrectableErrorsEnum.THREE_ERRORS_CORRECTED, 
					12u => RdsGroupBlockStatusCorrectableErrorsEnum.FOUR_ERRORS_CORRECTED, 
					13u => RdsGroupBlockStatusCorrectableErrorsEnum.FIVE_ERRORS_CORRECTED, 
					14u => RdsGroupBlockStatusCorrectableErrorsEnum.UNDEFINED, 
					15u => RdsGroupBlockStatusCorrectableErrorsEnum.NO_ERROR_DETECTED, 
					_ => RdsGroupBlockStatusCorrectableErrorsEnum.InvalidRdsGroupBlockStatusCorrectableErrorsValue, 
				};
			}

			public static uint RdsGroupBlockStatusCorrectableErrorsToValue(RdsGroupBlockStatusCorrectableErrorsEnum enumItem)
			{
				return enumItem switch
				{
					RdsGroupBlockStatusCorrectableErrorsEnum.UNCORRECTABLE_BLOCK => 0u, 
					RdsGroupBlockStatusCorrectableErrorsEnum.NO_ERROR_CORRECTED_INDETERMINATE => 8u, 
					RdsGroupBlockStatusCorrectableErrorsEnum.ONE_ERROR_CORRECTED => 9u, 
					RdsGroupBlockStatusCorrectableErrorsEnum.TWO_ERRORS_CORRECTED => 10u, 
					RdsGroupBlockStatusCorrectableErrorsEnum.THREE_ERRORS_CORRECTED => 11u, 
					RdsGroupBlockStatusCorrectableErrorsEnum.FOUR_ERRORS_CORRECTED => 12u, 
					RdsGroupBlockStatusCorrectableErrorsEnum.FIVE_ERRORS_CORRECTED => 13u, 
					RdsGroupBlockStatusCorrectableErrorsEnum.UNDEFINED => 14u, 
					RdsGroupBlockStatusCorrectableErrorsEnum.NO_ERROR_DETECTED => 15u, 
					_ => uint.MaxValue, 
				};
			}

			public static string RdsGroupBlockStatusCorrectableErrorsToString(RdsGroupBlockStatusCorrectableErrorsEnum enumItem)
			{
				return enumItem switch
				{
					RdsGroupBlockStatusCorrectableErrorsEnum.UNCORRECTABLE_BLOCK => "Uncorrectable block", 
					RdsGroupBlockStatusCorrectableErrorsEnum.NO_ERROR_CORRECTED_INDETERMINATE => "No error corrected; indeterminate whether syndrome match", 
					RdsGroupBlockStatusCorrectableErrorsEnum.ONE_ERROR_CORRECTED => "1 error corrected by FEC decoder", 
					RdsGroupBlockStatusCorrectableErrorsEnum.TWO_ERRORS_CORRECTED => "2 errors corrected by FEC decoder", 
					RdsGroupBlockStatusCorrectableErrorsEnum.THREE_ERRORS_CORRECTED => "3 errors corrected by FEC decoder", 
					RdsGroupBlockStatusCorrectableErrorsEnum.FOUR_ERRORS_CORRECTED => "4 errors corrected by FEC decoder", 
					RdsGroupBlockStatusCorrectableErrorsEnum.FIVE_ERRORS_CORRECTED => "5 errors corrected by FEC decoder", 
					RdsGroupBlockStatusCorrectableErrorsEnum.UNDEFINED => "Undefined", 
					RdsGroupBlockStatusCorrectableErrorsEnum.NO_ERROR_DETECTED => "Perfect syndrome match; no error detected", 
					_ => "Invalid RdsGroupBlockStatusCorrectableErrors Value", 
				};
			}

			public static string RdsGroupBlockStatusCorrectableErrorsToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0-0x7 = Uncorrectable block");
				stringBuilder.AppendLine("0x8 = No error corrected; indeterminate whether syndrome match");
				stringBuilder.AppendLine("0x9 = 1 error corrected by FEC decoder");
				stringBuilder.AppendLine("0xA = 2 errors corrected by FEC decoder");
				stringBuilder.AppendLine("0xB = 3 errors corrected by FEC decoder");
				stringBuilder.AppendLine("0xC = 4 errors corrected by FEC decoder");
				stringBuilder.AppendLine("0xD = 5 errors corrected by FEC decoder");
				stringBuilder.AppendLine("0xE = Undefined");
				stringBuilder.AppendLine("0xF = Perfect syndrome match; no error detected");
				return stringBuilder.ToString();
			}
		}

		public enum RdsGroupBlockStatusBlockIdEnum
		{
			NO_DECODE,
			BLOCK_A,
			BLOCK_B,
			BLOCK_C,
			BLOCK_C_PRIME,
			BLOCK_D,
			BLOCK_E,
			UNDEFINED,
			InvalidRdsGroupBlockStatusBlockIdValue
		}

		public static class RdsGroupBlockStatusBlockIdInfo
		{
			public static RdsGroupBlockStatusBlockIdEnum ValueToRdsGroupBlockStatusBlockId(uint value)
			{
				return value switch
				{
					0u => RdsGroupBlockStatusBlockIdEnum.NO_DECODE, 
					1u => RdsGroupBlockStatusBlockIdEnum.BLOCK_A, 
					2u => RdsGroupBlockStatusBlockIdEnum.BLOCK_B, 
					3u => RdsGroupBlockStatusBlockIdEnum.BLOCK_C, 
					4u => RdsGroupBlockStatusBlockIdEnum.BLOCK_C_PRIME, 
					5u => RdsGroupBlockStatusBlockIdEnum.BLOCK_D, 
					6u => RdsGroupBlockStatusBlockIdEnum.BLOCK_E, 
					7u => RdsGroupBlockStatusBlockIdEnum.UNDEFINED, 
					_ => RdsGroupBlockStatusBlockIdEnum.InvalidRdsGroupBlockStatusBlockIdValue, 
				};
			}

			public static uint RdsGroupBlockStatusBlockIdToValue(RdsGroupBlockStatusBlockIdEnum enumItem)
			{
				return enumItem switch
				{
					RdsGroupBlockStatusBlockIdEnum.NO_DECODE => 0u, 
					RdsGroupBlockStatusBlockIdEnum.BLOCK_A => 1u, 
					RdsGroupBlockStatusBlockIdEnum.BLOCK_B => 2u, 
					RdsGroupBlockStatusBlockIdEnum.BLOCK_C => 3u, 
					RdsGroupBlockStatusBlockIdEnum.BLOCK_C_PRIME => 4u, 
					RdsGroupBlockStatusBlockIdEnum.BLOCK_D => 5u, 
					RdsGroupBlockStatusBlockIdEnum.BLOCK_E => 6u, 
					RdsGroupBlockStatusBlockIdEnum.UNDEFINED => 7u, 
					_ => uint.MaxValue, 
				};
			}

			public static string RdsGroupBlockStatusBlockIdToString(RdsGroupBlockStatusBlockIdEnum enumItem)
			{
				return enumItem switch
				{
					RdsGroupBlockStatusBlockIdEnum.NO_DECODE => "No decode", 
					RdsGroupBlockStatusBlockIdEnum.BLOCK_A => "Block A", 
					RdsGroupBlockStatusBlockIdEnum.BLOCK_B => "Block B", 
					RdsGroupBlockStatusBlockIdEnum.BLOCK_C => "Block C", 
					RdsGroupBlockStatusBlockIdEnum.BLOCK_C_PRIME => "Block C'", 
					RdsGroupBlockStatusBlockIdEnum.BLOCK_D => "Block D", 
					RdsGroupBlockStatusBlockIdEnum.BLOCK_E => "Block E", 
					RdsGroupBlockStatusBlockIdEnum.UNDEFINED => "Undefined", 
					_ => "Invalid RdsGroupBlockStatusBlockId Value", 
				};
			}

			public static string RdsGroupBlockStatusBlockIdToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = No decode");
				stringBuilder.AppendLine("0x1 = Block A");
				stringBuilder.AppendLine("0x2 = Block B");
				stringBuilder.AppendLine("0x3 = Block C");
				stringBuilder.AppendLine("0x4 = Block C'");
				stringBuilder.AppendLine("0x5 = Block D");
				stringBuilder.AppendLine("0x6 = Block E");
				stringBuilder.AppendLine("0x7 = Undefined");
				return stringBuilder.ToString();
			}
		}

		private uint _RdsGroupBlockInfo1;

		private uint _RdsGroupBlockInfo2;

		private uint _RdsGroupBlockInfo3;

		private uint _RdsGroupBlockInfo4;

		private uint _RdsGroupBlockStatusReserved;

		private uint _RdsGroupBlockStatusCorrectableErrors;

		private uint _RdsGroupBlockStatusBlockId;

		public uint RdsGroupBlockInfo1
		{
			get
			{
				return _RdsGroupBlockInfo1;
			}
			set
			{
				if (value > 65535)
				{
					throw new Exception("Maximum possible value for RdsGroupBlockInfo1 is 0xFFFF");
				}
				_RdsGroupBlockInfo1 = value;
			}
		}

		public uint RdsGroupBlockInfo2
		{
			get
			{
				return _RdsGroupBlockInfo2;
			}
			set
			{
				if (value > 65535)
				{
					throw new Exception("Maximum possible value for RdsGroupBlockInfo2 is 0xFFFF");
				}
				_RdsGroupBlockInfo2 = value;
			}
		}

		public uint RdsGroupBlockInfo3
		{
			get
			{
				return _RdsGroupBlockInfo3;
			}
			set
			{
				if (value > 65535)
				{
					throw new Exception("Maximum possible value for RdsGroupBlockInfo3 is 0xFFFF");
				}
				_RdsGroupBlockInfo3 = value;
			}
		}

		public uint RdsGroupBlockInfo4
		{
			get
			{
				return _RdsGroupBlockInfo4;
			}
			set
			{
				if (value > 65535)
				{
					throw new Exception("Maximum possible value for RdsGroupBlockInfo4 is 0xFFFF");
				}
				_RdsGroupBlockInfo4 = value;
			}
		}

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

		public uint RdsGroupBlockStatusCorrectableErrors
		{
			get
			{
				return _RdsGroupBlockStatusCorrectableErrors;
			}
			set
			{
				if (value > 15)
				{
					throw new Exception("Maximum possible value for RdsGroupBlockStatusCorrectableErrors is 0xF");
				}
				_RdsGroupBlockStatusCorrectableErrors = value;
			}
		}

		public uint RdsGroupBlockStatusBlockId
		{
			get
			{
				return _RdsGroupBlockStatusBlockId;
			}
			set
			{
				if (value > 7)
				{
					throw new Exception("Maximum possible value for RdsGroupBlockStatusBlockId is 0x7");
				}
				_RdsGroupBlockStatusBlockId = value;
			}
		}

		public RdsGroupBlockStatusCorrectableErrorsEnum GetRdsGroupBlockStatusCorrectableErrorsAsRdsGroupBlockStatusCorrectableErrorsEnum()
		{
			return RdsGroupBlockStatusCorrectableErrorsInfo.ValueToRdsGroupBlockStatusCorrectableErrors(_RdsGroupBlockStatusCorrectableErrors);
		}

		public void SetRdsGroupBlockStatusCorrectableErrorsAsRdsGroupBlockStatusCorrectableErrorsEnum(RdsGroupBlockStatusCorrectableErrorsEnum enumItem)
		{
			RdsGroupBlockStatusCorrectableErrors = RdsGroupBlockStatusCorrectableErrorsInfo.RdsGroupBlockStatusCorrectableErrorsToValue(enumItem);
		}

		public RdsGroupBlockStatusBlockIdEnum GetRdsGroupBlockStatusBlockIdAsRdsGroupBlockStatusBlockIdEnum()
		{
			return RdsGroupBlockStatusBlockIdInfo.ValueToRdsGroupBlockStatusBlockId(_RdsGroupBlockStatusBlockId);
		}

		public void SetRdsGroupBlockStatusBlockIdAsRdsGroupBlockStatusBlockIdEnum(RdsGroupBlockStatusBlockIdEnum enumItem)
		{
			RdsGroupBlockStatusBlockId = RdsGroupBlockStatusBlockIdInfo.RdsGroupBlockStatusBlockIdToValue(enumItem);
		}

		public bool FromBitBuilder(ref BitBuilder bitBuilder)
		{
			RdsGroupBlockInfo1 = bitBuilder.RemoveBitsAsUintLittleEndian(16);
			RdsGroupBlockInfo2 = bitBuilder.RemoveBitsAsUintLittleEndian(16);
			RdsGroupBlockInfo3 = bitBuilder.RemoveBitsAsUintLittleEndian(16);
			RdsGroupBlockInfo4 = bitBuilder.RemoveBitsAsUintLittleEndian(16);
			RdsGroupBlockStatusReserved = bitBuilder.RemoveBitsAsUint(1);
			RdsGroupBlockStatusCorrectableErrors = bitBuilder.RemoveBitsAsUint(4);
			RdsGroupBlockStatusBlockId = bitBuilder.RemoveBitsAsUint(3);
			return true;
		}

		public string ToBitString()
		{
			BitBuilder bitBuilder = new BitBuilder();
			bitBuilder.AddBitsAsUintLittleEndian(RdsGroupBlockInfo1, 16);
			bitBuilder.AddBitsAsUintLittleEndian(RdsGroupBlockInfo2, 16);
			bitBuilder.AddBitsAsUintLittleEndian(RdsGroupBlockInfo3, 16);
			bitBuilder.AddBitsAsUintLittleEndian(RdsGroupBlockInfo4, 16);
			bitBuilder.AddBitsAsUint(RdsGroupBlockStatusReserved, 1);
			bitBuilder.AddBitsAsUint(RdsGroupBlockStatusCorrectableErrors, 4);
			bitBuilder.AddBitsAsUint(RdsGroupBlockStatusBlockId, 3);
			return bitBuilder.ToString();
		}
	}

	private const uint _EventCode = 8u;

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

	private PacketInfoBase info;

	private uint _PayloadLength;

	public UserFieldsWrapper _UserFields = new UserFieldsWrapper();

	public override PacketType Type => PacketType.Notification;

	public override Type[] ExpectedResponseTypes => expectedResponseTypes;

	public override PacketInfoBase Info
	{
		get
		{
			if (info == null)
			{
				info = new RdsRxDataInfo(this);
			}
			return info;
		}
	}

	public uint EventCode => 8u;

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

	public UserFieldsWrapper UserFields => _UserFields;

	protected override bool FromBitBuilder(ref BitBuilder bitBuilder)
	{
		if (bitBuilder.RemoveBitsAsUint(8) != EventCode)
		{
			return false;
		}
		_PayloadLength = bitBuilder.RemoveBitsAsUint(8);
		int numberOfBits = bitBuilder.GetNumberOfBits();
		if (numberOfBits > _PayloadLength * 8 + 7)
		{
			return false;
		}
		if (numberOfBits < _PayloadLength * 8)
		{
			return false;
		}
		UserFields.NumberOfRdsGroups = bitBuilder.RemoveBitsAsUint(8);
		for (int i = 0; i < UserFields.RdsGroupListList.Count; i++)
		{
			UserFields.RdsGroupListList[i].FromBitBuilder(ref bitBuilder);
		}
		if (bitBuilder.GetNumberOfBits() > 7)
		{
			return false;
		}
		return true;
	}

	public override string ToBitString()
	{
		BitBuilder bitBuilder = new BitBuilder();
		bitBuilder.AddBitsAsUint(EventCode, 8);
		int numberOfBits = bitBuilder.GetNumberOfBits();
		bitBuilder.AddBitsAsUint(0u, 8);
		bitBuilder.AddBitsAsUint(UserFields.NumberOfRdsGroups, 8);
		for (int i = 0; i < UserFields.RdsGroupListList.Count; i++)
		{
			bitBuilder.AddBitsAsString(UserFields.RdsGroupListList[i].ToBitString());
		}
		_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.NumberOfRdsGroups > 31)
		{
			list.Add("Maximum allowed value for Number Of RDS Groups is 0x1F");
		}
		return list;
	}
}
