using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;
using System.Threading.Tasks;
using System.Linq;

public class EnemyAI : MonoBehaviour
{
    [SerializeField] private TurnSystem turnSystem;
    [SerializeField] private UnitManager unitManager;
    private enum State {
        WaitingForEnemyTurn,
        TakingTurn,
        Busy,
    }
    private State state;
    private float timer;
    private void Awake() {
        state = State.WaitingForEnemyTurn;
    }
    private void Start() {
        turnSystem.OnTurnChanged += TurnSystem_OnTurnChanged;
    }
    private void Update() {
        if (turnSystem.IsPlayerTurn()) {
            return;
        }
        switch (state) {
            case State.WaitingForEnemyTurn:
                break;
            case State.TakingTurn:
                timer -= Time.deltaTime;
                if (timer <= 0f) {
                    if (TryTakeEnemyAIAction(SetStateTakingTurn)) {
                        state = State.Busy;
                    } else {
                        turnSystem.EndTurn();
                    }
                }
                break;
            case State.Busy:
                break;
        }
    }
    
    private void SetStateTakingTurn() {
        timer = 0.5f;
        state = State.TakingTurn;
    }
    private void TurnSystem_OnTurnChanged(object sender, EventArgs empty) {
        if (!turnSystem.IsPlayerTurn()) {
            state = State.TakingTurn;
            timer = 0.5f;
        }
    }

    private bool TryTakeEnemyAIAction(Action onEnemyAIActionComplete) {
        return unitManager.GetEnemyUnitList().Any(enemyUnit => TryTakeEnemyAIAction(enemyUnit, onEnemyAIActionComplete));
    }

    private bool TryTakeEnemyAIAction(Unit enemyUnit, Action onEnemyAIActionComplete) {
        BaseAction bestBaseAction = null;
        EnemyAIAction bestEnemyAIAction = null;

        foreach ((BaseAction baseAction, EnemyAIAction enemyAIAction) in enemyUnit.GetBaseActionArray()
                                                                                  .Where(baseAction => enemyUnit.CanSpendActionPointToTakeAction(baseAction))
                                                                                  .SelectMany(baseAction => baseAction.GetPossibleEnemyAIAction())
                                                                                  .Where(action => action.enemyAIAction.actionValue > 0)) {
            
            if (bestBaseAction == null) {
                bestBaseAction = baseAction;
                bestEnemyAIAction = enemyAIAction;
            } else {
                if (enemyAIAction.actionValue > bestEnemyAIAction.actionValue) {
                    bestBaseAction = baseAction;
                    bestEnemyAIAction = enemyAIAction;
                }
            }
        }

        bool spentActionPoint = false;
        if (bestBaseAction != null) {
            spentActionPoint = enemyUnit.TrySpendActionPointToTakeAction(bestBaseAction);
        }
        if (spentActionPoint) {
            bestBaseAction.TakeAction(bestEnemyAIAction.gridPosition, out CancellationToken cancellationToken);
            cancellationToken.Register(onEnemyAIActionComplete);
        }

        return spentActionPoint;
    }
}