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

namespace QCRPG.TSL.BT.Packets;

public class DumpInformationVse : PacketBase
{
	public class UserFieldsWrapper
	{
		public enum DumpReasonEnum
		{
			UNKNOWN,
			SW_REQUESTED,
			STACK_OVERFLOW,
			EXCEPTION,
			ASSERT,
			TRAP,
			OS_FATAL,
			HCI_RESET,
			PATCH_RESET,
			ABT,
			RAMMASK,
			PREBARK,
			BUSERROR,
			IOP_FATAL,
			SSR_CMD,
			POWERON,
			WATCHDOG,
			RAMMASK_RGN1,
			RAMMASK_RGN0,
			Q6_WATCHDOG,
			RX_INVALID_PKT_FATAL,
			RX_INVALID_PKT_LEN_FATAL,
			INVALID_STACK,
			InvalidDumpReasonValue
		}

		public static class DumpReasonInfo
		{
			public static DumpReasonEnum ValueToDumpReason(uint value)
			{
				return value switch
				{
					48513u => DumpReasonEnum.UNKNOWN, 
					48514u => DumpReasonEnum.SW_REQUESTED, 
					48515u => DumpReasonEnum.STACK_OVERFLOW, 
					48516u => DumpReasonEnum.EXCEPTION, 
					48517u => DumpReasonEnum.ASSERT, 
					48518u => DumpReasonEnum.TRAP, 
					48519u => DumpReasonEnum.OS_FATAL, 
					48520u => DumpReasonEnum.HCI_RESET, 
					48521u => DumpReasonEnum.PATCH_RESET, 
					48522u => DumpReasonEnum.ABT, 
					48523u => DumpReasonEnum.RAMMASK, 
					48524u => DumpReasonEnum.PREBARK, 
					48525u => DumpReasonEnum.BUSERROR, 
					48526u => DumpReasonEnum.IOP_FATAL, 
					48527u => DumpReasonEnum.SSR_CMD, 
					48528u => DumpReasonEnum.POWERON, 
					48529u => DumpReasonEnum.WATCHDOG, 
					48530u => DumpReasonEnum.RAMMASK_RGN1, 
					48531u => DumpReasonEnum.RAMMASK_RGN0, 
					48532u => DumpReasonEnum.Q6_WATCHDOG, 
					48576u => DumpReasonEnum.RX_INVALID_PKT_FATAL, 
					48577u => DumpReasonEnum.RX_INVALID_PKT_LEN_FATAL, 
					48624u => DumpReasonEnum.INVALID_STACK, 
					_ => DumpReasonEnum.InvalidDumpReasonValue, 
				};
			}

			public static uint DumpReasonToValue(DumpReasonEnum enumItem)
			{
				return enumItem switch
				{
					DumpReasonEnum.UNKNOWN => 48513u, 
					DumpReasonEnum.SW_REQUESTED => 48514u, 
					DumpReasonEnum.STACK_OVERFLOW => 48515u, 
					DumpReasonEnum.EXCEPTION => 48516u, 
					DumpReasonEnum.ASSERT => 48517u, 
					DumpReasonEnum.TRAP => 48518u, 
					DumpReasonEnum.OS_FATAL => 48519u, 
					DumpReasonEnum.HCI_RESET => 48520u, 
					DumpReasonEnum.PATCH_RESET => 48521u, 
					DumpReasonEnum.ABT => 48522u, 
					DumpReasonEnum.RAMMASK => 48523u, 
					DumpReasonEnum.PREBARK => 48524u, 
					DumpReasonEnum.BUSERROR => 48525u, 
					DumpReasonEnum.IOP_FATAL => 48526u, 
					DumpReasonEnum.SSR_CMD => 48527u, 
					DumpReasonEnum.POWERON => 48528u, 
					DumpReasonEnum.WATCHDOG => 48529u, 
					DumpReasonEnum.RAMMASK_RGN1 => 48530u, 
					DumpReasonEnum.RAMMASK_RGN0 => 48531u, 
					DumpReasonEnum.Q6_WATCHDOG => 48532u, 
					DumpReasonEnum.RX_INVALID_PKT_FATAL => 48576u, 
					DumpReasonEnum.RX_INVALID_PKT_LEN_FATAL => 48577u, 
					DumpReasonEnum.INVALID_STACK => 48624u, 
					_ => uint.MaxValue, 
				};
			}

