extends Node3D

@export var batch_duration: float = 16.0
@export var lateral_variance: float = 1.5

var _active_walkers: Array[Node] = []
var _batch_generation: int = 0

@onready var survivor = preload("res://scenes/survivor.tscn")
@export var survivor_spawn: Node3D

func _enter_tree() -> void:
	EventBus.floor_started.connect(_on_floor_started, CONNECT_DEFERRED)
	EventBus.doors_closed.connect(_on_doors_closed)
	EventBus.doors_fully_closed.connect(_clear_active_walkers)

func _on_floor_started(count: int) -> void:
	_batch_generation += 1
	_clear_active_walkers()
	if count <= 0:
		return
	_run_batch(count, _batch_generation)

func _on_doors_closed(_fast: bool) -> void:
	_batch_generation += 1

func _clear_active_walkers() -> void:
	for w in _active_walkers:
		if is_instance_valid(w):
			w.queue_free()
	_active_walkers.clear()

func _run_batch(count: int, generation: int) -> void:
	var gap: float = batch_duration / float(count)
	for i in range(count):
		if generation != _batch_generation:
			return
		_spawn_one()
		var jitter: float = randf_range(-gap * 0.25, gap * 0.25)
		await get_tree().create_timer(max(0.05, gap + jitter), false).timeout

func _spawn_one() -> void:
	var s = survivor.instantiate()
	var offset := Vector3(randf_range(-lateral_variance, lateral_variance), 0, 0)
	add_child.call_deferred(s)
	s.position = survivor_spawn.global_position + offset
	_active_walkers.append(s)
