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

namespace QCRPG.TSL.BT.Packets;

public class WriteLocationData : PacketBase
{
	public class UserFieldsWrapper
	{
		public enum LocationDomainAwareEnum
		{
			Regulatory_domain_unknown,
			Regulatory_domain_known,
			Reserved_for_future_use,
			InvalidLocationDomainAwareValue
		}

		public static class LocationDomainAwareInfo
		{
			public static LocationDomainAwareEnum ValueToLocationDomainAware(uint value)
			{
				switch (value)
				{
				case 0u:
					return LocationDomainAwareEnum.Regulatory_domain_unknown;
				case 1u:
					return LocationDomainAwareEnum.Regulatory_domain_known;
				default:
					if (value >= 2 && value <= 255)
					{
						return LocationDomainAwareEnum.Reserved_for_future_use;
					}
					return LocationDomainAwareEnum.InvalidLocationDomainAwareValue;
				}
			}

			public static uint LocationDomainAwareToValue(LocationDomainAwareEnum enumItem)
			{
				return enumItem switch
				{
					LocationDomainAwareEnum.Regulatory_domain_unknown => 0u, 
					LocationDomainAwareEnum.Regulatory_domain_known => 1u, 
					LocationDomainAwareEnum.Reserved_for_future_use => 2u, 
					_ => uint.MaxValue, 
				};
			}

			public static string LocationDomainAwareToString(LocationDomainAwareEnum enumItem)
			{
				return enumItem switch
				{
					LocationDomainAwareEnum.Regulatory_domain_unknown => "Regulatory domain unknown", 
					LocationDomainAwareEnum.Regulatory_domain_known => "Regulatory domain known", 
					LocationDomainAwareEnum.Reserved_for_future_use => "Reserved for future use", 
					_ => "Invalid LocationDomainAware Value", 
				};
			}

			public static string LocationDomainAwareToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = Regulatory domain unknown");
				stringBuilder.AppendLine("0x1 = Regulatory domain known");
				stringBuilder.AppendLine("0x2-0xFF = Reserved for future use");
				return stringBuilder.ToString();
			}
		}

		public enum LocationDomainOptionsEnum
		{
			Indicates_that_the_code_applies_to_the_entire_country,
			Indicates_for_use_outdoors_only,
			Indicates_for_use_indoors_only,
			Indicates_a_non_country_entity,
			InvalidLocationDomainOptionsValue
		}

		public static class LocationDomainOptionsInfo
		{
			public static LocationDomainOptionsEnum ValueToLocationDomainOptions(uint value)
			{
				return value switch
				{
					32u => LocationDomainOptionsEnum.Indicates_that_the_code_applies_to_the_entire_country, 
					79u => LocationDomainOptionsEnum.Indicates_for_use_outdoors_only, 
					73u => LocationDomainOptionsEnum.Indicates_for_use_indoors_only, 
					88u => LocationDomainOptionsEnum.Indicates_a_non_country_entity, 
					_ => LocationDomainOptionsEnum.InvalidLocationDomainOptionsValue, 
				};
			}

			public static uint LocationDomainOptionsToValue(LocationDomainOptionsEnum enumItem)
			{
				return enumItem switch
				{
					LocationDomainOptionsEnum.Indicates_that_the_code_applies_to_the_entire_country => 32u, 
					LocationDomainOptionsEnum.Indicates_for_use_outdoors_only => 79u, 
					LocationDomainOptionsEnum.Indicates_for_use_indoors_only => 73u, 
					LocationDomainOptionsEnum.Indicates_a_non_country_entity => 88u, 
					_ => uint.MaxValue, 
				};
			}

			public static string LocationDomainOptionsToString(LocationDomainOptionsEnum enumItem)
			{
				return enumItem switch
				{
					LocationDomainOptionsEnum.Indicates_that_the_code_applies_to_the_entire_country => "'space' indicates that the code applies to the entire country", 
					LocationDomainOptionsEnum.Indicates_for_use_outdoors_only => "'O' indicates for use outdoors only", 
					LocationDomainOptionsEnum.Indicates_for_use_indoors_only => "'I' indicates for use indoors only", 
					LocationDomainOptionsEnum.Indicates_a_non_country_entity => "'X' indicates a non-country entity", 
					_ => "Invalid LocationDomainOptions Value", 
				};
			}

			public static string LocationDomainOptionsToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x20 = 'space' indicates that the code applies to the entire country");
				stringBuilder.AppendLine("0x4F = 'O' indicates for use outdoors only");
				stringBuilder.AppendLine("0x49 = 'I' indicates for use indoors only");
				stringBuilder.AppendLine("0x58 = 'X' indicates a non-country entity");
				return stringBuilder.ToString();
			}
		}

		private uint _LocationDomainAware;

		private uint _LocationDomain;

		private uint _LocationDomainOptions;

		private uint _LocationOptions;

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

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

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

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

		public LocationDomainAwareEnum GetLocationDomainAwareAsLocationDomainAwareEnum()
		{
			return LocationDomainAwareInfo.ValueToLocationDomainAware(_LocationDomainAware);
		}

		public void SetLocationDomainAwareAsLocationDomainAwareEnum(LocationDomainAwareEnum enumItem)
		{
			LocationDomainAware = LocationDomainAwareInfo.LocationDomainAwareToValue(enumItem);
		}

		public LocationDomainOptionsEnum GetLocationDomainOptionsAsLocationDomainOptionsEnum()
		{
			return LocationDomainOptionsInfo.ValueToLocationDomainOptions(_LocationDomainOptions);
		}

		public void SetLocationDomainOptionsAsLocationDomainOptionsEnum(LocationDomainOptionsEnum enumItem)
		{
			LocationDomainOptions = LocationDomainOptionsInfo.LocationDomainOptionsToValue(enumItem);
		}
	}

	private const uint _Opcode = 3173u;

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

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

	public uint Opcode => 3173u;

	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.LocationDomainAware = bitBuilder.RemoveBitsAsUint(8);
		UserFields.LocationDomain = bitBuilder.RemoveBitsAsUintLittleEndian(16);
		UserFields.LocationDomainOptions = bitBuilder.RemoveBitsAsUint(8);
		UserFields.LocationOptions = 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.LocationDomainAware, 8);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.LocationDomain, 16);
		bitBuilder.AddBitsAsUint(UserFields.LocationDomainOptions, 8);
		bitBuilder.AddBitsAsUint(UserFields.LocationOptions, 8);
		_PayloadLength = (uint)((bitBuilder.GetNumberOfBits() - numberOfBits - 8) / 8);
		if ((bitBuilder.GetNumberOfBits() - numberOfBits - 8) % 8 != 0)
		{
			_PayloadLength++;
		}
		bitBuilder.ChangeBitsAsUint(numberOfBits, _PayloadLength, 8);
		return bitBuilder.ToString();
	}
}
