extends Node2D

# Visual effect when a player is healed by Tome of Healing.
# Plays frames 589-598 from shade_spell_effects, green PointLight2D flicker,
# and pulses target player sprites green for a short duration.

const DURATION: float = 1.2
var _frames: Array = [589, 590, 591, 592, 593, 594, 595, 596, 597, 598]
const HEAL_PULSE_TINT: Color = Color(0.35, 1.5, 0.4, 1.0)

var target_player: Node = null
var elapsed: float = 0.0
var _original_tints: Dictionary = {}

@onready var fx_sprite: Sprite2D = $FxSprite
@onready var heal_light: PointLight2D = $HealLight

func _ready() -> void:
	pass

func setup(p_target: Node) -> void:
	target_player = p_target
	if not target_player or not is_instance_valid(target_player):
		queue_free()
		return
	$SfxHeal.play()
	global_position = target_player.global_position
	elapsed = 0.0
	if fx_sprite and _frames.size() > 0:
		fx_sprite.frame = _frames[0]
		fx_sprite.modulate = Color(0.4, 1.0, 0.5)
	if heal_light:
		heal_light.color = Color(0.3, 1.0, 0.35)
		heal_light.energy = 0.8
		heal_light.enabled = true

func _process(delta: float) -> void:
	if not target_player or not is_instance_valid(target_player):
		queue_free()
		return
	elapsed += delta
	global_position = target_player.global_position
	# Animate frames 589-598
	if fx_sprite and _frames.size() > 0:
		var idx = int((elapsed / DURATION) * float(_frames.size())) % _frames.size()
		fx_sprite.frame = _frames[idx]
	# Flicker light
	if heal_light:
		var flicker = 0.7 + 0.4 * sin(elapsed * 18.0) * cos(elapsed * 7.0)
		heal_light.energy = clamp(flicker, 0.3, 1.2)
	# Pulse green on target sprites
	_apply_heal_pulse()
	if elapsed >= DURATION:
		_clear_heal_pulse()
		queue_free()

func _sprites_for_target() -> Array:
	if not target_player:
		return []
	var names = ["Sprite2DBody", "Sprite2DBoots", "Sprite2DArmour", "Sprite2DFacialHair", "Sprite2DHair", "Sprite2DEyes", "Sprite2DEyeLashes", "Sprite2DAddons", "Sprite2DHeadgear", "Sprite2DShield", "Sprite2DShieldHolding", "Sprite2DWeapon"]
	var out: Array = []
	for n in names:
		var node = target_player.get_node_or_null(n)
		if node and node is Sprite2D:
			out.append({"sprite": node, "name": n})
	return out

func _apply_heal_pulse() -> void:
	var pulse = (sin(elapsed * 12.0) + 1.0) * 0.5  # 0..1 oscillating
	for s in _sprites_for_target():
		var sprite: Sprite2D = s.sprite
		var key: String = s.name
		if not sprite or not is_instance_valid(sprite) or not sprite.material or not (sprite.material is ShaderMaterial):
			continue
		var sm: ShaderMaterial = sprite.material as ShaderMaterial
		if not _original_tints.has(key):
			var tp = sm.get_shader_parameter("tint")
			if tp is Vector4:
				_original_tints[key] = Color(tp.x, tp.y, tp.z, tp.w)
			elif tp is Color:
				_original_tints[key] = tp
			else:
				_original_tints[key] = Color.WHITE
		var orig: Color = _original_tints[key]
		var green_tint = Color(orig.r * HEAL_PULSE_TINT.r, orig.g * HEAL_PULSE_TINT.g, orig.b * HEAL_PULSE_TINT.b, orig.a * HEAL_PULSE_TINT.a)
		var cur = orig.lerp(green_tint, pulse * 0.6)
		sm.set_shader_parameter("tint", Vector4(cur.r, cur.g, cur.b, cur.a))

func _clear_heal_pulse() -> void:
	for s in _sprites_for_target():
		var sprite: Sprite2D = s.sprite
		var key: String = s.name
		if not sprite or not is_instance_valid(sprite) or not sprite.material or not (sprite.material is ShaderMaterial):
			continue
		if _original_tints.has(key):
			var c: Color = _original_tints[key]
			(sprite.material as ShaderMaterial).set_shader_parameter("tint", Vector4(c.r, c.g, c.b, c.a))
	_original_tints.clear()
