class_name TypewriterLabel extends RichTextLabel
## RichTextLabel with a managed typewriter effect.
## Allows for signal-based monitoring of a typewriter effect's status.
## In most cases you'll want to use this rather than instantiating TypewriterEffect yourself.
## Use `display_text` to set the text for this label.

## Emitted on the first frame that all characters in the typewriter effect are visible.
signal typing_finished

## Emit this to force the typewriter effect to finish on the next update.
## Useful for advancing skippable dialogue boxes.
signal force_visible

## Scale curve for animated typewriter character transition.
@export var scale_curve: Curve

## Translation curve for animated typewriter character transition.
## The Z curve will not be used.
@export var translation_curve: CurveXYZTexture

var _finished: bool = true
var _typing: bool = false

@onready var _current_text: String = text


func _ready() -> void:
	bbcode_enabled = true
	var effect := TypewriterEffect.new(force_visible)
	effect.scale_curve = scale_curve
	effect.translation_curve = translation_curve
	effect.typing.connect(_on_typing)
	effect.glyph_size_factor = get_theme_font_size("normal_font_size")
	install_effect(effect)
	if text:
		_finished = false

	visibility_changed.connect(restart)


## Is the typewriter effect finished?
func is_finished() -> bool:
	return _finished


## Reset the manager's progress monitor.
## This is called automatically when setting the label text with `set_text`
func reset() -> void:
	_finished = false


## Restart the existing typing effect.
func restart() -> void:
	display_text(_current_text)


## The `finished` signal will be emitted when the text is done displaying.
func display_text(new_text: String) -> void:
	reset()
	clear()
	append_text(new_text)
	_current_text = new_text


func _process(_delta: float) -> void:
	if not _finished:
		if not _typing:
			_finished = true
			typing_finished.emit()
		_typing = false


func _on_typing() -> void:
	_typing = true
