using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GTANetworkAPI;
using Newtonsoft.Json;
using ReallifeGamemode.Server.Managers;

namespace ReallifeGamemode.Server.Util
{
  public static class AnimationSync
  {
    public static Dictionary<Player, List<string>> animationPair = new Dictionary<Player, List<string>>();

    public static void SyncAnimation(this Player player, dynamic animationName)
    {
      if (player.IsInVehicle)
        return;

      if (!player.HasData("Animation"))
        player.SetData("Animation", String.Empty);

      string currentAnimation = player.GetData<string>("Animation");
      string newAnimation = animationName;

      if (currentAnimation.Equals(newAnimation))
        return;

      player.SetSharedData("AnimationData", newAnimation);
      player.SetData<string>("Animation", newAnimation);
    }

    public static void SyncAnimation(this Player player, List<string> animations)
    {
      if (animations.Count is 0)
        return;

      string animationName = animations.ElementAt(0);
      List<string> nextAnimations = animations.Skip(1).ToList();
      player.SyncAnimation(animationName);

      if (nextAnimations.Count is 0)
      {
        animationPair.Remove(player);
        return;
      }

      player.TriggerEvent("SERVER:QueueAnimation", animationName);
      if (animationPair.ContainsKey(player))
        animationPair[player] = nextAnimations;
      else
        animationPair.Add(player, nextAnimations);
    }

    /// <summary>Check if Player has any Animation playing.
    /// </summary>
    /// <param name="player"></param>
    public static bool HasAnimation(this Player player)
    {
      return player.HasData("Animation");
    }

    /// <summary>Check if Player has a specific Animation playing.
    /// </summary>
    /// <param name="animationName">Name of requested animation</param>
    public static bool HasAnimation(this Player player, dynamic animationName)
    {
      return player.HasData("Animation") && (player.GetData<string>("Animation") == animationName);
    }

    public static void ClearAnimation(this Player player)
    {
      if (!player.HasData("Animation"))
        return;

      player.ResetData("Animation");
      player.ResetSharedData("AnimationData");
    }
  }

  public class AnimationSyncEvents : Script
  {
    [RemoteEvent("CLIENT:AnimPairTransition")]
    public void AnimPairTransition(Player player)
    {
      if (!AnimationSync.animationPair.ContainsKey(player))
        return;

      List<string> animationPairs = AnimationSync.animationPair[player];

      player.SyncAnimation(animationPairs);
    }

    [RemoteEvent("CLIENT:ClearAnimationData")]
    public void ClearAnimationData(Player player, bool checkTransition)
    {
      player.ClearAnimation();
      if (checkTransition)
      {
        AnimPairTransition(player);
      }
      else
      {
        player.ClearAttachments();
        PositionManager.cuffPoints.Remove(player);
      }
    }

    [ServerEvent(Event.PlayerWeaponSwitch)]
    public void OnPlayerWeaponSwitch(Player player, WeaponHash oldWeapon, WeaponHash newWeapon)
    {
      if (!player.HasAnimation()) return;
      NAPI.Player.SetPlayerCurrentWeapon(player, WeaponHash.Unarmed);
    }

    [ServerEvent(Event.PlayerConnected)]
    public void OnPlayerConnected(Player player)
    {
      player.TriggerEvent("SERVER:LoadAnimations");
    }

    [ServerEvent(Event.PlayerDeath)]
    public void OnPlayerDeath(Player player, Player killer, uint reason)
    {
      player.ClearAnimation();
    }
  }
}
