@tool
class_name GunkRelay extends SignalNode
## Gunk node that rebroadcasts triggers to the network after a delay.

## Emitted when `trigger` is called, after a short delay.
signal triggered

## Emitted when `pulse` is called, after a short delay.
signal pulsed

@export var quick_connect_to: SignalNode:
	set = _editor_connect

var _busy := false

@onready var animation_player: AnimationPlayer = %AnimationPlayer
@onready var trigger_delay: Timer = %TriggerDelay
@onready var pulse_delay: Timer = %PulseDelay


## Trigger this relay.
##
## This will emit the `triggered` signal after a delay.
func trigger() -> void:
	if not _busy:
		_busy = true
		animation_player.play("trigger")
		trigger_delay.start()


## Send a pulse through this relay.
##
## This will emit the `pulse` signal after a delay.
func pulse() -> void:
	if not _busy:
		_busy = true
		animation_player.play("pulse")
		pulse_delay.start()


func _on_trigger_delay_timeout() -> void:
	triggered.emit()
	_busy = false


func _on_pulse_delay_timeout() -> void:
	pulsed.emit()
	_busy = false


## Find a path to a target node through a GunkRelay network.
static func find_path(
	current: GunkRelay, target: GunkNode, visited: Array[GunkNode] = []
) -> Array[GunkNode]:
	# Depth-first search
	for connection: Callable in current.triggered.get_connections():
		var neighbor := connection.get_object() as GunkNode
		if neighbor and not neighbor in visited:
			if neighbor == target:
				return [current, neighbor]
			var relay := neighbor as GunkRelay
			if relay:
				var path := find_path(relay, target, visited + [current])
				if path:
					return [current] + path
	return []


func _editor_connect(node: SignalNode) -> void:
	self.triggered.connect(node.trigger, CONNECT_PERSIST)
	self.pulsed.connect(node.trigger, CONNECT_PERSIST)
	self.notify_property_list_changed()
