extends MeshInstance3D
class_name TrainBody

signal speed_changed(new_speed: float)
signal rail_switched(old_rail: Path3D, new_rail: Path3D)

@export_group("Train")
@export var base_speed: float = 15.0
@export var max_speed: float = 50.0
@export var min_speed: float = 3.0
@export var acceleration: float = 12.0
@onready var rail_a: Path3D = $"../Rails1"
@onready var rail_b: Path3D = $"../Rails2"

var current_follower: PathFollow3D
var current_rail: Path3D
var current_speed: float = 15.0

func _ready() -> void:
	current_speed = base_speed
	switch_to_rail(rail_a)


func _process(delta: float) -> void:
	_handle_input(delta)
	current_follower.progress += current_speed * delta
	global_transform = current_follower.global_transform


func _handle_input(delta: float) -> void:
	if Input.is_action_pressed("speed_up"):
		current_speed = min(current_speed + acceleration * delta, max_speed)
		speed_changed.emit(current_speed)
	elif Input.is_action_pressed("speed_down"):
		current_speed = max(current_speed - acceleration * delta, min_speed)
		speed_changed.emit(current_speed)


func get_speed() -> float:
	return current_speed


func switch_to_rail(new_rail: Path3D) -> void:
	if new_rail == current_rail:
		return

	current_rail = new_rail
	current_follower = new_rail.get_node("TrainEngine") as PathFollow3D

	var closest_offset = find_closest_point_on_path(new_rail, global_position)
	current_follower.progress = closest_offset
	
	
func find_closest_point_on_path(path: Path3D, point: Vector3) -> float:
	var curve = path.curve
	var closest_offset = 0.0
	var min_distance = INF

	var length = curve.get_baked_length()
	var steps = 100  # Più alto = più preciso ma più lento

	for i in range(steps + 1):
		var offset = (float(i) / steps) * length
		# Trasforma il punto locale della curva in coordinate globali
		var path_point = path.global_transform * curve.sample_baked(offset)
		var dist = point.distance_to(path_point)

		if dist < min_distance:
			min_distance = dist
			closest_offset = offset

	return closest_offset
