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

namespace Actions {
    public class SwordAction : BaseAction {
        private State state;
        private float stateTimer;

        public int MaxSwordDistance { get; private set; }
        private Unit TargetUnit { get; set; }

        protected override void Awake() {
            base.Awake();
            ActionPointsCost = 1;
            MaxSwordDistance = 1;
            ActionName = "Sword";
        }

        private void Update() {
            if (!IsActive) return;

            stateTimer -= Time.deltaTime;
            switch (state) {
                case State.SwingingSwordBeforeHit:
                    Vector3 aimDirection = (TargetUnit.GetWorldPosition() - Unit.GetWorldPosition()).normalized;
                    const float rotationSpeed = 10f;
                    transform.forward = Vector3.Lerp(transform.forward, aimDirection, rotationSpeed * Time.deltaTime);
                    break;
                case State.SwingingSwordAfterHit:
                    break;
            }

            if (stateTimer <= 0f) NextState();
        }

        public static event EventHandler OnAnySwordHit;
        public event EventHandler OnSwordActionStarted;
        public event EventHandler OnSwordActionCompleted;

        public override void TakeAction(GridPosition gridPosition, Action onActionComplete) {
            TargetUnit = LevelGrid.Instance.GetUnitAtGridPosition(gridPosition);
            state = State.SwingingSwordBeforeHit;
            const float beforeHitStateTime = 0.7f;
            stateTimer = beforeHitStateTime;
            OnSwordActionStarted?.Invoke(this, EventArgs.Empty);
            ActionStart(onActionComplete);
        }

        public override List<GridPosition> GetValidActionGridPositionList() {
            List<GridPosition> validGridPositionList = new();
            GridPosition unitGridPosition = Unit.GridPosition;
            for (int x = -MaxSwordDistance; x <= MaxSwordDistance; x++) {
                for (int z = -MaxSwordDistance; z <= MaxSwordDistance; z++) {
                    GridPosition offsetGridPosition = new(x, z);
                    GridPosition testGridPosition = unitGridPosition + offsetGridPosition;
                    if (!LevelGrid.Instance.IsValidGridPosition(testGridPosition)) continue; //Only return valid grid positions
                    if (!LevelGrid.Instance.HasAnyUnitOnGridPosition(testGridPosition)) continue; //Grid position is empty, no unit
                    Unit unitAtGridPosition = LevelGrid.Instance.GetUnitAtGridPosition(testGridPosition);
                    if (unitAtGridPosition.IsEnemy == Unit.IsEnemy) continue; //Both units are on the same 'team'
                    // TargetUnit = unitAtGridPosition;
                    validGridPositionList.Add(testGridPosition);
                }
            }

            return validGridPositionList;
        }

        protected override EnemyAIAction GetEnemyAIAction(GridPosition gridPosition) => new(gridPosition, 200);

        private void NextState() {
            switch (state) {
                case State.SwingingSwordBeforeHit:
                    state = State.SwingingSwordAfterHit;
                    const float afterHitStateTime = 0.5f;
                    stateTimer = afterHitStateTime;
                    TargetUnit.Damage(100);
                    OnAnySwordHit?.Invoke(this, EventArgs.Empty);
                    break;
                case State.SwingingSwordAfterHit:
                    OnSwordActionCompleted?.Invoke(this, EventArgs.Empty);
                    ActionComplete();
                    break;
            }
        }

        private enum State {
            SwingingSwordBeforeHit,
            SwingingSwordAfterHit,
        }
    }
}