extends Node3D

# Blobber dungeon builder. Calls BrogueGen.generate_dungeon() and assembles
# per-material MeshInstance3D children from the returned mesh surface arrays.
# Material ids mirror src/mesh/material_ids.h.

const MAT_STONE_FLOOR   := 0
const MAT_STONE_CEILING := 1
const MAT_STONE_WALL    := 2
const MAT_DOOR_FLOOR    := 3
const MAT_STAIR_UP      := 4
const MAT_STAIR_DOWN    := 5
const MAT_WATER         := 6
const MAT_LAVA          := 7
const MAT_BRIDGE        := 8
const MAT_CAVE_FLOOR    := 9
const MAT_CAVE_CEILING  := 10
const MAT_CAVE_WALL     := 11

@export var seed_value: int = 42
@export var num_levels: int = 1
@export var depth: int = 1
@export var regenerate_on_ready: bool = true

var _materials: Dictionary = {}

func _ready() -> void:
	_materials = _build_materials()
	if regenerate_on_ready:
		regenerate()

func regenerate() -> void:
	for child in get_children():
		child.queue_free()

	var gen := BrogueGen.new()
	var dungeon: Dictionary = gen.generate_dungeon(seed_value, num_levels, depth)
	gen.free()

	if dungeon.is_empty():
		push_error("generate_dungeon returned empty dictionary")
		return

	var meshes: Array = dungeon.get("meshes", [])
	for entry_v in meshes:
		var entry: Dictionary = entry_v
		var material_id: int = entry.get("material", -1)
		var arrays: Array = entry.get("arrays", [])
		if material_id < 0 or arrays.is_empty():
			continue

		var mesh := ArrayMesh.new()
		mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, arrays)
		mesh.surface_set_material(0, _materials.get(material_id, _fallback_material()))

		var mi := MeshInstance3D.new()
		mi.mesh = mesh
		mi.name = "Surface_%d" % material_id
		add_child(mi)

	var dims: Vector3i = dungeon.get("dimensions", Vector3i(79, 1, 29))
	var levels: Array = dungeon.get("levels", [])
	print("Dungeon built: seed=%d dims=%s surfaces=%d levels=%d" %
		[seed_value, dims, meshes.size(), levels.size()])

# Distinct albedo colors per material for instant visual debugging.
# Later PRs replace these with proper StandardMaterial3D + textures.
func _build_materials() -> Dictionary:
	var m := {}
	m[MAT_STONE_FLOOR]   = _flat(Color(0.45, 0.42, 0.38))
	m[MAT_STONE_CEILING] = _flat(Color(0.30, 0.28, 0.26))
	m[MAT_STONE_WALL]    = _flat(Color(0.55, 0.50, 0.45))
	m[MAT_DOOR_FLOOR]    = _flat(Color(0.62, 0.38, 0.18))
	m[MAT_STAIR_UP]      = _flat(Color(0.20, 0.75, 0.40))
	m[MAT_STAIR_DOWN]    = _flat(Color(0.85, 0.25, 0.20))
	m[MAT_WATER]         = _flat(Color(0.15, 0.40, 0.75))
	m[MAT_LAVA]          = _flat(Color(0.95, 0.40, 0.10))
	m[MAT_BRIDGE]        = _flat(Color(0.50, 0.35, 0.20))
	m[MAT_CAVE_FLOOR]    = _flat(Color(0.35, 0.32, 0.28))
	m[MAT_CAVE_CEILING]  = _flat(Color(0.22, 0.20, 0.18))
	m[MAT_CAVE_WALL]     = _flat(Color(0.42, 0.38, 0.34))
	return m

func _flat(c: Color) -> StandardMaterial3D:
	var sm := StandardMaterial3D.new()
	sm.albedo_color = c
	sm.roughness = 0.85
	sm.metallic = 0.0
	return sm

func _fallback_material() -> StandardMaterial3D:
	return _flat(Color.MAGENTA)
