extends Node3D

## NEO-24 UX: the targeting registry anchors (`prototype_target_alpha`,
## `prototype_target_beta`) are invisible in the world, so "Tab says ok but I feel
## far away" is impossible to reason about without debug markers. This node spawns
## one small mast + a flat radius ring per id in
## `PrototypeTargetConstants.ANCHORS`, so the player can see exactly where each
## anchor sits and how big its lock radius is.
##
## Display-only; no game logic hangs off these nodes. If the server registry moves,
## update `prototype_target_constants.gd` — markers respawn on next scene load.

const PrototypeTargetConstants := preload("res://scripts/prototype_target_constants.gd")

## Visual tuning — keep markers unmistakable but not dominant.
const _MAST_HEIGHT: float = 2.5
const _MAST_RADIUS: float = 0.18
const _RING_RADIUS_SEGMENTS: int = 72
const _RING_Y: float = 0.05
const _RING_THICKNESS: float = 0.06


func _ready() -> void:
	for id_variant: Variant in PrototypeTargetConstants.ANCHORS.keys():
		if not id_variant is String:
			continue
		_spawn_marker(id_variant as String)


func _spawn_marker(target_id: String) -> void:
	var anchor: Vector3 = PrototypeTargetConstants.anchor_position(target_id)
	var radius: float = PrototypeTargetConstants.anchor_radius(target_id)
	var tint: Color = PrototypeTargetConstants.anchor_color(target_id)
	if radius <= 0.0:
		return

	var group := Node3D.new()
	group.name = "Marker_%s" % target_id
	group.position = anchor
	add_child(group)

	var mast := MeshInstance3D.new()
	mast.name = "Mast"
	var mast_mesh := CylinderMesh.new()
	mast_mesh.top_radius = _MAST_RADIUS
	mast_mesh.bottom_radius = _MAST_RADIUS
	mast_mesh.height = _MAST_HEIGHT
	mast.mesh = mast_mesh
	# CylinderMesh is Y-centered at its origin; raise so the base sits on the anchor Y.
	mast.position = Vector3(0.0, _MAST_HEIGHT * 0.5, 0.0)
	mast.material_override = _make_unshaded_material(tint, 1.0)
	group.add_child(mast)

	var ring: MeshInstance3D = _make_radius_ring(radius, tint)
	ring.name = "RadiusRing"
	ring.position = Vector3(0.0, _RING_Y - anchor.y, 0.0)
	group.add_child(ring)


func _make_unshaded_material(tint: Color, alpha: float) -> StandardMaterial3D:
	var m := StandardMaterial3D.new()
	m.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
	var c := tint
	c.a = alpha
	m.albedo_color = c
	if alpha < 0.999:
		m.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
	return m


## Builds a thin flat ring (annulus) by triangulating the band between `radius - t/2`
## and `radius + t/2`. `ImmediateMesh` with `SurfaceTool` would also work, but an
## `ArrayMesh` keeps this a static resource with no per-frame cost.
func _make_radius_ring(radius: float, tint: Color) -> MeshInstance3D:
	var mi := MeshInstance3D.new()
	var arr_mesh := ArrayMesh.new()
	var verts := PackedVector3Array()
	var normals := PackedVector3Array()
	var indices := PackedInt32Array()

	var inner: float = max(0.01, radius - _RING_THICKNESS * 0.5)
	var outer: float = radius + _RING_THICKNESS * 0.5
	var up := Vector3.UP
	for i in range(_RING_RADIUS_SEGMENTS):
		var a: float = TAU * float(i) / float(_RING_RADIUS_SEGMENTS)
		var c: float = cos(a)
		var s: float = sin(a)
		verts.append(Vector3(inner * c, 0.0, inner * s))
		verts.append(Vector3(outer * c, 0.0, outer * s))
		normals.append(up)
		normals.append(up)

	for i in range(_RING_RADIUS_SEGMENTS):
		var i_next: int = (i + 1) % _RING_RADIUS_SEGMENTS
		var a0: int = i * 2
		var a1: int = i * 2 + 1
		var b0: int = i_next * 2
		var b1: int = i_next * 2 + 1
		indices.append_array([a0, a1, b1, a0, b1, b0])

	var surface: Array = []
	surface.resize(Mesh.ARRAY_MAX)
	surface[Mesh.ARRAY_VERTEX] = verts
	surface[Mesh.ARRAY_NORMAL] = normals
	surface[Mesh.ARRAY_INDEX] = indices
	arr_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, surface)
	mi.mesh = arr_mesh
	mi.material_override = _make_unshaded_material(tint, 0.45)
	return mi
