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

public class MoveAction : BaseAction
{
    public event EventHandler OnStartMoving;
    public event EventHandler OnStopMoving;
    IEnumerator<GridPosition> itineraryIterator;
    private Vector3 targetPosition;
    private string walkingAnimation = new string("IsWalking");

    

    [SerializeField] float moveSpeed = 4f;
    [SerializeField] float rotateSpeed = 10f;

    protected override void Awake() {
        base.Awake();
        targetPosition = transform.position;
        maxDistance = (Range)4;
    }

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

        float stoppingDistance = 0.1f;
        Vector3 moveDirection = (targetPosition - transform.position).normalized;

        if (Vector3.Distance(transform.position,targetPosition) < stoppingDistance) {
            transform.position = targetPosition;
            if (itineraryIterator.MoveNext()) {
                targetPosition = LevelGrid.Instance.GetWorldPosition(itineraryIterator.Current);
            } else {               
                StopAction();
            }
        } else {            
            transform.forward = Vector3.Lerp(transform.forward
                                            ,moveDirection
                                            ,Time.deltaTime * rotateSpeed) ;
            transform.position += moveDirection * moveSpeed * Time.deltaTime;
        }
    
    }

    public override CancellationToken TakeAction(in GridPosition targetGridPosition, out CancellationToken cancellationToken) 
    {
        if (Pathfinding.Instance.TryFindPath(unit.GetGridPosition(), targetGridPosition, out (IEnumerable<GridPosition> itinerary, int distance) result))
        {
            itineraryIterator = result.itinerary.GetEnumerator();

            if (itineraryIterator.MoveNext()) {
                targetPosition = LevelGrid.Instance.GetWorldPosition(itineraryIterator.Current);
            }
            OnStartMoving?.Invoke(this, EventArgs.Empty);
            StartAction(out cancellationToken).Register(() => {
                OnStopMoving?.Invoke(this, EventArgs.Empty);
                (itineraryIterator as IDisposable)?.Dispose();
            });
        }

        return cancellationToken;
    }

    protected override bool IsValidTargetPositionSpecific(in GridPosition unitGridPosition, in GridPosition testGridPosition) {
        if (LevelGrid.Instance.HasAnyUnitOnGridPosition(testGridPosition)) {
            return false;
        }

        if (!Pathfinding.Instance.TryFindPath(unit.GetGridPosition(),testGridPosition, out (IEnumerable<GridPosition> itinerary, int distance) result)) {
            return false;
        };

        int distanceScale = 10;
        if (result.distance > maxDistance * distanceScale) {
            return false;
        }

        return true;
    }
    
    public override string GetActionName() {
        return "Move";
    }

    public override EnemyAIAction GetEnemyAIAction(GridPosition gridPosition)
    {
        return new EnemyAIAction {
            gridPosition = gridPosition,
            actionValue = unit.GetAction<ShootAction>().GetTargetCountAtPosition(gridPosition) * 10,
        };
    }
}