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

public interface IFighterCallback
{
    void OnDeath();
}

// Generic subclass for any Fighter on the field, whether it's an Enemy or the AntiPlayer.
// Contains stats management such as health, attacks, damage, death, etc.
public abstract class Fighter : MonoBehaviour
{

    [SerializeField] int baseHealth = 100;
    [SerializeField, Tooltip("Attack every x seconds")] float baseAttackSpeed = 1f;
    [SerializeField] int baseAttackDamage = 10;
    [SerializeField] int baseArmor = 1;

    public List<IFighterCallback> callbacks = new List<IFighterCallback>();

    [SerializeField] protected int currentHealth = 100;
    protected Animator animator;
    protected bool alive { get => currentHealth > 0; }
    protected FighterTypes fighterType;
    protected abstract void Attack();

    float timeSinceLastAttack = 0f;

    protected virtual void Awake()
    {
        animator = GetComponent<Animator>();
        fighterType = FighterTypes.ENEMY;
    }

    protected virtual void Start()
    {
        currentHealth = Mathf.RoundToInt(baseHealth * GetStats().healthMultiplier);
    }

    protected virtual void Update()
    {
        if (alive)
        {
            timeSinceLastAttack += Time.deltaTime;
            var timeUntilNextAttack = baseAttackSpeed - timeSinceLastAttack;
            if (timeUntilNextAttack <= 0) // TODO only attack when near opposing faction
            {
                Attack();
                timeSinceLastAttack = -timeUntilNextAttack; // To account for overshoot
            }
        }
    }

    public void DealDamage(int dmg)
    {
        if (!alive)
        {
            return;
        }
        var actualDamage = Mathf.Max(0, Mathf.RoundToInt(dmg - baseArmor * GetStats().armorMultiplier));
        currentHealth = Mathf.Max(currentHealth - actualDamage, 0);
        if (currentHealth == 0)
        {
            animator.SetTrigger("Death");
            callbacks.ForEach(c => c.OnDeath());
            // TODO (Depending on the death animation) only destroy on round end so that corpses stay on the ground
            // Destroy(gameObject);
        }
        else
        {
            animator.SetTrigger("Hurt");
        }
    }

    protected FighterStats GetStats()
    {
        return StatsManager.instance.fighterStats[fighterType];
    }

    void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("AntiPlayer"))
        {
            var damageToDeal = Mathf.RoundToInt(baseAttackDamage * GetStats().damageMultiplier);
            other.GetComponent<Fighter>().DealDamage(damageToDeal);
        }
    }

}