# ============================================================
# Gym 09 — Minigame 1: Animation Speed Challenge
# ============================================================
# A SpineSprite plays an animation at Normal, Fast, or Hard
# speed.  The player must click the button that matches the
# *current* speed.  Correct answers advance a progress bar;
# reach the threshold to win.  Run out of time and you lose.
# The speed changes to a new random value after *every* press.
# ============================================================
extends Node2D


# ---------- Configurable multipliers ----------
@export var normal_speed: float = 1.0
@export var fast_speed: float = 2.0
@export var hard_speed: float = 3.0

# ---------- Timing & progression ----------
@export var time_limit: float = 30.0          ## total seconds before auto-loss
@export var progress_per_click: float = 20.0  ## progress added on correct answer
@export var win_threshold: float = 100.0      ## progress value that triggers a win
@export var penalty_per_miss: float = 10.0    ## progress lost on wrong press

# ---------- Animation ----------
@export var animation_name: String = "roar"   ## which animation to play on the SpineSprite


enum Speed { NORMAL, FAST, HARD }

var _current_speed: Speed = Speed.NORMAL
var _progress: float = 0.0
var _time_remaining: float = 0.0
var _game_active: bool = false
var _result_pending: bool = false
var _track_entry = null  ## SpineTrackEntry — stored reference for time-scale changes


@onready var _spine_sprite: SpineSprite = %SpineSprite
@onready var _progress_bar: ProgressBar = %ProgressBar
@onready var _current_speed_label: Label = %CurrentSpeedLabel
@onready var _timer_label: Label = %TimerLabel
@onready var _status_label: Label = %StatusLabel
@onready var _normal_button: Button = %NormalButton
@onready var _fast_button: Button = %FastButton
@onready var _hard_button: Button = %HardButton


# ============================================================
# Lifecycle
# ============================================================

func _ready() -> void:
	print("[Gym09 Minigame 1] Ready! Match the animation speed — click the correct button.")
	_start_game()


func _process(delta: float) -> void:
	if not _game_active:
		return

	_time_remaining -= delta

	if _time_remaining <= 0.0:
		_time_remaining = 0.0
		_on_time_up()

	_update_ui()


# ============================================================
# Game state
# ============================================================

func _start_game() -> void:
	_progress = 0.0
	_time_remaining = time_limit
	_game_active = true
	_result_pending = false
	_pick_random_speed()
	_update_ui()


func _pick_random_speed() -> void:
	_current_speed = randi() % 3 as Speed
	_apply_speed()


func _apply_speed() -> void:
	_current_speed_label.text = "Press: " + Speed.keys()[_current_speed].capitalize()

	if _track_entry == null:
		return

	match _current_speed:
		Speed.NORMAL:
			_track_entry.set_time_scale(normal_speed)
		Speed.FAST:
			_track_entry.set_time_scale(fast_speed)
		Speed.HARD:
			_track_entry.set_time_scale(hard_speed)


# ============================================================
# Animation
# ============================================================

func _play_animation() -> void:
	_track_entry = _spine_sprite.get_animation_state().set_animation(animation_name, false, 0)


# ============================================================
# Button handlers
# ============================================================

func _on_normal_pressed() -> void:
	_evaluate_answer(Speed.NORMAL)


func _on_fast_pressed() -> void:
	_evaluate_answer(Speed.FAST)


func _on_hard_pressed() -> void:
	_evaluate_answer(Speed.HARD)


func _evaluate_answer(chosen: Speed) -> void:
	if not _game_active or _result_pending:
		return

	# Restart animation on each press
	_play_animation()
	_apply_speed()

	if chosen == _current_speed:
		_progress += progress_per_click
		print("[Gym09 Minigame 1] Correct! Progress: %.0f / %.0f" % [_progress, win_threshold])

		if _progress >= win_threshold:
			_on_win()
			return
	else:
		_progress = maxf(0.0, _progress - penalty_per_miss)
		print("[Gym09 Minigame 1] Wrong button! Current speed is ", Speed.keys()[_current_speed])

	# Speed changes after every button press
	_pick_random_speed()
	_update_ui()


# ============================================================
# End conditions
# ============================================================

func _on_win() -> void:
	_game_active = false
	_result_pending = true
	print("[Gym09 Minigame 1] WIN!")
	_status_label.text = "YOU WIN!"
	_disable_buttons()

	Dialogic.VAR.Gym.minigame_done = true

	await get_tree().create_timer(1.5).timeout
	_return_to_main()


func _on_time_up() -> void:
	_game_active = false
	_result_pending = true
	print("[Gym09 Minigame 1] TIME'S UP — You lose!")
	_status_label.text = "TIME'S UP!"
	_disable_buttons()

	# Do NOT set minigame_done — the controller will re-show the intro
	await get_tree().create_timer(1.5).timeout
	_return_to_main()


func _return_to_main() -> void:
	var return_path := "res://docs/gyms/gym09_scene_switching/gym09_main.tscn"
	if Dialogic.VAR.Gym.minigame_return == "hub":
		return_path = "res://docs/gyms/cross-timeline-interactions/gym_controller.tscn"

	print("[Gym09 Minigame 1] Returning to: ", return_path)
	get_tree().change_scene_to_file(return_path)


# ============================================================
# UI helpers
# ============================================================

func _disable_buttons() -> void:
	_normal_button.disabled = true
	_fast_button.disabled = true
	_hard_button.disabled = true


func _update_ui() -> void:
	_progress_bar.max_value = win_threshold
	_progress_bar.value = clampf(_progress, 0.0, win_threshold)
	_timer_label.text = "Time: %.1f" % _time_remaining
