@tool
class_name GunkAlarm extends SignalNode
## Raises the grunk alert when triggered.

const ALERT_DELTA := 1

const JITTER_SCALE_FACTOR := 0.15
const JITTER_INFLATION_FACTOR := 1.5

## Time to wait for a pulse signal before triggering.
@export var pulse_timeout := 6.0

var _busy := false

@onready var pulse_listener_timer: Timer = %PulseListenerTimer
@onready var animation_player: AnimationPlayer = $FrameSkipper/AlarmMesh/AnimationPlayer
@onready var bud: MeshInstance3D = $FrameSkipper/AlarmMesh/Armature/Skeleton3D/Bud
@onready var alarm_sfx: AudioStreamPlayer3D = %AlarmSFX


## Trigger this alarm.
##
## Will not trigger if this alarm is busy (e.g. on cooldown)
func trigger() -> void:
	if not _busy:
		_busy = true
		Game.manager.raise_alert(ALERT_DELTA)
		animation_player.play("trigger")
		alarm_sfx.play()


## Pulse this alarm, resetting the pulse countdown until triggering.
##
## Note that alarms will not begin the pulse countdown until receiving the first pulse.
## On networks without a heart, the pulse timeout will be completely ignored.
func pulse() -> void:
	pulse_listener_timer.start(pulse_timeout)


func _process(delta: float) -> void:
	if Engine.is_editor_hint():
		return

	super._process(delta)
	# TODO actual model & animation
	var shader: ShaderMaterial = bud.mesh.surface_get_material(0)
	var damage := pct_damage()
	shader.set_shader_parameter("jitter_time_scale", pow(damage * JITTER_SCALE_FACTOR, 1.2))
	shader.set_shader_parameter("vertex_inflation", pow(damage * JITTER_INFLATION_FACTOR, 3))
	# TODO pulse animation


func _on_animation_finished(anim_name: StringName) -> void:
	if anim_name == "trigger":
		_busy = false
