extends Node2D

var amount := 0
var number_color := Color.WHITE
var custom_text := ""
var subtitle := ""
var fancy := false

# --- Où le texte flotte -------------------------------------------------------
#
# Il appartient à sa **victime**, pas au monde. En rendu 3D la caméra 2D est
# éteinte: un `Node2D` laissé à sa position de monde se dessinerait à ses
# coordonnées brutes, donc à côté de l'entité qu'il commente — c'est ce qui
# faisait apparaître les dégâts d'un monstre au-dessus du héros.
#
# On garde donc le point du plan et la hauteur de la silhouette, et on les
# reprojette à chaque image. La victime peut mourir entre-temps: le texte tient
# tout seul, il ne la relit jamais.
var world_anchor := Vector2.ZERO
var plan_offset := Vector2.ZERO
var anchor_elevation := 0.0
var rise := 0.0

func setup(value: int, color: Color) -> void:
	amount = value
	number_color = color
	queue_redraw()

func setup_currency(value: int, tip: int = 0) -> void:
	amount = value
	number_color = Color("ffd166") if tip <= 0 else Color("ff9ff3")
	custom_text = "+%d$" % value
	subtitle = "TIP +%d$" % tip if tip > 0 else ""
	fancy = tip > 0
	queue_redraw()

# `victim` ne sert qu'à mesurer, une seule fois, où poser le texte. Il n'en garde
# aucune référence: la créature peut disparaître pendant que le nombre monte.
func float_above(victim: Node2D, jitter: float, lift: float) -> void:
	if victim == null or not is_instance_valid(victim):
		return
	world_anchor = victim.global_position
	plan_offset = Vector2(jitter, -lift)
	anchor_elevation = Bridge3D.entity_top_elevation(victim)
	_place()

func _ready() -> void:
	add_to_group("damage_number")
	if not custom_text.is_empty():
		add_to_group("currency_popup")
	z_index = 100
	# Sans ancrage déclaré, la position posée par l'appelant fait office de point
	# du plan: le texte garde alors le comportement d'avant.
	if world_anchor.is_zero_approx():
		world_anchor = global_position
	_place()
	# Un chiffre d'argent se lit, un chiffre de dégâts se constate: le premier
	# doit rester en l'air assez longtemps pour qu'on sache exactement combien
	# on vient de toucher. Il monte moins vite et ne s'efface qu'au bout.
	var money := is_in_group("currency_popup")
	var travel := 1.55 if money else 0.72
	var fade_delay := 0.95 if money else 0.18
	var tween := create_tween().set_parallel(true)
	tween.tween_property(self, "rise", -42.0, travel).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT)
	tween.tween_property(self, "modulate:a", 0.0, travel - fade_delay).set_delay(fade_delay)
	tween.tween_property(self, "scale", Vector2(1.25, 1.25), 0.14).set_trans(Tween.TRANS_BACK)
	tween.chain().tween_callback(queue_free)

func _process(_delta: float) -> void:
	_place()

# La montée s'ajoute à l'ancrage au lieu de se substituer à lui: sans ça, animer
# la position se battrait avec la reprojection à chaque image.
func _place() -> void:
	var screen := Bridge3D.world_to_screen(world_anchor, anchor_elevation) if Render3D.active \
		else Vector2.INF
	if screen.is_finite():
		global_position = screen + Vector2(plan_offset.x, rise)
	else:
		global_position = world_anchor + plan_offset + Vector2(0.0, rise)

func _draw() -> void:
	var text := custom_text if not custom_text.is_empty() else str(amount)
	var width := 110.0 if fancy else 60.0
	var origin := Vector2(-width * 0.5, 6)
	for offset: Vector2 in [Vector2(-2, 0), Vector2(2, 0), Vector2(0, -2), Vector2(0, 2)]:
		draw_string(ThemeDB.fallback_font, origin + offset, text, HORIZONTAL_ALIGNMENT_CENTER, width, 22 if fancy else 20, Color("261a31"))
	draw_string(ThemeDB.fallback_font, origin, text, HORIZONTAL_ALIGNMENT_CENTER, width, 22 if fancy else 20, number_color)
	if fancy:
		draw_circle(Vector2(-60, -2), 4.0, Color("ffd166"))
		draw_circle(Vector2(60, -2), 4.0, Color("ffd166"))
		draw_string(ThemeDB.fallback_font, Vector2(-55, 25), subtitle, HORIZONTAL_ALIGNMENT_CENTER, 110, 14, Color("ffd166"))
