using Godot;

namespace Cirno.Scripts.Components.FSM.Enemy;

public partial class NavigationMovementModule : Node2D
{
    
    private Vector2? _lastTargetPosition;
    private CharacterBody2D _characterBody;
    private NavigationAgent2D _navigationAgent;
    
    [Export]
    public EnemyStorageModule StorageModule { get; private set; }

    public void Init(CharacterBody2D characterBody)
    {
        _characterBody = characterBody;

        if (_navigationAgent is not null) return;
        _navigationAgent = this.GetNode<NavigationAgent2D>("NavigationAgent2D");
    }
    
    public void SetTarget(Vector2? target)
    {
        _lastTargetPosition = target;        
    }
    
    public void Move(float movementSpeed)
    {
        if (!_lastTargetPosition.HasValue)
        {
            return;
        }
        
        _navigationAgent.SetTargetPosition(_lastTargetPosition.Value);
        
        var currentAgentPosition = _characterBody.GlobalPosition;

        if (_navigationAgent.IsNavigationFinished())
        {
            return;
        }
        
        var nextPathPosition = _navigationAgent.GetNextPathPosition();

        var newVelocity = currentAgentPosition.DirectionTo(nextPathPosition) * movementSpeed;

        newVelocity += StorageModule.KnockbackVelocity;
        
        if (_navigationAgent.AvoidanceEnabled)
        {
            _navigationAgent.SetVelocity(newVelocity);
        }
        else
        {
            _on_navigation_agent_2d_velocity_computed(newVelocity);
        }

        _characterBody.MoveAndSlide();
    }
    
    public void _on_navigation_agent_2d_velocity_computed(Vector2 safeVelocity)
    {
        if (_characterBody is null) return;
        _characterBody.Velocity = safeVelocity;
        if (_characterBody.Velocity.Length() > 0)
        {
            StorageModule.FacingDirection = _characterBody.Velocity.Normalized();
        }
    }

    public bool IsNavigable(Vector2 newPos)
    {
        _navigationAgent.SetTargetPosition(newPos);
        return _navigationAgent.IsTargetReachable();
    }

    public bool IsNavigationFinished()
    {
        return _navigationAgent.IsNavigationFinished();
    }
}