using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Villain.Reflection;

namespace Villain.Networking.Packets
{
	public abstract class PacketHandler
	{
		public string ID { get; private set; }

		protected Dictionary<object, MethodInfo> _handlers = new Dictionary<object, MethodInfo>();

		public abstract bool Handle(Client client, IPacket packet);

		public PacketHandler(string id)
		{
			ID = id;

			GetHandlers();
		}
		
		private void GetHandlers()
		{
			IEnumerable<MethodByAttribute> methodsByAttribute = Reflector.FindMethodsByAttribute<PacketHandlerAttribute>();

			methodsByAttribute = methodsByAttribute.Where(x => ((PacketHandlerAttribute)x.Attribute).ForID == ID);

			foreach (MethodByAttribute handler in methodsByAttribute)
			{
				PacketHandlerAttribute packetHandlerAttribute = (PacketHandlerAttribute)handler.Attribute;

				var key = packetHandlerAttribute.Key;

				if (key is Enum)
				{
					key = Convert.ChangeType(key, ((Enum)key).GetTypeCode());
				}

				if (!_handlers.ContainsKey(key))
				{
					_handlers.Add(key, handler.MethodInfo);
				}
				else
				{
					throw new PacketHandlerException("Duplicate packet handler", handler);
				}
			}
		}

		protected static Action GetCallback(MethodInfo methodInfo, params object[] parameters)
		{
			return () => methodInfo.Invoke(null, parameters);
		}
	}
}