class_name Components
extends Node
## Provides a set of methods to easily access component nodes externally.
##
## The owner of this node should have a variable named [code]components[/code]
## containing a reference to it. [br]
## This API does require component scripts to have global names (via [code]class_name[/code]).

var _owned_cache := {}


func _ready() -> void:
	child_order_changed.connect(_clear_cache)


## Returns the first component child node of the specified class.
func get_component(name_of_class: StringName) -> Node:
	if name_of_class in _owned_cache:
		return _owned_cache[name_of_class]
	
	var component := find_child(name_of_class + "*", true, false)
	if component == null:
		return null
	
	_owned_cache[name_of_class] = component
	return component


## Returns all component child nodes of the specified class.
func get_components(name_of_class: StringName) -> Array[Node]:
	return find_children(name_of_class + "*", "", true, false)


## Returns the value of a node's [code]components[/code] variable.
## Mainly exists to avoid leaving strings everywhere.
static func get_from(node: Node) -> Components:
	return node.get("components")


func _clear_cache() -> void:
	_owned_cache.clear()
