using UnityEngine;
using UnityEngine.AI;
using Random = UnityEngine.Random;

public class PlayerAnimator : MonoBehaviour
{
    static readonly int Die = Animator.StringToHash("Die");
    static readonly int Crit = Animator.StringToHash("Crit");
    static readonly int Attack = Animator.StringToHash("Attack");
    static readonly int TakeHit = Animator.StringToHash("Take Hit");
    static readonly int Idle = Animator.StringToHash("Idle");
    static readonly int Speed = Animator.StringToHash("Speed");
    static readonly int Taunt = Animator.StringToHash("Taunt");
    static readonly int Victory = Animator.StringToHash("Victory");

    [SerializeField] Battler _battler;
    [SerializeField] NavMeshAgent _agent;
    [SerializeField] Animator _animator;

    double _nextAnimationRandomTime;
    float _idleAnimationBlend;

    void Start()
    {
        _battler.PerformedAttack += PlayPerformAttack;
        _battler.TookHit += PlayTookHit;
        _battler.Died += PlayDied;
        _battler.Won += PlayWon;
    }

    void PlayTookHit(int damage, bool wasCrit) => _animator.SetTrigger(TakeHit);
    void PlayDied() => _animator.SetTrigger(Die);
    void PlayWon() => _animator.SetTrigger(Victory);


    void PlayPerformAttack(int damage)
    {
        if (damage < BattleManager.Settings.CriticalDamage)
            _animator.SetTrigger(Attack);
        else
            _animator.SetTrigger(Crit);
    }


    void Update()
    {
        if (_animator == null || _animator.enabled == false || _animator.gameObject.activeSelf == false)
        {
            _animator = GetComponentInChildren<Animator>(false);
            if (!_animator)
                return;

            var currentInfo = _animator.GetCurrentAnimatorStateInfo(0);
            _animator.Play(currentInfo.fullPathHash, 0, Random.value);
            _animator.speed = Random.Range(0.95f, 1.05f);
            _animator.enabled = true;
            _animator.SetFloat(Idle, 0f);
        }

        if (ShouldStop())
        {
            RandomizeIdle();
            _animator.SetFloat(Speed, 0f);
        }
        else
        {
            float speed = Mathf.Lerp(0.15f, 1f, _agent.velocity.magnitude / _agent.speed);
            _animator.SetFloat(Speed, speed);
        }
    }

    bool ShouldStop() => _agent.enabled == false || _agent.isOnNavMesh == false || _agent.remainingDistance <= _agent.stoppingDistance + 0.1f;

    void RandomizeIdle()
    {
        if (Time.time >= _nextAnimationRandomTime)
        {
            _nextAnimationRandomTime = Time.time + 5f;
            _idleAnimationBlend = Random.Range(0, 1f);
            if (Random.Range(0, 100) < 25)
                _animator.SetTrigger(Taunt);
        }

        _animator.SetFloat(Idle, _idleAnimationBlend, 0.5f, Time.deltaTime);
    }

    void OnValidate()
    {
        _battler = GetComponent<Battler>();
        _agent = GetComponent<NavMeshAgent>();
    }
}