using System.Collections;
using System.Collections.Generic;
using System.Linq;
using RPG_Fight_Test.Assets.Scripts.Weapons;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class Creature : MonoBehaviour, ICreatureInterface {

    [SerializeField] Sprite creatureImage;
    [SerializeField] bool humanControlled;

    private int init;
    private int dex = 0;
    private int creatureHealth;
    private List<IAction> actions = new List<IAction>();

    internal int CurrentHealth { get; set; }
    internal int MaxHealth { get; set; }


    Weapon weapon;
    int health;
    private Vector3Int currentPos;

    internal IAction GetFirstAction() {
        return firstAction;
    }
    internal IAction GetSecondAction() {
        return secondAction;
    }

    private IAction firstAction;
    private IAction secondAction;
    public GameObject InitPanelGameObject { set; get; }

    internal int movementRate;
    private bool active;

    public int Dex { get => dex; set => dex = value; }

    public int Init { get => init; set => init = value; }

    public int CreatureHealth { get => creatureHealth; set => creatureHealth = value; }
    public bool IsCreatureAlive { get; set; }
    public Vector3Int CurrentPos { get => currentPos; set => currentPos = value; }
    public virtual IWeapon PrimaryWeapon { get; set; }
    public virtual int Evade { get; set; }

    public int GetInit() {
        return Init;
    }

    public IEnumerator WaitForPlayerAction() {

        active = true;
        while (!HasFirstAction()) {
            yield return null;
        }

        while (!HasSecondAction()) {
            yield return null;
        }

        active = false;
    }

    private void OnMouseUp() {
        Debug.Log("Mouse up on tile or Creature " + this.name);
        SetFirstAction(new AttackAction(this, this));
        SetSecondAction(new AttackAction(this, this));
    }

    internal void SetActive(bool v) {
        active = v;
    }

    internal bool HasSecondAction() {
        return secondAction != null;
    }

    public void RollInit() {
        Init = Random.Range(0, 100 - dex);
    }

    public Sprite GetSprite() {
        return creatureImage;
    }

    public bool IsHumanControlled() {
        return humanControlled;
    }

    public void SetFirstAction(IAction action) {
        firstAction = action;
    }

    public void SetSecondAction(IAction action) {
        secondAction = action;
    }

    internal List<Creature> EnemiesInSquareNextToCreature(Creature creature, List<Creature> combatants) {
        List<Creature> enemiesClose = new List<Creature>();
        foreach (Creature c in combatants) {
            Vector3 distance = c.CurrentPos - creature.CurrentPos;
            if (c.name != creature.name && distance.x <= 1 && distance.x >= -1 && distance.y <= 1 && distance.y >= -1) {
                enemiesClose.Add(c);
            }
        }
        return enemiesClose;
    }

    internal void SetPositionInGrid(Vector3Int vector3Int) {
        CurrentPos = vector3Int;
    }

    public bool HasFirstAction() {
        return firstAction != null;
    }

    internal Creature FindClosestEnemy(Creature creature, List<Creature> combatants) {
        Creature closestEnemy = null;
        float minDist = Mathf.Infinity;
        List<Creature> enemies = combatants.FindAll(p => p.IsHumanControlled() != creature.IsHumanControlled());

        foreach (Creature e in enemies) {
            float dist = Vector3.Distance(e.CurrentPos, creature.CurrentPos);
            if (dist < minDist) {
                closestEnemy = e;
                minDist = dist;
            }
            Debug.Log("Closest enemy is " + closestEnemy.name);
        }
        return closestEnemy;
    }

    public void Death() {
        IsCreatureAlive = false;
    }


    public void TakeDamage(int damage) {
        CurrentHealth -= damage;
        if (CurrentHealth <= 0) {
            Death();
        }

        InitPanelGameObject.GetComponent<InitCreaturePanelScript>().UpdateHealthBar(MaxHealth / CurrentHealth);
    }

    public virtual IAction ActionWhenBlocked(Creature blockingCreature) {
        throw new System.Exception("The Creature must decide this, add it to the specific creature");
    }

    public virtual void DecideActions(List<Creature> combatants) {
        throw new System.Exception("The Creature must decide this, add it to the specific creature");
    }

}
