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

namespace QCRPG.TSL.BT.Packets;

public class IsoData : PacketBase
{
	public class UserFieldsWrapper
	{
		public enum PbFlagEnum
		{
			FIRST_FRAGMENT,
			CONTINUATION_FRAGMENT,
			LAST_FRAGMENT,
			InvalidPbFlagValue
		}

		public static class PbFlagInfo
		{
			public static PbFlagEnum ValueToPbFlag(uint value)
			{
				return value switch
				{
					0u => PbFlagEnum.FIRST_FRAGMENT, 
					1u => PbFlagEnum.CONTINUATION_FRAGMENT, 
					3u => PbFlagEnum.LAST_FRAGMENT, 
					_ => PbFlagEnum.InvalidPbFlagValue, 
				};
			}

			public static uint PbFlagToValue(PbFlagEnum enumItem)
			{
				return enumItem switch
				{
					PbFlagEnum.FIRST_FRAGMENT => 0u, 
					PbFlagEnum.CONTINUATION_FRAGMENT => 1u, 
					PbFlagEnum.LAST_FRAGMENT => 3u, 
					_ => uint.MaxValue, 
				};
			}

			public static string PbFlagToString(PbFlagEnum enumItem)
			{
				return enumItem switch
				{
					PbFlagEnum.FIRST_FRAGMENT => "FIRST_FRAGMENT", 
					PbFlagEnum.CONTINUATION_FRAGMENT => "CONTINUATION_FRAGMENT", 
					PbFlagEnum.LAST_FRAGMENT => "LAST_FRAGMENT", 
					_ => "Invalid PbFlag Value", 
				};
			}

			public static string PbFlagToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = FIRST_FRAGMENT");
				stringBuilder.AppendLine("0x1 = CONTINUATION_FRAGMENT");
				stringBuilder.AppendLine("0x3 = LAST_FRAGMENT");
				return stringBuilder.ToString();
			}
		}

		public enum TsFlagEnum
		{
			TIMESTAMP_DISABLED,
			TIMESTAMP_ENABLED,
			InvalidTsFlagValue
		}

		public static class TsFlagInfo
		{
			public static TsFlagEnum ValueToTsFlag(uint value)
			{
				return value switch
				{
					0u => TsFlagEnum.TIMESTAMP_DISABLED, 
					1u => TsFlagEnum.TIMESTAMP_ENABLED, 
					_ => TsFlagEnum.InvalidTsFlagValue, 
				};
			}

			public static uint TsFlagToValue(TsFlagEnum enumItem)
			{
				return enumItem switch
				{
					TsFlagEnum.TIMESTAMP_DISABLED => 0u, 
					TsFlagEnum.TIMESTAMP_ENABLED => 1u, 
					_ => uint.MaxValue, 
				};
			}

			public static string TsFlagToString(TsFlagEnum enumItem)
			{
				return enumItem switch
				{
					TsFlagEnum.TIMESTAMP_DISABLED => "TIMESTAMP_DISABLED", 
					TsFlagEnum.TIMESTAMP_ENABLED => "TIMESTAMP_ENABLED", 
					_ => "Invalid TsFlag Value", 
				};
			}

