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

namespace QCRPG.TSL.BT.Packets;

public class DebugSimulateCxmMciRx : PacketBase
{
	public class UserFieldsWrapper
	{
		public enum MciHeaderEnum
		{
			Reserved,
			MCI_LNA_CTRL,
			MCI_CONT_NACK,
			MCI_CONT_INFO,
			MCI_CONT_RST,
			MCI_SCHED_INFO,
			MCI_CPU_INT,
			MCI_SYS_WAKING,
			MCI_GPM,
			MCI_LNA_INFO,
			MCI_LNA_STATE,
			MCI_LNA_TAKE,
			MCI_LNA_TRANS,
			MCI_SYS_SLEEPING,
			MCI_REQ_WAKE,
			MCI_AllWCI2_NTE,
			MCI_TYPE0WCI2_TE,
			MCI_DEBUG_16,
			MCI_REMOTE_RESET,
			InvalidMciHeaderValue
		}

		public static class MciHeaderInfo
		{
			public static MciHeaderEnum ValueToMciHeader(uint value)
			{
				return value switch
				{
					0u => MciHeaderEnum.Reserved, 
					16u => MciHeaderEnum.MCI_LNA_CTRL, 
					32u => MciHeaderEnum.MCI_CONT_NACK, 
					48u => MciHeaderEnum.MCI_CONT_INFO, 
					64u => MciHeaderEnum.MCI_CONT_RST, 
					80u => MciHeaderEnum.MCI_SCHED_INFO, 
					96u => MciHeaderEnum.MCI_CPU_INT, 
					112u => MciHeaderEnum.MCI_SYS_WAKING, 
					128u => MciHeaderEnum.MCI_GPM, 
					144u => MciHeaderEnum.MCI_LNA_INFO, 
					148u => MciHeaderEnum.MCI_LNA_STATE, 
					152u => MciHeaderEnum.MCI_LNA_TAKE, 
					156u => MciHeaderEnum.MCI_LNA_TRANS, 
					160u => MciHeaderEnum.MCI_SYS_SLEEPING, 
					192u => MciHeaderEnum.MCI_REQ_WAKE, 
					208u => MciHeaderEnum.MCI_AllWCI2_NTE, 
					212u => MciHeaderEnum.MCI_TYPE0WCI2_TE, 
					254u => MciHeaderEnum.MCI_DEBUG_16, 
					255u => MciHeaderEnum.MCI_REMOTE_RESET, 
					_ => MciHeaderEnum.InvalidMciHeaderValue, 
				};
			}

			public static uint MciHeaderToValue(MciHeaderEnum enumItem)
			{
				return enumItem switch
				{
					MciHeaderEnum.Reserved => 0u, 
					MciHeaderEnum.MCI_LNA_CTRL => 16u, 
					MciHeaderEnum.MCI_CONT_NACK => 32u, 
					MciHeaderEnum.MCI_CONT_INFO => 48u, 
					MciHeaderEnum.MCI_CONT_RST => 64u, 
					MciHeaderEnum.MCI_SCHED_INFO => 80u, 
					MciHeaderEnum.MCI_CPU_INT => 96u, 
					MciHeaderEnum.MCI_SYS_WAKING => 112u, 
					MciHeaderEnum.MCI_GPM => 128u, 
					MciHeaderEnum.MCI_LNA_INFO => 144u, 
					MciHeaderEnum.MCI_LNA_STATE => 148u, 
					MciHeaderEnum.MCI_LNA_TAKE => 152u, 
					MciHeaderEnum.MCI_LNA_TRANS => 156u, 
					MciHeaderEnum.MCI_SYS_SLEEPING => 160u, 
					MciHeaderEnum.MCI_REQ_WAKE => 192u, 
					MciHeaderEnum.MCI_AllWCI2_NTE => 208u, 
					MciHeaderEnum.MCI_TYPE0WCI2_TE => 212u, 
					MciHeaderEnum.MCI_DEBUG_16 => 254u, 
					MciHeaderEnum.MCI_REMOTE_RESET => 255u, 
					_ => uint.MaxValue, 
				};
			}

