class_name DiveResult
extends CanvasLayer

# Le bilan d'une plongée.
#
# La plongée se terminait sur un toast d'une ligne et un fondu d'une seconde: le
# joueur ne voyait jamais ce qu'il ramenait, ni ce qu'il venait de perdre. La
# fenêtre nomme la raison, liste la récolte, et attend un geste pour rentrer.
#
# Elle ne décide de rien: `dungeon.gd` lui passe ce qui a été ramassé et ce qui
# survit réellement. Les deux diffèrent quand le héros est mis hors service et
# que l'assurance ne couvre qu'une part.

signal return_requested

const KNOCKED_TINT := Color(0.45, 0.05, 0.07, 0.55)
const CALM_TINT := Color(0.05, 0.04, 0.09, 0.82)
const LOST_COLOR := Color(0.55, 0.5, 0.58)
const KEPT_COLOR := Color(0.78, 0.93, 0.8)

var _root: Control
var _backdrop: ColorRect
var _title: Label
var _subtitle: Label
var _list: VBoxContainer
var _return_button: Button
# Ce que le test lit pour savoir ce que le joueur a réellement vu.
var listed_ingredients: Array[String] = []
var knocked_out := false

func _ready() -> void:
	layer = 25
	_build()
	hide()

func _build() -> void:
	_root = Control.new()
	_root.set_anchors_preset(Control.PRESET_FULL_RECT)
	_root.mouse_filter = Control.MOUSE_FILTER_STOP
	add_child(_root)

	# Le fondu couvre tout l'écran SAUF la fenêtre: il est dessous, et c'est le
	# panneau posé par-dessus qui reste lisible.
	_backdrop = ColorRect.new()
	_backdrop.set_anchors_preset(Control.PRESET_FULL_RECT)
	_backdrop.color = CALM_TINT
	_backdrop.mouse_filter = Control.MOUSE_FILTER_IGNORE
	_root.add_child(_backdrop)

	var panel := PanelContainer.new()
	panel.name = "Panel"
	panel.set_anchors_preset(Control.PRESET_CENTER)
	panel.grow_horizontal = Control.GROW_DIRECTION_BOTH
	panel.grow_vertical = Control.GROW_DIRECTION_BOTH
	panel.custom_minimum_size = Vector2(620, 0)
	var style := StyleBoxFlat.new()
	style.bg_color = Color(0.08, 0.07, 0.13, 0.97)
	style.border_color = Color(0.72, 0.62, 0.35)
	style.set_border_width_all(3)
	style.set_corner_radius_all(10)
	style.set_content_margin_all(26)
	panel.add_theme_stylebox_override("panel", style)
	_root.add_child(panel)

	var column := VBoxContainer.new()
	column.add_theme_constant_override("separation", 14)
	panel.add_child(column)

	_title = Label.new()
	_title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
	_title.add_theme_font_size_override("font_size", 40)
	column.add_child(_title)

	_subtitle = Label.new()
	_subtitle.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
	_subtitle.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
	_subtitle.custom_minimum_size = Vector2(560, 0)
	_subtitle.add_theme_font_size_override("font_size", 18)
	_subtitle.add_theme_color_override("font_color", Color("b8c4d8"))
	column.add_child(_subtitle)

	var heading := Label.new()
	heading.name = "Heading"
	heading.text = Loc.ui("ui.dive_result.harvest")
	heading.add_theme_font_size_override("font_size", 16)
	heading.add_theme_color_override("font_color", Color("8fa3c4"))
	column.add_child(heading)

	# La récolte peut être longue: seule la liste défile, le bouton de retour
	# reste toujours atteignable.
	var scroll := ScrollContainer.new()
	scroll.custom_minimum_size = Vector2(560, 260)
	scroll.horizontal_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED
	column.add_child(scroll)
	_list = VBoxContainer.new()
	_list.size_flags_horizontal = Control.SIZE_EXPAND_FILL
	_list.add_theme_constant_override("separation", 4)
	scroll.add_child(_list)

	_return_button = Button.new()
	_return_button.name = "Return"
	_return_button.custom_minimum_size = Vector2(300, 52)
	_return_button.size_flags_horizontal = Control.SIZE_SHRINK_CENTER
	_return_button.text = Loc.ui("ui.dive_result.return")
	_return_button.pressed.connect(_on_return)
	column.add_child(_return_button)

# `harvested` est tout ce qui a été ramassé pendant la plongée; `kept` ce qui
# rentre vraiment. Les deux diffèrent quand l'assurance ne couvre qu'une part.
# `title_key` vide veut dire « le titre se déduit de la mise hors service »,
# c'est-à-dire le comportement d'origine. Une plongée quittée volontairement est
# pourtant une troisième issue: ni assommé, ni à bout de souffle. Sans ce
# paramètre elle s'annoncerait « OUT OF ENERGY » alors que le joueur est reparti
# en pleine forme.
func present(reason: String, harvested: Dictionary, kept: Dictionary, was_knocked_out: bool, title_key: String = "") -> void:
	knocked_out = was_knocked_out
	_backdrop.color = KNOCKED_TINT if knocked_out else CALM_TINT
	if title_key.is_empty():
		title_key = "ui.dive_result.title_knocked" if knocked_out else "ui.dive_result.title_stamina"
	_title.text = Loc.ui(title_key)
	_title.add_theme_color_override("font_color", Color("ff9d9d") if knocked_out else Color("ffe6a7"))
	_subtitle.text = reason
	listed_ingredients.clear()
	for child: Node in _list.get_children():
		_list.remove_child(child)
		child.queue_free()

	var ids := harvested.keys()
	ids.sort()
	for raw_id: Variant in ids:
		var id := str(raw_id)
		var gathered := int(harvested[id])
		if gathered <= 0:
			continue
		listed_ingredients.append(id)
		_list.add_child(_line(id, gathered, int(kept.get(id, 0))))
	if listed_ingredients.is_empty():
		var empty := Label.new()
		empty.text = Loc.ui("ui.dive_result.nothing")
		empty.add_theme_color_override("font_color", LOST_COLOR)
		_list.add_child(empty)

	show()
	_return_button.call_deferred("grab_focus")

# Une ligne dit toujours combien a été trouvé, et combien rentre. Griser sans
# donner le chiffre laisserait le joueur deviner ce qu'il a perdu.
func _line(id: String, gathered: int, kept: int) -> Control:
	var row := HBoxContainer.new()
	row.add_theme_constant_override("separation", 10)
	var name_label := Label.new()
	name_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
	name_label.text = DataCatalog.ingredient_name(id)
	var amount := Label.new()
	amount.custom_minimum_size = Vector2(120, 0)
	amount.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
	if kept >= gathered:
		amount.text = "× %d" % gathered
		name_label.add_theme_color_override("font_color", KEPT_COLOR)
		amount.add_theme_color_override("font_color", KEPT_COLOR)
	else:
		amount.text = "%d / %d" % [kept, gathered]
		var tint := LOST_COLOR if kept <= 0 else Color("d8c98f")
		name_label.add_theme_color_override("font_color", tint)
		amount.add_theme_color_override("font_color", tint)
	row.add_child(name_label)
	row.add_child(amount)
	return row

func _on_return() -> void:
	return_requested.emit()

func _unhandled_input(event: InputEvent) -> void:
	if not visible:
		return
	if event.is_action_pressed("action") or event.is_action_pressed("ui_accept"):
		get_viewport().set_input_as_handled()
		_on_return()
