extends Node

@onready var random_daily_voice: String = ""
@onready var fallback_remove_timer: Timer = $FallbackRemoveTimer

signal request_skip
@warning_ignore("unused_signal")
signal finished_speaking


func _ready():
	fallback_remove_timer.one_shot = true
	fallback_remove_timer.timeout.connect(_on_fallback_timeout)


## INFO Fallback to kill the chatter if it gets stuck. (It shouldn’t, but some idiot is going to find a way to break it. me. It’s probably going to be me. -Logan_Core)
func start_fallback(seconds: float = 45.0):
	if seconds > 0.0:
		fallback_remove_timer.start(seconds)


func stop_fallback():
	if fallback_remove_timer.time_left > 0.0:
		fallback_remove_timer.stop()


func _on_fallback_timeout():
	request_skip.emit()


## All chat voices get randomized once a day at 8am.
## TODO Setup a way to allow chatters to pick a voice? or add command to randomize their current? Figure something out
func init_random_daily_voice(chatter_name: String) -> String:
	var rng := RandomNumberGenerator.new()
	var now := Time.get_datetime_dict_from_system()

	if now.hour < 8:
		var unix_time := int(Time.get_unix_time_from_system() - 86400)
		now = Time.get_datetime_dict_from_unix_time(unix_time)

	var date_key := "%04d-%02d-%02d" % [now.year, now.month, now.day]
	var seed_string := "%s_%s" % [chatter_name, date_key]
	rng.seed = hash(seed_string)

	# WARNING The voices available are going to OS dependent. The English TTS voices built into Linux are going to be different than on Windows/etc.
	# Right now, this method will return ALL TTS voices available in english and choose randomly. Extending out this to pick from just a few 'GOOD' sounding voices may be needed
	var voices := DisplayServer.tts_get_voices_for_language("en")
	if voices.is_empty():
		random_daily_voice = ""
		return ""

	random_daily_voice = voices[rng.randi_range(0, voices.size() - 1)]
	return random_daily_voice


## The TTS voice doesn't need to comprehend symbols and stuff. Just use basic characters to prevent possible issues with TTS
func filter_alphanumeric(text: String) -> String:
	var result := ""
	for c in text:
		var code := c.unicode_at(0)
		if (code >= 48 and code <= 57) or \
		   (code >= 65 and code <= 90) or \
		   (code >= 97 and code <= 122) or \
		   code == 32:
			result += c

	return result if not result.strip_edges().is_empty() else "a"