			public static string DumpReasonToString(DumpReasonEnum enumItem)
			{
				return enumItem switch
				{
					DumpReasonEnum.UNKNOWN => "UNKNOWN", 
					DumpReasonEnum.SW_REQUESTED => "SW_REQUESTED", 
					DumpReasonEnum.STACK_OVERFLOW => "STACK_OVERFLOW", 
					DumpReasonEnum.EXCEPTION => "EXCEPTION", 
					DumpReasonEnum.ASSERT => "ASSERT", 
					DumpReasonEnum.TRAP => "TRAP", 
					DumpReasonEnum.OS_FATAL => "OS_FATAL", 
					DumpReasonEnum.HCI_RESET => "HCI_RESET", 
					DumpReasonEnum.PATCH_RESET => "PATCH_RESET", 
					DumpReasonEnum.ABT => "ABT", 
					DumpReasonEnum.RAMMASK => "RAMMASK", 
					DumpReasonEnum.PREBARK => "PREBARK", 
					DumpReasonEnum.BUSERROR => "BUSERROR", 
					DumpReasonEnum.IOP_FATAL => "IOP_FATAL", 
					DumpReasonEnum.SSR_CMD => "SSR_CMD", 
					DumpReasonEnum.POWERON => "POWERON", 
					DumpReasonEnum.WATCHDOG => "WATCHDOG", 
					DumpReasonEnum.RAMMASK_RGN1 => "RAMMASK_RGN1", 
					DumpReasonEnum.RAMMASK_RGN0 => "RAMMASK_RGN0", 
					DumpReasonEnum.Q6_WATCHDOG => "Q6_WATCHDOG", 
					DumpReasonEnum.RX_INVALID_PKT_FATAL => "RX_INVALID_PKT_FATAL", 
					DumpReasonEnum.RX_INVALID_PKT_LEN_FATAL => "RX_INVALID_PKT_LEN_FATAL", 
					DumpReasonEnum.INVALID_STACK => "INVALID_STACK", 
					_ => "Invalid DumpReason Value", 
				};
			}

			public static string DumpReasonToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0xBD81 = UNKNOWN");
				stringBuilder.AppendLine("0xBD82 = SW_REQUESTED");
				stringBuilder.AppendLine("0xBD83 = STACK_OVERFLOW");
				stringBuilder.AppendLine("0xBD84 = EXCEPTION");
				stringBuilder.AppendLine("0xBD85 = ASSERT");
				stringBuilder.AppendLine("0xBD86 = TRAP");
				stringBuilder.AppendLine("0xBD87 = OS_FATAL");
				stringBuilder.AppendLine("0xBD88 = HCI_RESET");
				stringBuilder.AppendLine("0xBD89 = PATCH_RESET");
				stringBuilder.AppendLine("0xBD8A = ABT");
				stringBuilder.AppendLine("0xBD8B = RAMMASK");
				stringBuilder.AppendLine("0xBD8C = PREBARK");
				stringBuilder.AppendLine("0xBD8D = BUSERROR");
				stringBuilder.AppendLine("0xBD8E = IOP_FATAL");
				stringBuilder.AppendLine("0xBD8F = SSR_CMD");
				stringBuilder.AppendLine("0xBD90 = POWERON");
				stringBuilder.AppendLine("0xBD91 = WATCHDOG");
				stringBuilder.AppendLine("0xBD92 = RAMMASK_RGN1");
				stringBuilder.AppendLine("0xBD93 = RAMMASK_RGN0");
				stringBuilder.AppendLine("0xBD94 = Q6_WATCHDOG");
				stringBuilder.AppendLine("0xBDC0 = RX_INVALID_PKT_FATAL");
				stringBuilder.AppendLine("0xBDC1 = RX_INVALID_PKT_LEN_FATAL");
				stringBuilder.AppendLine("0xBDF0 = INVALID_STACK");
				return stringBuilder.ToString();
			}
		}

