extends Level

signal beat_tick(beat: int)

const SPEED_TRANSITION_DISTANCE: float = 0.1
const BPM: int = 160

var _previous_beat: int = 0

@onready var progress_track: Path3D = $ProgressTrack
@onready var player_desired_progress: PathFollow3D = $ProgressTrack/PlayerDesiredProgress
@onready var music_animation: AnimationPlayer = $MusicAnimation
@onready var debug_visualizer: MeshInstance3D = $ProgressTrack/PlayerDesiredProgress/DebugVisualizer
@onready var music: AudioStreamPlayer = $Music


func _ready() -> void:
	InputManager.set_mouse_captured(true)
	beat_tick.connect(_on_beat_tick)

	GameGlobals.player.global_position = PlayerSpawnPoint.get_spawn_point_by_identifier(&"ChaseBeginning").global_position


func _process(_delta: float) -> void:
	if not music_animation.is_playing():
		return

	# Beat tick
	var _current_time: float = music_animation.current_animation_position + AudioServer.get_time_since_last_mix()
	SPrint.print_msgf("Current Music-Time: %s" % _current_time)
	_current_time -= AudioServer.get_output_latency()
	var beat := int(_current_time * BPM / 60.0)

	if _previous_beat != beat:
		_previous_beat = beat
		beat_tick.emit(beat)


func _physics_process(delta: float) -> void:
	var player_character: PlayerCharacter = GameGlobals.player

	var player_offset: float = progress_track.curve.get_closest_offset(player_character.global_position)
	var desired_speed_scale: float = remap(
		(player_desired_progress.progress - player_offset) + SPEED_TRANSITION_DISTANCE,
		0.0, SPEED_TRANSITION_DISTANCE,
		0.1, 1.05
	)
	player_character.speed_scale = move_toward(
		player_character.speed_scale,
		clampf(desired_speed_scale, 0.1, 1.05),
		delta
	)


func _on_start_chase_area_body_entered(_body: Node3D) -> void:
	music_animation.play(&"main_track")


func _on_beat_tick(beat: int) -> void:
	debug_visualizer.scale = Vector3.ONE * (1.25 if beat % 2 == 0 else 1.0)
