extends Node3D
## Tower Defense — Lecture 26 (Final)
##
## Main game world with enemy spawning, wave management,
## and player health tracking. Enemies follow a Path3D and
## damage the player when they reach the end.

# ============================================================
# CONSTANTS
# ============================================================

const PLAYER_START_HP := 100

# Enemy types and wave definitions
const WAVE_1 := ["slime", "slime", "slime"]
const WAVE_2 := ["slime", "slime", "goblin", "slime"]
const WAVE_3 := ["goblin", "goblin", "slime", "goblin", "slime"]
const WAVE_4 := ["goblin", "goblin", "goblin", "orc"]
const WAVE_5 := ["orc", "goblin", "goblin", "orc", "slime"]

const SPAWN_DELAY := 1.0  # Seconds between each enemy in a wave
const WAVE_DELAY := 5.0   # Seconds between waves

# ============================================================
# STATE
# ============================================================

var player_hp: int = PLAYER_START_HP
var current_wave: int = 0
var enemies_remaining_in_wave: int = 0
var is_spawning: bool = false

# Wave list
var waves: Array[Array] = [WAVE_1, WAVE_2, WAVE_3, WAVE_4, WAVE_5]

# ============================================================
# NODES
# ============================================================

@onready var hp_label: Label = $UI/HPLabel
@onready var wave_label: Label = $UI/WaveLabel
@onready var spawn_timer: Timer = $SpawnTimer
@onready var wave_timer: Timer = $WaveTimer
@onready var enemy_path: Path3D = $EnemyPath

# Enemy scene preload
var enemy_scene := preload("res://scenes/enemy.tscn")

# ============================================================
# LIFECYCLE
# ============================================================

func _ready() -> void:
	_update_ui()
	_start_next_wave()


# ============================================================
# WAVE MANAGEMENT
# ============================================================

## Starts the next wave if available
func _start_next_wave() -> void:
	if current_wave >= waves.size():
		_game_won()
		return
	
	current_wave += 1
	var wave_enemies := waves[current_wave - 1]
	enemies_remaining_in_wave = wave_enemies.size()
	
	_update_ui()
	
	# Start spawning enemies
	is_spawning = true
	_spawn_next_enemy_in_wave(wave_enemies, 0)


## Recursively spawns enemies with delay
func _spawn_next_enemy_in_wave(wave_enemies: Array, index: int) -> void:
	if index >= wave_enemies.size():
		is_spawning = false
		return
	
	_spawn_enemy(wave_enemies[index])
	
	# Schedule next enemy
	await get_tree().create_timer(SPAWN_DELAY).timeout
	_spawn_next_enemy_in_wave(wave_enemies, index + 1)


## Spawns a single enemy of the given type
func _spawn_enemy(enemy_type: String) -> void:
	var enemy := enemy_scene.instantiate()
	enemy_path.add_child(enemy)
	
	# Set enemy type
	enemy.enemy_type = enemy_type
	enemy.initialize()
	
	# Connect signals
	enemy.reached_end.connect(_on_enemy_reached_end)
	enemy.died.connect(_on_enemy_died)


# ============================================================
# ENEMY CALLBACKS
# ============================================================

## Called when enemy reaches end of path
func _on_enemy_reached_end(damage: int) -> void:
	player_hp -= damage
	player_hp = maxi(player_hp, 0)
	_update_ui()
	
	enemies_remaining_in_wave -= 1
	_check_wave_complete()
	
	if player_hp <= 0:
		_game_over()


## Called when enemy is killed by tower
func _on_enemy_died() -> void:
	enemies_remaining_in_wave -= 1
	_check_wave_complete()


## Checks if wave is complete and starts next wave
func _check_wave_complete() -> void:
	if enemies_remaining_in_wave <= 0 and not is_spawning:
		# Wait before next wave
		wave_timer.start(WAVE_DELAY)
		await wave_timer.timeout
		_start_next_wave()


# ============================================================
# UI
# ============================================================

func _update_ui() -> void:
	hp_label.text = "HP: %d" % player_hp
	wave_label.text = "Wave: %d / %d" % [current_wave, waves.size()]


# ============================================================
# GAME OVER / WIN
# ============================================================

func _game_over() -> void:
	print("Game Over!")
	get_tree().paused = true
	# TODO: Show game over screen in Lecture 28


func _game_won() -> void:
	print("Victory! All waves defeated!")
	get_tree().paused = true
	# TODO: Show victory screen in Lecture 28
