using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Extensions.Logging;
using ReallifeGamemode.Server.Common;
using ReallifeGamemode.Server.Core.API;
using ReallifeGamemode.Server.Log;
using ReallifeGamemode.Server.Types;

namespace ReallifeGamemode.Server.Core.Events
{
  public class EventHandler
  {
    private readonly IAPI api;

    public delegate void PlayerEvent(IPlayer player);
    public delegate void VehicleEvent(IVehicle vehicle);
    public delegate void PlayerVehicleEvent(IPlayer player, IVehicle vehicle);
    public delegate void PlayerDisconnectEvent(IPlayer player, DisconnectReason reason, string reasonString);

    public delegate void ClientEvent(IPlayer player, params object[] args);
    private static readonly Dictionary<string, ClientEvent> clientEvents = new Dictionary<string, ClientEvent>();

    public static event PlayerEvent OnPlayerJoin;
    public static event PlayerDisconnectEvent OnPlayerLeave;
    public static event PlayerVehicleEvent OnPlayerExitVehicle;

    private static readonly ILogger logger = LogManager.GetLogger<EventHandler>();

    public EventHandler(IAPI api)
    {
      this.api = api;
    }

    public void RegisterClientEvent(string eventName, ClientEvent clientEvent)
    {
      if (eventName.IsNullOrEmpty())
      {
        logger.LogWarning("'eventName' is null");
        return;
      }

      if (clientEvents.ContainsKey(eventName))
      {
        logger.LogError("Client event '{EventName}' is already registered", eventName);
        return;
      }

      clientEvents[eventName] = clientEvent;
    }

    public void HandleEvent(IPlayer player, List<object> data)
    {
      logger.LogDebug("Client event from '{Name}', data: '{DataStr}'", player.Name, data.SerializeJson());

      var eventName = data.Last() as string;

      if (eventName.IsNullOrEmpty())
      {
        logger.LogError("Client event name is null");
        return;
      }

      if (!clientEvents.ContainsKey(eventName))
      {
        logger.LogError("Client event '{EventName}' is not registered", eventName);
        return;
      }

      var arguments = data.Take(data.Count - 1).ToArray();

      clientEvents[eventName](player, arguments);
    }
  }
}
