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

namespace QCRPG.TSL.FMHCI.Packets;

public class EnableWanAvoidanceControl : PacketBase
{
	public class UserFieldsWrapper
	{
		private uint _NumberOfForbiddenFrequencies;

		private List<ForbiddenFrequencyListSubField> _ForbiddenFrequencyListList = new List<ForbiddenFrequencyListSubField>();

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

		public List<ForbiddenFrequencyListSubField> ForbiddenFrequencyListList => _ForbiddenFrequencyListList;
	}

	public class ForbiddenFrequencyListSubField
	{
		public enum LoShiftEnum
		{
			NO_LO_SHIFT,
			LO_SHIFT_PLUS_200KHZ,
			LO_SHIFT_MINUS_180KHZ,
			LO_SHIFT_PLUS_380KHZ,
			InvalidLoShiftValue
		}

		public static class LoShiftInfo
		{
			public static LoShiftEnum ValueToLoShift(uint value)
			{
				return value switch
				{
					0u => LoShiftEnum.NO_LO_SHIFT, 
					1u => LoShiftEnum.LO_SHIFT_PLUS_200KHZ, 
					2u => LoShiftEnum.LO_SHIFT_MINUS_180KHZ, 
					3u => LoShiftEnum.LO_SHIFT_PLUS_380KHZ, 
					_ => LoShiftEnum.InvalidLoShiftValue, 
				};
			}

			public static uint LoShiftToValue(LoShiftEnum enumItem)
			{
				return enumItem switch
				{
					LoShiftEnum.NO_LO_SHIFT => 0u, 
					LoShiftEnum.LO_SHIFT_PLUS_200KHZ => 1u, 
					LoShiftEnum.LO_SHIFT_MINUS_180KHZ => 2u, 
					LoShiftEnum.LO_SHIFT_PLUS_380KHZ => 3u, 
					_ => uint.MaxValue, 
				};
			}

			public static string LoShiftToString(LoShiftEnum enumItem)
			{
				return enumItem switch
				{
					LoShiftEnum.NO_LO_SHIFT => "NO_LO_SHIFT", 
					LoShiftEnum.LO_SHIFT_PLUS_200KHZ => "LO_SHIFT_PLUS_200KHZ", 
					LoShiftEnum.LO_SHIFT_MINUS_180KHZ => "LO_SHIFT_MINUS_180KHZ", 
					LoShiftEnum.LO_SHIFT_PLUS_380KHZ => "LO_SHIFT_PLUS_380KHZ", 
					_ => "Invalid LoShift Value", 
				};
			}

			public static string LoShiftToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = NO_LO_SHIFT");
				stringBuilder.AppendLine("0x1 = LO_SHIFT_PLUS_200KHZ");
				stringBuilder.AppendLine("0x2 = LO_SHIFT_MINUS_180KHZ");
				stringBuilder.AppendLine("0x3 = LO_SHIFT_PLUS_380KHZ");
				return stringBuilder.ToString();
			}
		}

		private uint _ForbiddenFrequencyIndex;

		private uint _LoShift;

		private uint _ForbiddenFrequencyMinimumInKhz;

		private uint _ForbiddenFrequencyMaximumInKhz;

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

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

		public uint ForbiddenFrequencyMinimumInKhz
		{
			get
			{
				return _ForbiddenFrequencyMinimumInKhz;
			}
			set
			{
				_ForbiddenFrequencyMinimumInKhz = value;
			}
		}

		public uint ForbiddenFrequencyMaximumInKhz
		{
			get
			{
				return _ForbiddenFrequencyMaximumInKhz;
			}
			set
			{
				_ForbiddenFrequencyMaximumInKhz = value;
			}
		}

		public LoShiftEnum GetLoShiftAsLoShiftEnum()
		{
			return LoShiftInfo.ValueToLoShift(_LoShift);
		}

		public void SetLoShiftAsLoShiftEnum(LoShiftEnum enumItem)
		{
			LoShift = LoShiftInfo.LoShiftToValue(enumItem);
		}

		public bool FromBitBuilder(ref BitBuilder bitBuilder)
		{
			ForbiddenFrequencyIndex = bitBuilder.RemoveBitsAsUint(8);
			LoShift = bitBuilder.RemoveBitsAsUint(8);
			ForbiddenFrequencyMinimumInKhz = bitBuilder.RemoveBitsAsUintLittleEndian(32);
			ForbiddenFrequencyMaximumInKhz = bitBuilder.RemoveBitsAsUintLittleEndian(32);
			return true;
		}

		public string ToBitString()
		{
			BitBuilder bitBuilder = new BitBuilder();
			bitBuilder.AddBitsAsUint(ForbiddenFrequencyIndex, 8);
			bitBuilder.AddBitsAsUint(LoShift, 8);
			bitBuilder.AddBitsAsUintLittleEndian(ForbiddenFrequencyMinimumInKhz, 32);
			bitBuilder.AddBitsAsUintLittleEndian(ForbiddenFrequencyMaximumInKhz, 32);
			return bitBuilder.ToString();
		}

		public List<string> GetWarnings()
		{
			List<string> list = new List<string>();
			if (LoShift > 4)
			{
				list.Add("Maximum allowed value for LO Shift is 0x4");
			}
			return list;
		}
	}

	private const uint _Opcode = 19476u;

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

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

	public uint Opcode => 19476u;

	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.NumberOfForbiddenFrequencies = bitBuilder.RemoveBitsAsUint(8);
		for (int i = 0; i < UserFields.ForbiddenFrequencyListList.Count; i++)
		{
			UserFields.ForbiddenFrequencyListList[i].FromBitBuilder(ref bitBuilder);
		}
		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.NumberOfForbiddenFrequencies, 8);
		for (int i = 0; i < UserFields.ForbiddenFrequencyListList.Count; i++)
		{
			bitBuilder.AddBitsAsString(UserFields.ForbiddenFrequencyListList[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.NumberOfForbiddenFrequencies > 16)
		{
			list.Add("Maximum allowed value for Number Of Forbidden Frequencies is 0x10");
		}
		for (int i = 0; i < UserFields.ForbiddenFrequencyListList.Count; i++)
		{
			list.AddRange(UserFields.ForbiddenFrequencyListList[i].GetWarnings());
		}
		return list;
	}
}
