extends Node3D

signal matador_killed

const MATADOR := preload("res://Matador.tscn")
const RESPAWN_COOLDOWN := 8.0

var _respawn_cooldown: float = 0.0
var _wave_count: int = 1
var _alive: int = 0


func _ready() -> void:
	add_to_group(&"matador_spawn")
	_wave_count = maxi(1, int(DP.f("mat_spawn_count")))
	_spawn.call_deferred()


func _process(delta: float) -> void:
	_respawn_cooldown = maxf(0.0, _respawn_cooldown - delta)


func _unhandled_input(event: InputEvent) -> void:
	if event is InputEventKey and event.pressed and not event.echo:
		if event.physical_keycode == KEY_R and _respawn_cooldown <= 0.0:
			_respawn_cooldown = RESPAWN_COOLDOWN
			reset_spawn()


func _spawn() -> void:
	var positions := _spread_positions(_wave_count)
	for pos: Vector3 in positions:
		_spawn_at(pos)


func _spread_positions(count: int) -> Array[Vector3]:
	var positions: Array[Vector3] = []
	var arena_r := DP.f("mat_wander_radius") * 0.72
	var min_r   := 5.0
	for i: int in count:
		var sector  := TAU / count
		var angle   := sector * i + randf_range(-sector * 0.35, sector * 0.35)
		var radius  := randf_range(min_r, arena_r)
		positions.append(Vector3(cos(angle) * radius, 1.0, sin(angle) * radius))
	return positions


func _spawn_at(pos: Vector3) -> void:
	var m: Node3D = MATADOR.instantiate()
	m.position = pos
	get_parent().add_child(m)
	m.killed.connect(_on_matador_killed)
	_alive += 1


func _on_matador_killed() -> void:
	matador_killed.emit()
	_alive -= 1
	if _alive <= 0:
		_wave_count *= 2
		_spawn.call_deferred()


func reset_spawn() -> void:
	for m: Node in get_tree().get_nodes_in_group(&"matador"):
		m.queue_free()
	await get_tree().process_frame
	_wave_count = maxi(1, int(DP.f("mat_spawn_count")))
	_alive = 0
	_spawn()
