extends SceneTree

const STREAMING_WORLD_LOADER := preload("res://src/scenes/streaming/streaming_world_loader.gd")
const ADT_BUILDER := preload("res://addons/mpq_extractor/loaders/adt_builder.gd")

var _failures := 0


func _initialize() -> void:
	_verify_empty_water_root_ownership()
	_verify_runtime_cache_ownership()

	if _failures > 0:
		push_error("Render runtime cache shutdown verification failed: %d issue(s)" % _failures)
		quit(1)
		return
	print("Render runtime cache shutdown verification passed.")
	quit(0)


func _verify_empty_water_root_ownership() -> void:
	var node_count_before := int(Performance.get_monitor(Performance.OBJECT_NODE_COUNT))
	var empty_water_root: Node3D = ADT_BUILDER.build_tile_water_scene({"chunks": []}, Vector3.ZERO)
	var node_count_after := int(Performance.get_monitor(Performance.OBJECT_NODE_COUNT))
	_expect(empty_water_root == null, "empty ADT liquid payload should not produce a water root")
	_expect(node_count_after == node_count_before, "empty ADT liquid payload should release its temporary water root")


func _verify_runtime_cache_ownership() -> void:
	var loader: Node = STREAMING_WORLD_LOADER.new()
	var static_m2_prototype := Node3D.new()
	var animated_m2_prototype := Node3D.new()
	var wmo_prototype := Node3D.new()

	loader.set("_m2_scene_cache", {"static": static_m2_prototype})
	loader.set("_m2_animated_scene_cache", {"animated": animated_m2_prototype})
	loader.set("_wmo_prototype_cache", {"wmo": wmo_prototype})
	loader.set("_m2_mesh_cache", {"mesh": ArrayMesh.new()})
	loader.set("_m2_static_animation_cache", {"static": true})
	loader.set("_m2_missing_cache", {"missing": true})
	loader.set("_wmo_render_cache", {"render": Resource.new()})
	loader.set("_wmo_scene_resource_cache", {"scene": PackedScene.new()})
	loader.set("_wmo_render_missing_cache", {"missing": true})
	loader.set("_wmo_scene_cache_missing", {"missing": true})
	loader.set("_wmo_missing_cache", {"missing": true})
	loader.set("_shared_tex_cache", {"texture": ImageTexture.new()})

	loader.call("_release_runtime_caches_for_shutdown")

	_expect(not is_instance_valid(static_m2_prototype), "static M2 prototype should be freed")
	_expect(not is_instance_valid(animated_m2_prototype), "animated M2 prototype should be freed")
	_expect(not is_instance_valid(wmo_prototype), "WMO prototype should be freed")
	for cache_name in [
		"_m2_scene_cache",
		"_m2_animated_scene_cache",
		"_wmo_prototype_cache",
		"_m2_mesh_cache",
		"_m2_static_animation_cache",
		"_m2_missing_cache",
		"_wmo_render_cache",
		"_wmo_scene_resource_cache",
		"_wmo_render_missing_cache",
		"_wmo_scene_cache_missing",
		"_wmo_missing_cache",
		"_shared_tex_cache",
	]:
		var cache: Dictionary = loader.get(cache_name)
		_expect(cache.is_empty(), "%s should be empty after shutdown" % cache_name)

	loader.free()


func _expect(condition: bool, message: String) -> void:
	if condition:
		return
	_failures += 1
	push_error(message)
