extends Minigame

const LABEL_SCENE: PackedScene = preload("res://sources/minigames/penguin/penguin_label.tscn")

var current_word_progression: int = 0: set = _set_current_word_progression
var max_word_progression: int = 0
var labels: Array[PenguinLabel] = []

@onready var penguin: Penguin = $GameRoot/Penguin
@onready var sentence_background: HFlowContainer = %SentenceBackground
@onready var sentence_container: HFlowContainer = %Sentence


# Find words with silent GPs
func _find_stimuli_and_distractions() -> void:
	var sentences_list: Array = Database.get_sentences_for_lesson_with_silent_gps(lesson_nb)
	
	if sentences_list.is_empty():
		return
	var current_lesson_sentences: Array[Dictionary] = []
	var previous_lesson_sentences: Array[Dictionary] = []
	
	for sentence: Dictionary in sentences_list:
		if sentence.LessonNb == lesson_nb:
			current_lesson_sentences.append(sentence)
		else:
			previous_lesson_sentences.append(sentence)
	
	# Shuffle everything
	current_lesson_sentences.shuffle()
	previous_lesson_sentences.shuffle()
	
	# If there is no previous stimuli, only adds from current lesson
	if previous_lesson_sentences.is_empty():
		while stimuli.size() < max_progression:
			stimuli.append(current_lesson_sentences.pick_random())
	else:
		if not current_lesson_sentences.is_empty():
			# If there are more stimuli in current lesson than needed
			if current_lesson_sentences.size() >= current_lesson_stimuli_number:
				for index: int in range(current_lesson_stimuli_number):
					stimuli.append(current_lesson_sentences[index])
			else:
				stimuli.append_array(current_lesson_sentences)
			
			# If there are not enough stimuli from current lesson, we want at least half the target number of stimuli
			var minimal_stimuli: int = floori(current_lesson_stimuli_number/2.0)
			if stimuli.size() < minimal_stimuli:
				while stimuli.size() < minimal_stimuli:
					stimuli.append(current_lesson_sentences.pick_random())
		
		# Gets other stimuli from previous errors or lessons
		var spaces_left: int = max_progression - stimuli.size()
		if previous_lesson_sentences.size() >= spaces_left:
			for index: int in range(spaces_left):
				stimuli.append(previous_lesson_sentences[index])
		else:
			stimuli.append_array(previous_lesson_sentences)
		
		# If there are not enough stimuli, fill the rest with current lesson
		if current_lesson_sentences:
			while stimuli.size() < max_progression:
				stimuli.append(current_lesson_sentences.pick_random())
	
	# Shuffle the stimuli
	stimuli.shuffle()
	
	# Find the GPs and distractors for each word
	for sentence: Dictionary in stimuli:
		sentence.GPs = Database.get_gps_from_sentence(sentence.ID as int)
		
	Log.trace("PenguinMinigame: Stimuli: %s" % str(stimuli))


# Launch the minigame
func _start() -> void:
	super()
	fireworks.set_colors([Color("#bca4ff"), Color("#f5a8c8"), Color("#7fc8ff")])
	if stimuli.is_empty():
		Log.error("PenguinMinigame: Cannot start game because stimuli is empty")
		_win()
		return
	_setup_word_progression()
	sentence_background.show()


# Sets up the word progression for the current progression
func _setup_word_progression() -> void:
	max_word_progression = 0
	
	for node: Node in sentence_container.get_children():
		node.queue_free()
	labels.clear()
	
	var stimulus: Dictionary = _get_current_stimulus()
	
	var first_gp: bool = true
	var last_word_id: int
	var word_container: HBoxContainer
	
	for gp: Dictionary in stimulus.GPs:
		if gp.WordID != last_word_id:
			last_word_id = gp.WordID
			word_container = HBoxContainer.new()
			sentence_container.add_child(word_container)
		
		var label: PenguinLabel = LABEL_SCENE.instantiate()
		if first_gp:
			label.capitalized = true
			first_gp = false
		label.gp = gp
		word_container.add_child(label)
		label.pressed.connect(_on_snowball_thrown.bind(label))
		labels.append(label)
		
		if gp.Type == 0:
			max_word_progression += 1
	
	setup_sentence_background()
	current_word_progression = 0


func setup_sentence_background() -> void:
	await get_tree().process_frame
	var number_of_lines: int = sentence_container.get_line_count()
	var children: Array[Node] = sentence_background.get_children()
	if children.is_empty():
		Log.error("Ants Minigame: sentence_background has no child, but it should always at least keep 1")
		return
	if number_of_lines == children.size():
		return
	while number_of_lines < sentence_background.get_children().size():
		var child: Node = sentence_background.get_child(-1) # Get last child
		child.queue_free()
		await get_tree().process_frame
	if number_of_lines == children.size():
		return
	var template: Node = children[0]
	while number_of_lines > sentence_background.get_children().size():
		var new_child: Node = template.duplicate()
		sentence_background.add_child(new_child)
		await get_tree().process_frame


func _highlight() -> void:
	for label: PenguinLabel in labels:
		if self._is_silent(label.gp) and not label.is_pressed:
			label.highlight()


func _stop_highlight() -> void:
	for label: PenguinLabel in labels:
		label.highlight(false)


# Get the current stimulus which needs to be found to increase progression
func _get_current_stimulus() -> Dictionary:
	if stimuli.size() == 0:
		return {}
	return stimuli[current_progression % stimuli.size()]


func _is_silent(gp: Dictionary) -> bool:
	return gp.Type == 0


func _set_current_word_progression(p_current_word_progression: int) -> void:
	current_word_progression = p_current_word_progression
	if current_word_progression == max_word_progression:
		current_progression += 1

#region Connections

func _on_snowball_thrown(pos: Vector2, label: PenguinLabel) -> void:
	# Disables all labels
	for p_label: PenguinLabel in labels:
		p_label.set_button_enabled(false)
	
	# Throw the snowball
	await penguin.throw(pos)
	
	var correct_answer: bool = _is_silent(label.gp)
	
	_log_new_response({"gp": label.gp, "is_silent": correct_answer}, {"gp": label.gp, "is_silent": true})
	
	if label.gp.has("WordID"):
		_update_remediation_word_score(label.gp.WordID as int, 1 if correct_answer else -1)
	else:
		Log.error("PenguinMinigame: Cannot update remediation score because label GP has no WordID")
	
	if correct_answer:
		label.right()
		await penguin.happy()
		current_word_progression += 1
	else:
		label.wrong()
		await penguin.sad()
		current_lives -= 1
	
	# Re-enables all labels
	for p_label: PenguinLabel in labels:
		p_label.set_button_enabled(true)
	
	penguin.idle()


func _on_current_progression_changed() -> void:
	if current_progression >= max_progression:
		return
	_setup_word_progression()

#endregion
