using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AntiPlayer : Fighter, IFighterCallback
{

    [SerializeField, Tooltip("How close the AntiPlayer has to be to start attacking, or how far away it has to be to start running towards the target")]
    float maxDistanceToEnemy = 1f;
    [SerializeField] float movementSpeed = 4f;
    [SerializeField, Tooltip("After killing an Enemy, how long to stay idle before targeting the next enemy")]
    float delayUntilNextTarget = 0.3f;

    List<Fighter> enemies = new List<Fighter>();
    Fighter currentTargetEnemy;
    string[] attackAnimationTriggers = new string[] { "Attack1", "Attack2", "Attack3" };

    protected override void Awake()
    {
        base.Awake();
        fighterType = FighterTypes.ANTI_PLAYER;
        opponentTag = "Enemy";
        // TODO Eventually, the player will be able to place enemies _after_ the AntiPlayer has been created.
        // Idea: Create a global GameManager-like class where scripts can register an IGameState callback,
        // which has a `OnRoundStart()` callback.
        foreach (var enemy in GameObject.FindGameObjectsWithTag("Enemy"))
        {
            var fighter = enemy.GetComponent<Fighter>();
            fighter.callbacks.Add(this);
            enemies.Add(fighter);
        }
        CalculateClosestEnemy();
        animator.SetBool("Grounded", true);
    }

    protected override void Update()
    {
        base.Update();
        if (!alive || currentTargetEnemy == null)
        {
            return;
        }

        var vectorToNextEnemy = currentTargetEnemy.transform.position - transform.position;
        var scale = transform.localScale;
        // Always face the target Enemy
        scale.x = vectorToNextEnemy.x < 0 ? -initalScale.x : initalScale.x;
        transform.localScale = scale;

        // Run towards target enemy if too far away
        if (Mathf.Abs(vectorToNextEnemy.x) > maxDistanceToEnemy)
        {
            animator.SetInteger("AnimState", 1); // Run
            rigidbody.velocity = new Vector2(Mathf.Sign(vectorToNextEnemy.x) * movementSpeed, rigidbody.velocity.y);
        } else
        {
            animator.SetInteger("AnimState", 0);
            rigidbody.velocity = new Vector2(0, rigidbody.velocity.y);
        }
    }
    protected override bool CanAttack()
    {
        if (currentTargetEnemy == null)
        {
            return false;
        }
        // Can only attack when near an Enemy
        var vectorToNextEnemy = currentTargetEnemy.transform.position - transform.position;
        return Mathf.Abs(vectorToNextEnemy.x) <= maxDistanceToEnemy;
    }

    protected override void Attack()
    {
        animator.SetTrigger(attackAnimationTriggers[Random.Range(0, attackAnimationTriggers.Length)]);
    }

    void CalculateClosestEnemy()
    {
        enemies.Sort((a, b) => (int)Mathf.Sign(Vector3.Distance(transform.position, a.transform.position) - Vector3.Distance(transform.position, b.transform.position)));
        currentTargetEnemy = enemies.Count > 0 ? enemies[0] : null;
    }

    public void OnFighterDeath(Fighter fighter)
    {
        enemies.Remove(fighter);
        // Wait a short time before targeting next enemy. This is to avoid interrupting the current
        // attack animation, which would happen if we immediately ran to the next target.
        currentTargetEnemy = null;
        Invoke(nameof(CalculateClosestEnemy), delayUntilNextTarget);
    }
}