using System;
using System.Collections.Generic;

namespace QCRPG.Framework;

public abstract class PacketListBase
{
	private List<string> displayGroups = new List<string>();

	public abstract List<PacketBase> Packets { get; }

	public List<PacketBase> CommandPackets
	{
		get
		{
			List<PacketBase> list = new List<PacketBase>();
			foreach (PacketBase packet in Packets)
			{
				if (packet.Type == PacketType.Command)
				{
					list.Add(packet);
				}
			}
			return list;
		}
	}

	public List<PacketBase> ResponsePackets
	{
		get
		{
			List<PacketBase> list = new List<PacketBase>();
			foreach (PacketBase packet in Packets)
			{
				if (packet.Type == PacketType.Response)
				{
					list.Add(packet);
				}
			}
			return list;
		}
	}

	public List<PacketBase> NotificationPackets
	{
		get
		{
			List<PacketBase> list = new List<PacketBase>();
			foreach (PacketBase packet in Packets)
			{
				if (packet.Type == PacketType.Notification)
				{
					list.Add(packet);
				}
			}
			return list;
		}
	}

	public List<PacketBase> ResponseAsCommandPackets
	{
		get
		{
			List<PacketBase> result = new List<PacketBase>();
			foreach (PacketBase packet in Packets)
			{
				if (packet.Type == PacketType.ResponseAsCommand)
				{
					ResponseAsCommandPackets.Add(packet);
				}
			}
			return result;
		}
	}

	public List<PacketBase> EnhancedLogPackets
	{
		get
		{
			List<PacketBase> list = new List<PacketBase>();
			foreach (PacketBase packet in Packets)
			{
				if (packet.Type == PacketType.EnhancedLog)
				{
					list.Add(packet);
				}
			}
			return list;
		}
	}

	public List<string> DisplayGroups
	{
		get
		{
			if (displayGroups.Count == 0)
			{
				foreach (PacketBase packet in Packets)
				{
					if (!displayGroups.Contains(packet.Info.DisplayGroup))
					{
						displayGroups.Add(packet.Info.DisplayGroup);
					}
				}
			}
			return displayGroups;
		}
	}

	public PacketBase StringToPacket(string packetString)
	{
		string text = string.Empty;
		foreach (PacketBase packet in Packets)
		{
			try
			{
				if (packet.FromTextString(packetString))
				{
					return packet.DeepCopy();
				}
			}
			catch (Exception ex)
			{
				text = text + ex.Message + ' ';
			}
		}
		throw new Exception(text + packetString + " is not a valid packet");
	}

	public PacketBase BytesToPacket(byte[] bytes)
	{
		BitBuilder bitBuilder = new BitBuilder();
		foreach (byte b in bytes)
		{
			bitBuilder.AddBitsAsByte(b);
		}
		foreach (PacketBase packet in Packets)
		{
			try
			{
				if (packet.FromBitBuilder(bitBuilder))
				{
					return packet.DeepCopy();
				}
			}
			catch (Exception)
			{
			}
		}
		throw new Exception("Bytes are not a valid packet");
	}

	public PacketBase BytesToPacket(byte[] bytes, int length)
	{
		byte[] array = new byte[length];
		Array.Copy(bytes, array, length);
		return BytesToPacket(array);
	}

	public PacketBase BytesToPacketOfType(byte[] bytes, List<PacketType> packetTypes)
	{
		foreach (PacketBase packet in Packets)
		{
			if (!packetTypes.Contains(packet.Type))
			{
				continue;
			}
			try
			{
				if (packet.FromByteArray(bytes))
				{
					return packet.DeepCopy();
				}
			}
			catch (Exception)
			{
			}
		}
		throw new Exception("Bytes are not a valid packet");
	}

	public PacketBase BytesToPacketOfType(byte[] bytes, int length, List<PacketType> packetTypes)
	{
		byte[] array = new byte[length];
		Array.Copy(bytes, array, length);
		return BytesToPacketOfType(array, packetTypes);
	}

	public List<Type> GetCommandPacketTypes()
	{
		List<Type> list = new List<Type>();
		foreach (PacketBase packet in Packets)
		{
			if (packet.Type == PacketType.Command)
			{
				list.Add(packet.GetType());
			}
		}
		return list;
	}

	public List<Type> GetResponsePacketTypes()
	{
		List<Type> list = new List<Type>();
		foreach (PacketBase packet in Packets)
		{
			if (packet.Type == PacketType.Response)
			{
				list.Add(packet.GetType());
			}
		}
		return list;
	}

	public List<Type> GetNotificationPacketTypes()
	{
		List<Type> list = new List<Type>();
		foreach (PacketBase packet in Packets)
		{
			if (packet.Type == PacketType.Notification)
			{
				list.Add(packet.GetType());
			}
		}
		return list;
	}

	public List<Type> GetResponseAsCommandPacketTypes()
	{
		List<Type> list = new List<Type>();
		foreach (PacketBase packet in Packets)
		{
			if (packet.Type == PacketType.ResponseAsCommand)
			{
				list.Add(packet.GetType());
			}
		}
		return list;
	}
}
