@tool
class_name LevelLoader
extends Marker3D

signal level_loaded
signal level_unloaded

static var initial_level_reference: PackedScene

@export_file("*.tscn", "*.scn") var scene_path: String
@export var load_threaded: bool = true
@export_tool_button("Load Level", "Slot") var editor_load: Callable = load_level
@export_tool_button("Unload Level", "Clear") var editor_unload: Callable = unload_level
@export_group("Level ID")
@export var override_level_id: bool = true
@export var level_id: StringName = &""

var level: Node
var is_loading: bool = false


func load_level() -> void:
	if is_loading:
		return

	if not Engine.is_editor_hint() and override_level_id:
		GameGlobals.set_level(level_id)

	if is_instance_valid(level):
		if _get_uid(level.scene_file_path) == _get_uid(scene_path):
			push_warning("Level already loaded")
			return

		unload_level()

	is_loading = true

	var scene: PackedScene

	if load_threaded:
		scene = await _load_level_threaded()
	else:
		scene = load(scene_path)

	assert(is_instance_valid(scene), "Scene is not valid.")

	level = scene.instantiate()
	add_child(level)

	is_loading = false
	initial_level_reference = null
	level_loaded.emit()


func unload_level() -> void:
	if is_instance_valid(level):
		level.queue_free()

	# Remove children that have no owner. Usually happens when duplicating the node (in the editor).
	for child: Node in get_children():
		if child.owner == null:
			child.queue_free()

	initial_level_reference = null
	level_unloaded.emit()


func _load_level_threaded() -> PackedScene:
	var interactive_loader := InteractiveLoader.new()
	interactive_loader.auto_free = true
	add_child(interactive_loader)

	var resource: Resource = await interactive_loader.load_threaded(scene_path)
	#interactive_loader.queue_free()
	return resource


func _get_uid(path: String) -> int:
	var uid: int = ResourceUID.text_to_id(ResourceUID.path_to_uid(path))
	#print("UID: ", uid, " Path: ", path)
	return uid