		private const uint _VendorEventClass = 1u;

		private const uint _MessageType = 9u;

		private uint _BuildVersion;

		private uint _DumpReason;

		private uint _ArmRegistersSize;

		private List<uint> _ArmRegistersList = new List<uint>();

		private uint _CallStackSize;

		private List<uint> _CallStackList = new List<uint>();

		public uint VendorEventClass => 1u;

		public uint MessageType => 9u;

		public uint BuildVersion
		{
			get
			{
				return _BuildVersion;
			}
			set
			{
				_BuildVersion = value;
			}
		}

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

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

		public List<uint> ArmRegistersList => _ArmRegistersList;

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

		public List<uint> CallStackList => _CallStackList;

		public DumpReasonEnum GetDumpReasonAsDumpReasonEnum()
		{
			return DumpReasonInfo.ValueToDumpReason(_DumpReason);
		}

		public void SetDumpReasonAsDumpReasonEnum(DumpReasonEnum enumItem)
		{
			DumpReason = DumpReasonInfo.DumpReasonToValue(enumItem);
		}
	}

	private const uint _EventCode = 255u;

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

	public uint EventCode => 255u;

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

	public UserFieldsWrapper UserFields => _UserFields;

	public override void SetDefaultValues()
	{
		UserFields.ArmRegistersSize = 76u;
	}

	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;
		}
		if (bitBuilder.RemoveBitsAsUint(8) != UserFields.VendorEventClass)
		{
			return false;
		}
		if (bitBuilder.RemoveBitsAsUint(8) != UserFields.MessageType)
		{
			return false;
		}
		UserFields.BuildVersion = bitBuilder.RemoveBitsAsUintLittleEndian(32);
		UserFields.DumpReason = bitBuilder.RemoveBitsAsUintLittleEndian(16);
		UserFields.ArmRegistersSize = bitBuilder.RemoveBitsAsUint(8);
		for (int num = UserFields.ArmRegistersList.Count - 1; num >= 0; num--)
		{
			UserFields.ArmRegistersList[num] = bitBuilder.RemoveBitsAsUint(8);
		}
		UserFields.CallStackSize = bitBuilder.RemoveBitsAsUint(8);
		for (int i = 0; i < UserFields.CallStackList.Count; i++)
		{
			UserFields.CallStackList[i] = bitBuilder.RemoveBitsAsUint(8);
		}
		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.VendorEventClass, 8);
		bitBuilder.AddBitsAsUint(UserFields.MessageType, 8);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.BuildVersion, 32);
		bitBuilder.AddBitsAsUintLittleEndian(UserFields.DumpReason, 16);
		bitBuilder.AddBitsAsUint(UserFields.ArmRegistersSize, 8);
		for (int num = UserFields.ArmRegistersList.Count - 1; num >= 0; num--)
		{
			if (UserFields.ArmRegistersList[num] > 255)
			{
				throw new Exception("UserFields.ArmRegistersList[i] is > 0xFF");
			}
			bitBuilder.AddBitsAsUint(UserFields.ArmRegistersList[num], 8);
		}
		bitBuilder.AddBitsAsUint(UserFields.CallStackSize, 8);
		for (int i = 0; i < UserFields.CallStackList.Count; i++)
		{
			if (UserFields.CallStackList[i] > 255)
			{
				throw new Exception("UserFields.CallStackList[i] is > 0xFF");
			}
			bitBuilder.AddBitsAsUint(UserFields.CallStackList[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();
	}

	public override List<string> GetWarnings()
	{
		List<string> list = new List<string>();
		if (UserFields.CallStackSize > 128)
		{
			list.Add("Maximum allowed value for Call Stack Size is 0x80");
		}
		return list;
	}
}