			public static string MciHeaderToString(MciHeaderEnum enumItem)
			{
				return enumItem switch
				{
					MciHeaderEnum.Reserved => "Reserved", 
					MciHeaderEnum.MCI_LNA_CTRL => "MCI_LNA_CTRL", 
					MciHeaderEnum.MCI_CONT_NACK => "MCI_CONT_NACK", 
					MciHeaderEnum.MCI_CONT_INFO => "MCI_CONT_INFO", 
					MciHeaderEnum.MCI_CONT_RST => "MCI_CONT_RST", 
					MciHeaderEnum.MCI_SCHED_INFO => "MCI_SCHED_INFO", 
					MciHeaderEnum.MCI_CPU_INT => "MCI_CPU_INT", 
					MciHeaderEnum.MCI_SYS_WAKING => "MCI_SYS_WAKING", 
					MciHeaderEnum.MCI_GPM => "MCI_GPM", 
					MciHeaderEnum.MCI_LNA_INFO => "MCI_LNA_INFO", 
					MciHeaderEnum.MCI_LNA_STATE => "MCI_LNA_STATE", 
					MciHeaderEnum.MCI_LNA_TAKE => "MCI_LNA_TAKE", 
					MciHeaderEnum.MCI_LNA_TRANS => "MCI_LNA_TRANS", 
					MciHeaderEnum.MCI_SYS_SLEEPING => "MCI_SYS_SLEEPING", 
					MciHeaderEnum.MCI_REQ_WAKE => "MCI_REQ_WAKE", 
					MciHeaderEnum.MCI_AllWCI2_NTE => "MCI_AllWCI2_NTE", 
					MciHeaderEnum.MCI_TYPE0WCI2_TE => "MCI_TYPE0WCI2_TE", 
					MciHeaderEnum.MCI_DEBUG_16 => "MCI_DEBUG_16", 
					MciHeaderEnum.MCI_REMOTE_RESET => "MCI_REMOTE_RESET", 
					_ => "Invalid MciHeader Value", 
				};
			}

			public static string MciHeaderToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = Reserved");
				stringBuilder.AppendLine("0x10 = MCI_LNA_CTRL");
				stringBuilder.AppendLine("0x20 = MCI_CONT_NACK");
				stringBuilder.AppendLine("0x30 = MCI_CONT_INFO");
				stringBuilder.AppendLine("0x40 = MCI_CONT_RST");
				stringBuilder.AppendLine("0x50 = MCI_SCHED_INFO");
				stringBuilder.AppendLine("0x60 = MCI_CPU_INT");
				stringBuilder.AppendLine("0x70 = MCI_SYS_WAKING");
				stringBuilder.AppendLine("0x80 = MCI_GPM");
				stringBuilder.AppendLine("0x90 = MCI_LNA_INFO");
				stringBuilder.AppendLine("0x94 = MCI_LNA_STATE");
				stringBuilder.AppendLine("0x98 = MCI_LNA_TAKE");
				stringBuilder.AppendLine("0x9C = MCI_LNA_TRANS");
				stringBuilder.AppendLine("0xA0 = MCI_SYS_SLEEPING");
				stringBuilder.AppendLine("0xC0 = MCI_REQ_WAKE");
				stringBuilder.AppendLine("0xD0 = MCI_AllWCI2_NTE");
				stringBuilder.AppendLine("0xD4 = MCI_TYPE0WCI2_TE");
				stringBuilder.AppendLine("0xFE = MCI_DEBUG_16");
				stringBuilder.AppendLine("0xFF = MCI_REMOTE_RESET");
				return stringBuilder.ToString();
			}
		}

		private const uint _SubOpcode = 54u;

		private uint _MciHeader;

		private List<uint> _MciBodyList = new List<uint>(new uint[16]);

		public uint SubOpcode => 54u;

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

		public List<uint> MciBodyList => _MciBodyList;

		public MciHeaderEnum GetMciHeaderAsMciHeaderEnum()
		{
			return MciHeaderInfo.ValueToMciHeader(_MciHeader);
		}

		public void SetMciHeaderAsMciHeaderEnum(MciHeaderEnum enumItem)
		{
			MciHeader = MciHeaderInfo.MciHeaderToValue(enumItem);
		}
	}

	private const uint _Opcode = 64524u;

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

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

	public uint Opcode => 64524u;

	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;
		}
		if (bitBuilder.RemoveBitsAsUint(8) != UserFields.SubOpcode)
		{
			return false;
		}
		UserFields.MciHeader = bitBuilder.RemoveBitsAsUint(8);
		for (int i = 0; i < UserFields.MciBodyList.Count; i++)
		{
			UserFields.MciBodyList[i] = 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.SubOpcode, 8);
		bitBuilder.AddBitsAsUint(UserFields.MciHeader, 8);
		for (int i = 0; i < UserFields.MciBodyList.Count; i++)
		{
			if (UserFields.MciBodyList[i] > 255)
			{
				throw new Exception("UserFields.MciBodyList[i] is > 0xFF");
			}
			bitBuilder.AddBitsAsUint(UserFields.MciBodyList[i], 8);
		}
		_PayloadLength = (uint)((bitBuilder.GetNumberOfBits() - numberOfBits - 8) / 8);
		if ((bitBuilder.GetNumberOfBits() - numberOfBits - 8) % 8 != 0)
		{
			_PayloadLength++;
		}
		bitBuilder.ChangeBitsAsUint(numberOfBits, _PayloadLength, 8);
		return bitBuilder.ToString();
	}
}
