class_name World extends Node
## Container scene for a game world instance.
##
## A world contains player(s) and the active level, manages player states,
## and transitions between active levels.

@export var initial_level: PackedScene = load("res://levels/debug_level/debug_level.tscn")

@export var manager: PlayManager

@export var spawn_group := "PlayerSpawn"

var _spawns_available: Array[Node3D] = []

@onready var level: Node3D = %Level
@onready var ui: WorldUI = %UI

static var group := "WorldGroup"


func _ready() -> void:
	load_level(initial_level)

	# Spawn players in the level
	for player: WorldPlayer in manager.players:
		_spawn_player(player)

	manager.initialize()
	if not manager.players:
		push_warning("Warning: Starting game world with no players!")


func _random_spawn() -> Node3D:
	# Get random spawn point
	if not _spawns_available:
		_spawns_available.assign(get_tree().get_nodes_in_group(spawn_group))
	@warning_ignore("unsafe_cast")
	var spawn_point := _spawns_available.pick_random() as Node3D
	assert(spawn_point, "No nodes in spawn group `%s` found!" % spawn_group)
	_spawns_available.erase(spawn_point)
	return spawn_point


func _spawn_player(player: WorldPlayer) -> void:
	var spawn_point := _random_spawn()
	var shot_setup := player.shot_setup
	shot_setup.global_transform = spawn_point.global_transform
	spawn_point.add_sibling(shot_setup)


## Instantiate and mantle the given level scene.
##
## This will free any currently-loaded level!
func load_level(level_scene: PackedScene) -> void:
	# Remove any currently-loaded level assets
	for c: Node in level.get_children():
		c.queue_free()

	# Load the level
	var instance: Node3D = level_scene.instantiate()
	level.add_child(instance)