			public static string TsFlagToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = TIMESTAMP_DISABLED");
				stringBuilder.AppendLine("0x1 = TIMESTAMP_ENABLED");
				return stringBuilder.ToString();
			}
		}

		public enum PacketStatusFlagEnum
		{
			VALID_DATA,
			POSSIBLY_INVALID_DATA,
			LOST_DATA,
			InvalidPacketStatusFlagValue
		}

		public static class PacketStatusFlagInfo
		{
			public static PacketStatusFlagEnum ValueToPacketStatusFlag(uint value)
			{
				return value switch
				{
					0u => PacketStatusFlagEnum.VALID_DATA, 
					1u => PacketStatusFlagEnum.POSSIBLY_INVALID_DATA, 
					2u => PacketStatusFlagEnum.LOST_DATA, 
					_ => PacketStatusFlagEnum.InvalidPacketStatusFlagValue, 
				};
			}

			public static uint PacketStatusFlagToValue(PacketStatusFlagEnum enumItem)
			{
				return enumItem switch
				{
					PacketStatusFlagEnum.VALID_DATA => 0u, 
					PacketStatusFlagEnum.POSSIBLY_INVALID_DATA => 1u, 
					PacketStatusFlagEnum.LOST_DATA => 2u, 
					_ => uint.MaxValue, 
				};
			}

			public static string PacketStatusFlagToString(PacketStatusFlagEnum enumItem)
			{
				return enumItem switch
				{
					PacketStatusFlagEnum.VALID_DATA => "VALID_DATA", 
					PacketStatusFlagEnum.POSSIBLY_INVALID_DATA => "POSSIBLY_INVALID_DATA", 
					PacketStatusFlagEnum.LOST_DATA => "LOST_DATA", 
					_ => "Invalid PacketStatusFlag Value", 
				};
			}

			public static string PacketStatusFlagToDescription()
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("0x0 = VALID_DATA");
				stringBuilder.AppendLine("0x1 = POSSIBLY_INVALID_DATA");
				stringBuilder.AppendLine("0x2 = LOST_DATA");
				return stringBuilder.ToString();
			}
		}

		private uint _ConnectionHandle;

		private uint _PbFlag;

		private uint _TsFlag;

		private uint _Rfu0;

		private uint _Rfu1;

		private uint _TimeStamp;

		private uint _PacketSequenceNumber;

		private uint _IsoSduLength;

		private uint _Rfu2;

		private uint _PacketStatusFlag;

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

		public uint ConnectionHandle
		{
			get
			{
				return _ConnectionHandle;
			}
			set
			{
				if (value > 4095)
				{
					throw new Exception("Maximum possible value for ConnectionHandle is 0xFFF");
				}
				_ConnectionHandle = value;
			}
		}

		public uint PbFlag
		{
			get
			{
				return _PbFlag;
			}
			set
			{
				if (value > 3)
				{
					throw new Exception("Maximum possible value for PbFlag is 0x3");
				}
				_PbFlag = value;
			}
		}

		public uint TsFlag
		{
			get
			{
				return _TsFlag;
			}
			set
			{
				if (value > 1)
				{
					throw new Exception("Maximum possible value for TsFlag is 0x1");
				}
				_TsFlag = value;
			}
		}

		public uint Rfu0
		{
			get
			{
				return _Rfu0;
			}
			set
			{
				if (value > 1)
				{
					throw new Exception("Maximum possible value for Rfu0 is 0x1");
				}
				_Rfu0 = value;
			}
		}

		public uint Rfu1
		{
			get
			{
				return _Rfu1;
			}
			set
			{
				if (value > 3)
				{
					throw new Exception("Maximum possible value for Rfu1 is 0x3");
				}
				_Rfu1 = value;
			}
		}

		public uint TimeStamp
		{
			get
			{
				return _TimeStamp;
			}
			set
			{
				_TimeStamp = value;
			}
		}

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

		public uint IsoSduLength
		{
			get
			{
				return _IsoSduLength;
			}
			set
			{
				if (value > 4095)
				{
					throw new Exception("Maximum possible value for IsoSduLength is 0xFFF");
				}
				_IsoSduLength = value;
				while (_IsoSduList.Count < _IsoSduLength)
				{
					_IsoSduList.Add(0u);
				}
				while (_IsoSduList.Count > _IsoSduLength)
				{
					_IsoSduList.RemoveAt(_IsoSduList.Count - 1);
				}
			}
		}

		public uint Rfu2
		{
			get
			{
				return _Rfu2;
			}
			set
			{
				if (value > 3)
				{
					throw new Exception("Maximum possible value for Rfu2 is 0x3");
				}
				_Rfu2 = value;
			}
		}

		public uint PacketStatusFlag
		{
			get
			{
				return _PacketStatusFlag;
			}
			set
			{
				if (value > 3)
				{
					throw new Exception("Maximum possible value for PacketStatusFlag is 0x3");
				}
				_PacketStatusFlag = value;
			}
		}

		public List<uint> IsoSduList => _IsoSduList;

		public PbFlagEnum GetPbFlagAsPbFlagEnum()
		{
			return PbFlagInfo.ValueToPbFlag(_PbFlag);
		}

		public void SetPbFlagAsPbFlagEnum(PbFlagEnum enumItem)
		{
			PbFlag = PbFlagInfo.PbFlagToValue(enumItem);
		}

		public TsFlagEnum GetTsFlagAsTsFlagEnum()
		{
			return TsFlagInfo.ValueToTsFlag(_TsFlag);
		}

		public void SetTsFlagAsTsFlagEnum(TsFlagEnum enumItem)
		{
			TsFlag = TsFlagInfo.TsFlagToValue(enumItem);
		}

		public PacketStatusFlagEnum GetPacketStatusFlagAsPacketStatusFlagEnum()
		{
			return PacketStatusFlagInfo.ValueToPacketStatusFlag(_PacketStatusFlag);
		}

		public void SetPacketStatusFlagAsPacketStatusFlagEnum(PacketStatusFlagEnum enumItem)
		{
			PacketStatusFlag = PacketStatusFlagInfo.PacketStatusFlagToValue(enumItem);
		}
	}

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

	private PacketInfoBase info;

	private uint _IsoDataLoadLength;

	public UserFieldsWrapper _UserFields = new UserFieldsWrapper();

	public override PacketType Type => PacketType.Data;

	public override bool SuppressRawByteLogging => true;

	public override Type[] ExpectedResponseTypes => expectedResponseTypes;

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

	public uint IsoDataLoadLength
	{
		get
		{
			ToBitString();
			return _IsoDataLoadLength;
		}
		set
		{
			_IsoDataLoadLength = value;
		}
	}

	public UserFieldsWrapper UserFields => _UserFields;

	protected override bool FromBitBuilder(ref BitBuilder bitBuilder)
	{
		UserFields.ConnectionHandle = Convert.ToUInt32(bitBuilder.RemoveBitsAsString(8), 2);
		uint num = bitBuilder.RemoveBitsAsUint(8);
		UserFields.ConnectionHandle += (num & 0xF) << 8;
		UserFields.PbFlag = (num & 0x30) >> 4;
		UserFields.TsFlag = (num & 0x40) >> 6;
		UserFields.Rfu0 = (num & 0x80) >> 7;
		_IsoDataLoadLength = Convert.ToUInt32(bitBuilder.RemoveBitsAsString(8), 2);
		_IsoDataLoadLength += Convert.ToUInt32(bitBuilder.RemoveBitsAsString(6), 2) << 8;
		int numberOfBits = bitBuilder.GetNumberOfBits();
		if (numberOfBits > _IsoDataLoadLength * 8 + 7)
		{
			return false;
		}
		if (numberOfBits < _IsoDataLoadLength * 8)
		{
			return false;
		}
		UserFields.Rfu1 = bitBuilder.RemoveBitsAsUint(2);
		if (UserFields.PbFlag == 0)
		{
			if (UserFields.TsFlag == 1)
			{
				UserFields.TimeStamp = bitBuilder.RemoveBitsAsUintLittleEndian(32);
			}
			else
			{
				UserFields.TimeStamp = 0u;
			}
			UserFields.PacketSequenceNumber = bitBuilder.RemoveBitsAsUintLittleEndian(16);
			UserFields.IsoSduLength = Convert.ToUInt32(bitBuilder.RemoveBitsAsString(8), 2);
			UserFields.IsoSduLength += Convert.ToUInt32(bitBuilder.RemoveBitsAsString(4), 2) << 8;
			UserFields.Rfu2 = bitBuilder.RemoveBitsAsUint(2);
			UserFields.PacketStatusFlag = bitBuilder.RemoveBitsAsUint(2);
			while (UserFields.IsoSduList.Count < UserFields.IsoSduLength)
			{
				UserFields.IsoSduList.Add(0u);
			}
			while (UserFields.IsoSduList.Count > UserFields.IsoSduLength)
			{
				UserFields.IsoSduList.RemoveAt(UserFields.IsoSduList.Count - 1);
			}
		}
		else
		{
			while (UserFields.IsoSduList.Count < _IsoDataLoadLength)
			{
				UserFields.IsoSduList.Add(0u);
			}
			while (UserFields.IsoSduList.Count > _IsoDataLoadLength)
			{
				UserFields.IsoSduList.RemoveAt(UserFields.IsoSduList.Count - 1);
			}
		}
		for (int i = 0; i < UserFields.IsoSduList.Count; i++)
		{
			UserFields.IsoSduList[i] = bitBuilder.RemoveBitsAsUint(8);
		}
		if (bitBuilder.GetNumberOfBits() > 7)
		{
			return false;
		}
		return true;
	}

	public override string ToBitString()
	{
		BitBuilder bitBuilder = new BitBuilder();
		bitBuilder.AddBitsAsUint(UserFields.ConnectionHandle & 0xFFu, 8);
		byte b = (byte)((UserFields.ConnectionHandle & 0xF00) >> 8);
		b += (byte)((UserFields.PbFlag & 3) << 4);
		b += (byte)((UserFields.TsFlag & 1) << 6);
		b += (byte)((UserFields.Rfu0 & 1) << 7);
		bitBuilder.AddBitsAsUint(b, 8);
		bitBuilder.AddBitsAsUint(_IsoDataLoadLength & 0xFFu, 8);
		bitBuilder.AddBitsAsUint((_IsoDataLoadLength & 0xF00) >> 8, 6);
		bitBuilder.AddBitsAsUint(UserFields.Rfu1, 2);
		if (UserFields.PbFlag == 0)
		{
			if (UserFields.TsFlag == 1)
			{
				bitBuilder.AddBitsAsUintLittleEndian(UserFields.TimeStamp, 32);
			}
			bitBuilder.AddBitsAsUintLittleEndian(UserFields.PacketSequenceNumber, 16);
			bitBuilder.AddBitsAsUint(UserFields.IsoSduLength & 0xFFu, 8);
			bitBuilder.AddBitsAsUint(UserFields.IsoSduLength & 0xF00u, 4);
			bitBuilder.AddBitsAsUint(UserFields.Rfu2, 2);
			bitBuilder.AddBitsAsUint(UserFields.PacketStatusFlag, 2);
		}
		for (int i = 0; i < UserFields.IsoSduList.Count; i++)
		{
			if (UserFields.IsoSduList[i] > 255)
			{
				throw new Exception("UserFields.IsoSduList[i] is > 0xFF");
			}
			bitBuilder.AddBitsAsUint(UserFields.IsoSduList[i], 8);
		}
		return bitBuilder.ToString();
	}
}
