using Godot;

namespace Cirno.Scripts.Components.Actors;

public partial class ActorTankMovement : MovementHandler
{
    public override Vector2 FacingDirection
    {
        get => _parent.FacingDirection;
        set => _parent.FacingDirection = value;
    }

    public override Vector2 MovementDirection
    {
        get => _parent.MovementDirection;
        set => _parent.MovementDirection = value;
    }
    
    [Export] public float TurnSpeed = 4.0f; // Speed of turning
    [Export] public float Acceleration = 30f;
    [Export] public float Deceleration = 50f;
    
    private float _currentTurnProgress = 0;
    private Vector2 _targetFacingDirection = Vector2.Up;

    private float _currentSpeed = 0;

    private AnimatedSprite2D _animatedSprite;
    
    public override void Init(Actor parent) 
    {
        base.Init(parent);
       
        MovementDirection = Vector2.Zero;
        FacingDirection = Vector2.Down;
    }

    public override void Update(double delta)
    {
        
    }

    public override void PhysicsUpdate(double delta)
    {
        var inputDirection = AggregateInputProviders();
        
        // Handle Turning
        HandleTurning(_parent, inputDirection, delta);

        // Handle Movement (forward/backward)
        HandleMovement(_parent, inputDirection, delta);

        // Set Animation
        //UpdateAnimation(actor);
    }
    
    private void HandleTurning(Actor actor, Vector2 input, double delta)
    {
        // Only rotate if there is input and not currently turning
        if (input.Length() > 0.1f && _currentTurnProgress <= 0)
        {
            // Snap to the closest 8-direction vector
            _targetFacingDirection = GetSnappedDirection(input);
            _currentTurnProgress = 1.0f; // Start turn animation
        }

        // Simulate turning delay
        if (_currentTurnProgress > 0)
        {
            _currentTurnProgress -= (float)(TurnSpeed * delta);
            if (_currentTurnProgress <= 0)
            {
                actor.FacingDirection = _targetFacingDirection;
            }
        }
    }
    
    private Vector2 GetSnappedDirection(Vector2 input)
    {
        // Get angle and snap to 45-degree increments
        float angle = input.Angle();
        float snappedAngle = Mathf.Round(angle / (Mathf.Pi / 4)) * (Mathf.Pi / 4); // 45° increments

        return Vector2.Right.Rotated(snappedAngle).Normalized();
    }


    private void HandleMovement(Actor actor, Vector2 input, double delta)
    {
        // If turning, no movement
        if (_currentTurnProgress > 0)
        {
            actor.Velocity = Vector2.Zero;
            return;
        }

        // Move forward/backward based on facing direction
        if (input.Y < 0) // Forward
        {
            _currentSpeed = Mathf.MoveToward(_currentSpeed, actor.MovementSpeed, Acceleration * (float)delta);
        }
        else if (input.Y > 0) // Backward
        {
            _currentSpeed = Mathf.MoveToward(_currentSpeed, -actor.MovementSpeed / 2, Acceleration * (float)delta);
        }
        else
        {
            _currentSpeed = Mathf.MoveToward(_currentSpeed, 0, Deceleration * (float)delta);
        }

        // Set velocity
        actor.Velocity = actor.FacingDirection * _currentSpeed;

        actor.MoveAndSlide();
    }

}