class_name WaveManager
extends Node

signal wave_changed(wave_number)
signal all_waves_defeated()
signal wave_message(msg:String)

@export var waves: Array[EnemyWave]
@export var enemy_parent:Node2D
@export var warning_prefab:PackedScene

@export var spawn_points:Array[Marker2D]

var _current_wave_index = 0
var _current_wave_enemies_left = 0
var total_spawned:int  = 0
# allows me to cancel a "session"
var _session_id = 0 

func restart(restart_waves:bool = true):
	_session_id += 1
	if restart_waves:
		_current_wave_index = 0
	_current_wave_enemies_left = 0
	total_spawned = 0
	U.free_children(enemy_parent)
	start_next_wave()

#signal _spawn_ok
#var spawn_timer:float
#func _process(delta: float) -> void:
	#if spawn_timer > 0.0:
		#spawn_timer -= delta
		#if spawn_timer == 0.0 || total_spawned == 0:
			#_spawn_ok.emit()

func start_next_wave():
	if _current_wave_index >= waves.size():
		all_waves_defeated.emit()
		return
		
	emit_signal("wave_changed", _current_wave_index + 1)
	var current_wave_data = waves[_current_wave_index]
	
	if !current_wave_data.pre_wave_message.is_empty():
		wave_message.emit(current_wave_data.pre_wave_message)

	# Use await to run the spawning logic without complex Timer nodes
	_spawn_wave(current_wave_data, _session_id)

func _spawn_wave(wave_data: EnemyWave, session_id:int):
	if session_id != _session_id:
		return
		
	print("Starting Wave ", _current_wave_index + 1)
	_current_wave_enemies_left = 0
	for group in wave_data.enemy_groups:
		if group.prefab:
			_current_wave_enemies_left += group.count

	for group in wave_data.enemy_groups:
		for i in range(group.count):
			if not group.prefab:
				continue # Skip if no enemy scene is assigned

			_spawn_enemy(group, session_id)
			if i < group.count:
				await get_tree().create_timer(group.spawn_delay).timeout
				
			if session_id != _session_id:
				return

func _spawn_enemy(group:EnemyGroup, session_id:int):
	if session_id != _session_id:
		return

	var spawn_point:Vector2 = spawn_points.pick_random().global_position
	var wp:Sprite2D = warning_prefab.instantiate()
	wp.global_position = spawn_point
	add_child(wp)
	total_spawned += 1
	
	# Wait for the specified delay before spawning the next enemy
	await get_tree().create_timer(group.warning_delay).timeout
	wp.queue_free()
	
	if session_id != _session_id:
		return

	var enemy:Enemy = group.prefab.instantiate()
	enemy.died.connect(_on_enemy_died.bind(session_id))
	enemy.global_position = spawn_point
	
	enemy_parent.add_child(enemy)

func _on_enemy_died(session_id:int):
	if session_id != _session_id: return
	_current_wave_enemies_left -= 1
	total_spawned -= 1
	if _current_wave_enemies_left <= 0:
		print("Wave ", _current_wave_index + 1, " cleared!")
		
		_current_wave_index += 1
		total_spawned = 0
		if _current_wave_index < waves.size():
			if !waves[_current_wave_index- 1].post_wave_message.is_empty():
				wave_message.emit(waves[_current_wave_index- 1].post_wave_message)
		
			var time_to_wait = waves[_current_wave_index].time_to_next_wave
			await get_tree().create_timer(time_to_wait).timeout
			start_next_wave()
		else:
			all_waves_defeated.emit()
