using System;
using System.Collections.Generic;

namespace QCRPG.Framework;

public class SpecificPacketNotifier : IObserver<PacketBase>
{
	public delegate void PacketNotifier(PacketBase packet);

	private List<Type> packetTypeForNotification = new List<Type>();

	private List<PacketNotifier> callbackToNotify = new List<PacketNotifier>();

	private List<bool> notifyEnabled = new List<bool>();

	public void AddPacketNotification(Type type, PacketNotifier pktNotify)
	{
		if (!FindPacketNotifier(type, pktNotify, out var _))
		{
			packetTypeForNotification.Add(type);
			callbackToNotify.Add(pktNotify);
			notifyEnabled.Add(item: true);
		}
	}

	public void SetPacketNotification(Type type, PacketNotifier pktNotify, bool enabled)
	{
		if (FindPacketNotifier(type, pktNotify, out var foundIndex))
		{
			notifyEnabled[foundIndex] = enabled;
			return;
		}
		throw new KeyNotFoundException($"Packet Type: {type.ToString()} with packet notifier: {pktNotify.ToString()} not found!");
	}

	public void ClearAllPacketNotification()
	{
		packetTypeForNotification.Clear();
		callbackToNotify.Clear();
		notifyEnabled.Clear();
	}

	public void NotifyObserver(PacketBase packet)
	{
		Type type = packet.GetType();
		try
		{
			for (int i = 0; i < packetTypeForNotification.Count; i++)
			{
				if (packetTypeForNotification[i] == type && notifyEnabled[i])
				{
					callbackToNotify[i](packet);
				}
			}
		}
		catch (ArgumentOutOfRangeException)
		{
		}
	}

	private bool FindPacketNotifier(Type type, PacketNotifier pktNotify, out int foundIndex)
	{
		bool result = false;
		foundIndex = -1;
		for (int i = 0; i < packetTypeForNotification.Count; i++)
		{
			if (type == packetTypeForNotification[i] && pktNotify == callbackToNotify[i])
			{
				result = true;
				foundIndex = i;
			}
		}
		return result;
	}
}
