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

public class SwordAction : BaseAction
{
    public static event EventHandler onAnySwordHit;
    public event EventHandler onSwordActionStarted;
    public event EventHandler onSwordActionCompleted;
    private State state;
    private float stateTimer;
    private float beforeHitStateTime = 0.7f;
    private float afterHitStateTime = 0.5f;
    private Vector3 swingStartDirectionVector;
    private Vector3 swingEndDirectionVector;
    private enum State {
        Idle,
        SwingingSwordBeforeHit,
        SwingingSwordAfterHit,

    }
    private Unit targetUnit;

    public override string GetActionName()
    {
        return "Sword";
    }

    private void Start() {
        actionCost = 1;
        maxDistance = (Range)1;
    }
    private void Update() {
        if (!IsActive()) {
            return;
        }
        stateTimer -= Time.deltaTime;

        switch (state) {
            case State.SwingingSwordBeforeHit:
                float rotateSpeed = 2;
                float timeElapsed = (beforeHitStateTime - stateTimer) * rotateSpeed;
                if (timeElapsed > beforeHitStateTime) {
                    timeElapsed = beforeHitStateTime;
                }
                transform.forward = Vector3.Lerp(swingStartDirectionVector
                                         ,swingEndDirectionVector
                                         ,timeElapsed / beforeHitStateTime) ;
                break;
            case State.SwingingSwordAfterHit:
                break;
        }
        if (IsStateTimerElapsed()) {
            NextState();
        }
    }

    private bool IsStateTimerElapsed() => (stateTimer <= 0f);
    private void NextState() {
        switch (state) {
            case State.Idle:
                swingStartDirectionVector = transform.forward;        
                swingEndDirectionVector = ( targetUnit.GetWorldPosition() - transform.position).normalized;
                state = State.SwingingSwordBeforeHit;
                SetTimer(beforeHitStateTime);
                break;
            case State.SwingingSwordBeforeHit:
                state = State.SwingingSwordAfterHit;
                SetTimer(afterHitStateTime);
                SwordSlash();
                break;
            case State.SwingingSwordAfterHit:
                onAnySwordHit?.Invoke(this, EventArgs.Empty);
                targetUnit.Damage(100);                
                StopAction();
                break;
        }
    }
    private void SwordSlash() {
        onSwordActionStarted?.Invoke(this, EventArgs.Empty);
    }
    private void SetTimer(float time) {
        stateTimer = time;
    }        
    public override EnemyAIAction GetEnemyAIAction(GridPosition gridPosition)
    {
        return new EnemyAIAction {
            gridPosition = gridPosition,
            actionValue = 200,
        };
    }

    public override CancellationToken TakeAction(in GridPosition gridPosition, out CancellationToken cancellationToken)
    {
        targetUnit = LevelGrid.Instance.GetUnitAtGridPosition(gridPosition);
        NextState();
        StartAction(out cancellationToken).Register(() => {
            state = State.Idle;
            onSwordActionCompleted?.Invoke(this, EventArgs.Empty);
        });
        return cancellationToken;
    }

    protected override bool IsValidTargetPositionSpecific(in GridPosition unitGridPosition, in GridPosition testGridPosition)
    {
        return (LevelGrid.Instance.HasAnyUnitOnGridPosition(testGridPosition)
                && (LevelGrid.Instance.GetUnitAtGridPosition(testGridPosition).IsEnemy() != unit.IsEnemy())
                );
    }
}