class_name DialogueBox
extends Control

@onready var dialogue_box_container: MarginContainer = $DialogueBoxContainer
@onready var rich_text_label: RichTextLabel = $DialogueBoxContainer/Panel/MarginContainer/HBoxContainer/RichTextLabel
@onready var end: Label = $DialogueBoxContainer/Panel/MarginContainer/HBoxContainer/End

@export_color_no_alpha var font_color = Color(0.5, 1, 1)
@export var dialogues : Array[DialogueAction]
@export var duration_per_char = 0.1
@export var dialogue_animation_player : AnimationPlayer

@onready var animation_player: AnimationPlayer = $AnimationPlayer

enum State {HIDDEN, READY, READING, FINISHED}
var current_state = State.HIDDEN

var tween : Tween
signal dialogue_finished

# for sfx
var sfx_timer = 0
@export var text_cooldown = 0.07

func _ready() -> void:
	hide_dialogue_box()

func start():
	animation_player.play("fade_in")
	await animation_player.animation_finished
	current_state = State.READY

func _process(_delta: float) -> void:
	match current_state:
		State.READY:
			handle_dialogue()
		State.READING:
			text_sfx(_delta)
			if Input.is_action_just_pressed("ui_accept"):
				if tween.is_running(): tween.stop()
				rich_text_label.visible_characters = -1
				end.text = "> "
				current_state = State.FINISHED
		State.FINISHED:
			if Input.is_action_just_pressed("ui_accept"):
				handle_dialogue()

func text_sfx(_delta):
	sfx_timer -= _delta
	if sfx_timer <= 0.0:
		AudioManager.create_audio(SoundEffect.SOUND_EFFECT_TYPE.TEXT)  # good enough
		sfx_timer = text_cooldown

func hide_dialogue_box():
	rich_text_label.text = ""
	end.text = ""

func _show_text(text : String):
	end.text = ""
	current_state = State.READING
	rich_text_label.text = "[color=" + font_color.to_html(false) + "]" + tr(text) + "[/color]"
	rich_text_label.visible_characters = 0
	if tween: tween.kill()
	tween = get_tree().create_tween()
	tween.tween_property(rich_text_label, "visible_characters", tr(text).length(), duration_per_char * tr(text).length())
	tween.play()
	await tween.finished
	end.text = "> "
	current_state = State.FINISHED

func handle_dialogue():
	if dialogues.is_empty():
		if dialogue_animation_player and dialogue_animation_player.is_playing() and dialogue_animation_player.get_animation(dialogue_animation_player.current_animation).loop_mode == Animation.LOOP_NONE:
			await dialogue_animation_player.animation_finished
		current_state = State.HIDDEN
		animation_player.play("fade_out")
		await animation_player.animation_finished
		rich_text_label.text = ""
		dialogue_finished.emit()
		return
	var dialogue_action = dialogues.pop_front()
	match dialogue_action.type:
		Utils.DIALOGUE_ACTIONS.TEXT:
			dialogue_action = dialogue_action as DialogueText
			_show_text(dialogue_action.content)
		Utils.DIALOGUE_ACTIONS.ANIMATION:
			if dialogue_animation_player:
				current_state = State.READING
				dialogue_action = dialogue_action as DialogueAnimation
				dialogue_animation_player.play(dialogue_action.animation_name)
				if dialogue_animation_player.get_animation(dialogue_animation_player.current_animation).loop_mode == Animation.LOOP_NONE:
					await dialogue_animation_player.animation_finished
				current_state = State.FINISHED
			handle_dialogue()
