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

namespace QCRPG.TSL.NFC.Packets;

public class CoreConnCreateRsp : PacketBase
{
	public class UserFieldsWrapper
	{
		public enum InitialNumberOfCreditsEnum
		{
			NUMBER_OF_CREDITS,
			DATA_FLOW_CONTROL_IS_NOT_USED,
			InvalidInitialNumberOfCreditsValue
		}

		public static class InitialNumberOfCreditsInfo
		{
			public static InitialNumberOfCreditsEnum ValueToInitialNumberOfCredits(uint value)
			{
				if (value >= 0 && value <= 254)
				{
					return InitialNumberOfCreditsEnum.NUMBER_OF_CREDITS;
				}
				if (value == 255)
				{
					return InitialNumberOfCreditsEnum.DATA_FLOW_CONTROL_IS_NOT_USED;
				}
				return InitialNumberOfCreditsEnum.InvalidInitialNumberOfCreditsValue;
			}

			public static uint InitialNumberOfCreditsToValue(InitialNumberOfCreditsEnum enumItem)
			{
				return enumItem switch
				{
					InitialNumberOfCreditsEnum.NUMBER_OF_CREDITS => 0u, 
					InitialNumberOfCreditsEnum.DATA_FLOW_CONTROL_IS_NOT_USED => 255u, 
					_ => uint.MaxValue, 
				};
			}

			public static string InitialNumberOfCreditsToString(InitialNumberOfCreditsEnum enumItem)
			{
				return enumItem switch
				{
					InitialNumberOfCreditsEnum.NUMBER_OF_CREDITS => "Number of credits", 
					InitialNumberOfCreditsEnum.DATA_FLOW_CONTROL_IS_NOT_USED => "Data flow control is not used", 
					_ => "Invalid InitialNumberOfCredits Value", 
				};
			}

			public static string InitialNumberOfCreditsToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0-0xFE = Number of credits");
				stringBuilder.AppendLine("0xFF = Data flow control is not used");
				return stringBuilder.ToString();
			}
		}

		private uint _Status;

		private uint _MaxDataPacketPayloadSize = 32u;

		private uint _InitialNumberOfCredits;

		private uint _ConnId;

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

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

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

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

		public StatusCodesEnum GetStatusAsStatusCodesEnum()
		{
			return StatusCodesInfo.ValueToStatusCodes(_Status);
		}

		public void SetStatusAsStatusCodesEnum(StatusCodesEnum enumItem)
		{
			Status = StatusCodesInfo.StatusCodesToValue(enumItem);
		}

		public InitialNumberOfCreditsEnum GetInitialNumberOfCreditsAsInitialNumberOfCreditsEnum()
		{
			return InitialNumberOfCreditsInfo.ValueToInitialNumberOfCredits(_InitialNumberOfCredits);
		}

		public void SetInitialNumberOfCreditsAsInitialNumberOfCreditsEnum(InitialNumberOfCreditsEnum enumItem)
		{
			InitialNumberOfCredits = InitialNumberOfCreditsInfo.InitialNumberOfCreditsToValue(enumItem);
		}
	}

	private const uint _Mt = 2u;

	private const uint _Gid = 0u;

	private const uint _Oid = 4u;

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

	private PacketInfoBase info;

	private uint _Pbf;

	private uint _Rfu;

	private uint _PayloadLength;

	public UserFieldsWrapper _UserFields = new UserFieldsWrapper();

	public override PacketType Type => PacketType.Response;

	public override Type[] ExpectedResponseTypes => expectedResponseTypes;

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

	public uint Mt => 2u;

	public uint Pbf => _Pbf;

	public uint Gid => 0u;

	public uint Rfu => _Rfu;

	public uint Oid => 4u;

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

	public UserFieldsWrapper UserFields => _UserFields;

	public override void SetDefaultValues()
	{
		UserFields.MaxDataPacketPayloadSize = 32u;
	}

	protected override bool FromBitBuilder(ref BitBuilder bitBuilder)
	{
		if (bitBuilder.RemoveBitsAsUint(3) != Mt)
		{
			return false;
		}
		_Pbf = bitBuilder.RemoveBitsAsUint(1);
		if (bitBuilder.RemoveBitsAsUint(4) != Gid)
		{
			return false;
		}
		_Rfu = bitBuilder.RemoveBitsAsUint(2);
		if (bitBuilder.RemoveBitsAsUint(6) != Oid)
		{
			return false;
		}
		_PayloadLength = bitBuilder.RemoveBitsAsUint(8);
		int numberOfBits = bitBuilder.GetNumberOfBits();
		if (numberOfBits > _PayloadLength * 8 + 7)
		{
			return false;
		}
		if (numberOfBits < _PayloadLength * 8)
		{
			return false;
		}
		UserFields.Status = bitBuilder.RemoveBitsAsUint(8);
		UserFields.MaxDataPacketPayloadSize = bitBuilder.RemoveBitsAsUint(8);
		UserFields.InitialNumberOfCredits = bitBuilder.RemoveBitsAsUint(8);
		UserFields.ConnId = bitBuilder.RemoveBitsAsUint(8);
		if (bitBuilder.GetNumberOfBits() > 7)
		{
			return false;
		}
		return true;
	}

	public override string ToBitString()
	{
		BitBuilder bitBuilder = new BitBuilder();
		bitBuilder.AddBitsAsUint(Mt, 3);
		bitBuilder.AddBitsAsUint(Pbf, 1);
		bitBuilder.AddBitsAsUint(Gid, 4);
		bitBuilder.AddBitsAsUint(Rfu, 2);
		bitBuilder.AddBitsAsUint(Oid, 6);
		int numberOfBits = bitBuilder.GetNumberOfBits();
		bitBuilder.AddBitsAsUint(0u, 8);
		bitBuilder.AddBitsAsUint(UserFields.Status, 8);
		bitBuilder.AddBitsAsUint(UserFields.MaxDataPacketPayloadSize, 8);
		bitBuilder.AddBitsAsUint(UserFields.InitialNumberOfCredits, 8);
		bitBuilder.AddBitsAsUint(UserFields.ConnId, 8);
		_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.MaxDataPacketPayloadSize < 32)
		{
			list.Add("Minimum allowed value for Max Data Packet Payload Size is 0x20");
		}
		return list;
	}
}
