using System;
using System.Collections.Generic;
using System.Reflection;
using Villain.Networking;
using Villain.Networking.Packets;

namespace Fiesta.Networking.Packets
{
	public class PacketHandler : Villain.Networking.Packets.PacketHandler, IDisposable
	{
		private PacketWorker _packetWorker = new PacketWorker();

		public PacketHandler(string id) : base(id)
		{
			_packetWorker.Start();
		}

		~PacketHandler()
		{
			Dispose();
		}

		public void Dispose()
		{
			_packetWorker.Stop();
		}

		public override bool Handle(Villain.Networking.Client client, IPacket packet)
		{
			return Handle((Client)client, (InPacket)packet);
		}

		public bool Handle(Client client, IPacket packet)
		{
			return Handle(client, (InPacket)packet);
		}

		public bool Handle(Client client, InPacket packet)
		{
			if (_handlers.ContainsKey(packet.Type))
			{
				Action callback = GetCallback(_handlers[packet.Type], client, packet);

				_packetWorker.Enqueue(callback);

				return true;
			}

			return false;
		}

		protected static Action GetCallback(MethodInfo methodInfo, Client client, InPacket packet)
		{
			return () =>
			{
				using (packet)
				{
					try
					{
						object[] parameters = new object[]
						{
							client,
							packet
						};

						methodInfo.Invoke(null, parameters);
					}
					catch
					{
						client.Disconnect();
					}
				}
			};
		}
	}
}