class_name StorageNode
extends Node3D

static var _all: Array = []

@export var storage_id: StringName = SimulationIds.STORAGE_VILLAGE_PANTRY
@export var display_name := "Village Pantry"
@export var accepted_items: Array[StringName] = []
@export var debug_label_enabled := true

@onready var interaction_point: Marker3D = $InteractionPoint

var state: StorageStateRecord
var _last_label_text := ""


func _ready() -> void:
	if accepted_items.is_empty():
		accepted_items = [SimulationIds.RESOURCE_FOOD]
	if storage_id.is_empty():
		push_error("StorageNode at %s has empty storage_id" % get_path())
		_update_presentation()
		return
	var existing: StorageNode = get_by_id(storage_id) as StorageNode
	if existing != null:
		push_error(
			(
				"Duplicate StorageNode storage_id '%s' at %s; first registered at %s"
				% [storage_id, get_path(), existing.get_path()]
			)
		)
		_update_presentation()
		return
	_all.append(self)
	add_to_group("storage_nodes")
	_try_register_with_simulation()
	_update_presentation()


func _process(_delta: float) -> void:
	if debug_label_enabled:
		_update_presentation()


func _exit_tree() -> void:
	_all.erase(self)
	state = null


func bind_state(storage_state: StorageStateRecord) -> bool:
	if storage_state == null or storage_state.get_storage_id() != storage_id:
		return false
	state = storage_state
	_update_presentation()
	return true


func get_interaction_position() -> Vector3:
	return interaction_point.global_position if interaction_point != null else global_position


func accepts_item(item_id: StringName) -> bool:
	return accepted_items.is_empty() or item_id in accepted_items


func _try_register_with_simulation() -> void:
	var managers := get_tree().get_nodes_in_group("simulation_manager")
	if managers.size() != 1:
		return
	var manager := managers[0]
	if manager.has_method("register_storage_node"):
		manager.register_storage_node(self)


func _update_presentation() -> void:
	if not has_node("DebugLabel"):
		return
	var label := $DebugLabel as Label3D
	label.visible = debug_label_enabled
	if not debug_label_enabled:
		return
	var text := "%s\n%s" % [display_name, storage_id]
	if state == null:
		text += "\nUNBOUND"
	else:
		for item_id in accepted_items:
			text += "\n%s: %.1f" % [item_id, state.get_amount(item_id)]
	if text == _last_label_text:
		return
	_last_label_text = text
	label.text = text


static func get_by_id(search_id: StringName):
	for node in _all:
		if node.storage_id == search_id:
			return node
	return null


static func get_all() -> Array:
	return _all.duplicate()
