extends CanvasLayer

enum TextboxDirection {
	LEFT,
	RIGHT
}

# CPS = Characters per second
@export var cps = 3.0

@onready var animation_player = $AnimationPlayer
@onready var _textboxes = [
	$LeftTextbox/ChatboxContainer/Chatbox/PlacementContainer/MarginContainer/Text,
	$RightTextbox/ChatboxContainer/Chatbox/PlacementContainer/MarginContainer/Text
]
@onready var _portraits = [
	$LeftTextbox/ChatboxContainer/Portrait,
	$RightTextbox/ChatboxContainer/Portrait
]
@onready var _indicators = [
	$LeftTextbox/ChatboxContainer/Chatbox/PlacementContainer/NextIndicator,
	$RightTextbox/ChatboxContainer/Chatbox/PlacementContainer/NextIndicator
]

const CAST_PORTRAITS = [
	"hiro",
	"reed",
	"nem",
	"sam",
	"sevi"
]

const CAST_NAMES = [
	"HIRO",
	"REED",
	"NEM",
	"SAM",
	"SEVI"
]

signal dialogue_started
signal dialogue_opened
signal display_completed
signal dialogue_continued
signal dialogue_completed

var _direction = TextboxDirection.LEFT
var _directions = ["left", "right"]
var _dialogue: Array[String] = []
var _next = 0
var _text = ""
var _display_text = ""
var _displaying = false
var frames = 0.0

func _ready():
	for textbox in _textboxes:
		textbox.size = Vector2(720, 480)

func _process(delta):
	if _displaying:
		if _display_text == _text:
			_displaying = false
			display_completed.emit()
		else:
			frames += delta
			if frames >= 1/cps:
				frames = 0.0
				_display_text = _display_text + _text.substr(_display_text.length(), 1)
	_textboxes[_direction].text = _display_text
	for i in _indicators.size():
		var indicator = _indicators[i]
		indicator.visible = i == _direction && !_displaying && !animation_player.is_playing()

func _input(event):
	if event.is_action_pressed("ui_accept") and _dialogue.size() > 0:
		if _displaying:
			_display_text = _text
			_displaying = false
			get_viewport().set_input_as_handled()
		elif _display_text == _text:
			_dialogue_continue()
			get_viewport().set_input_as_handled()
			dialogue_continued.emit()

func _dialogue_start(who: Util.CastCharacter, custom_name: String, portrait_set: String, portrait_emotion: String, dialogue: Array[String], direction: TextboxDirection):
	var name = custom_name.to_upper() if custom_name != "" else CAST_NAMES[who]
	_next = 0
	_direction = direction
	_dialogue = dialogue
	_text = "{name}: {text}".format({"name": name, "text": _dialogue[_next]})
	_display_text = ""
	var portrait_texture = load("res://Portraits/{0}_{1}_{2}.png".format([CAST_PORTRAITS[who], portrait_set, portrait_emotion]))
	for portrait in _portraits:
		portrait.texture = portrait_texture
	animation_player.play("show_" + _directions[_direction])
	dialogue_started.emit()
	
func _dialogue_continue():
	_next += 1
	if _next >= _dialogue.size():
		_end_dialogue()
	else:
		_text = _dialogue[_next]
		_display_text = ""
		_displaying = true
	
func _end_dialogue():
	_text = ""
	_display_text = ""
	_displaying = false # just in case
	_dialogue = []
	animation_player.play("hide_" + _directions[_direction])

func _on_animation_finished(anim_name: StringName):
	if anim_name.contains("show"):
		_displaying = true
		dialogue_opened.emit()
	elif anim_name.contains("hide"):
		dialogue_completed.emit()

func _on_cutscene_command_issued(command: CutsceneCommand, _manager: CutsceneManager):
	if command is ShowDialogueCommand:
		_dialogue_start(command.character, command.custom_name, command.portrait_set, command.portrait_emotion, command.messages, command.textbox_direction)
