using System.Collections.Generic;
using Godot;

public class MoveNode : ProgramNode
{
    public Vector3 startPosition;
    public Vector3I targetPosition;
    public List<Vector3> pathPoints;
    public MoveNode()
    {
        DisplayText = "Move";
    }
    public override NodeResult Execute(Robot robot, double delta)
    {
        pathPoints ??= new List<Vector3>(Pathfinding.GetPath(Pathfinding.GetClosestStartPoint(robot.Position), targetPosition));

        if (pathPoints.Count <= 0)
        {
            lastExecutionMessage = "No path available";
            return NodeResult.FAILURE;
        }

        startPosition = robot.Position;
        Vector3 target = pathPoints[0] - startPosition;
        float distance = target.Length();
        
        float movementSpeed = robot.GetMovementSpeed();

        if (distance < 0.1f * Mathf.Sqrt(movementSpeed))
        {
            robot.Position = pathPoints[0];
            Vector3I mapIndex = Pathfinding.GetClosestStartPoint(robot.Position);
            Tile tile = GameData.map[mapIndex.Y].tiles[mapIndex.X, mapIndex.Z];
            if (!tile.wasVisited)
            {
                tile.VisitTile();
            }

            pathPoints.Remove(pathPoints[0]);
            if (pathPoints.Count <= 0)
            {
                lastExecutionMessage = "";
                return NodeResult.SUCCESS;
            }

            lastExecutionMessage = "";
            return NodeResult.RUNNING;
        }

        Vector3 direction = target / distance;
        Vector3 lookDirection = new Vector3(direction.X, 0, direction.Z);
        if (lookDirection.Length() > 0.1f)
        {
            robot.LookAt(robot.GlobalPosition + lookDirection, Vector3.Up);
        }
        robot.GlobalPosition += direction * (float)delta * movementSpeed;

        return NodeResult.RUNNING;
    }

    public override void ReadParameters(NodeDisplay display)
    {
        HBoxContainer valueContainer = display.GetNode<HBoxContainer>("./EditorDisplay/HBoxContainer/");
        int posX = (int)valueContainer.GetNode<SpinBox>("./CoordinateX").Value;
        int posY = (int)valueContainer.GetNode<SpinBox>("./CoordinateY").Value;
        int posZ = (int)valueContainer.GetNode<SpinBox>("./CoordinateZ").Value;
        targetPosition = new Vector3I(posX, posY, posZ);
    }

    public override ProgramNode Duplicate()
    {
        MoveNode duplicate = new MoveNode
        {
            targetPosition = targetPosition
        };
        return duplicate;
    }

    public override void Setup(NodeDisplay display)
    {
    }

    public override string Save()
    {
        return $"Name: {DisplayText}, Position: ({targetPosition.X}|{targetPosition.Y}|{targetPosition.Z})";
    }
}
