class_name OptionsMenu
extends Control

signal closed
signal settings_changed
## Effacer une partie se demande d'ici, mais ne se fait pas ici: l'ecran des
## emplacements appartient a l'accueil, et c'est lui qui sait quoi montrer.
signal delete_requested

## Le meme menu sert a l'accueil et a la pause. Effacer une partie n'a de sens
## qu'au premier: en pleine partie, le bouton proposerait de supprimer ce qu'on
## est en train de jouer.
var allow_delete := false:
	set(value):
		allow_delete = value
		if is_node_ready():
			refresh()

@onready var title_label: Label = %TitleLabel
@onready var display_label: Label = %DisplayLabel
@onready var display_button: Button = %DisplayButton
@onready var language_label: Label = %LanguageLabel
@onready var language_button: Button = %LanguageButton
@onready var volume_label: Label = %VolumeLabel
@onready var volume_value: Label = %VolumeValue
@onready var volume_slider: HSlider = %VolumeSlider
@onready var preview_label: Label = %PreviewLabel
@onready var preview_toggle: CheckButton = %PreviewToggle
@onready var vsync_label: Label = %VSyncLabel
@onready var vsync_toggle: CheckButton = %VSyncToggle
@onready var delete_button: Button = %DeleteButton
@onready var close_button: Button = %CloseButton
@onready var display_menu: DisplayMenu = %DisplayMenu

var _refreshing := false

func _ready() -> void:
	process_mode = Node.PROCESS_MODE_ALWAYS
	display_button.pressed.connect(display_menu.open)
	language_button.pressed.connect(_toggle_language)
	volume_slider.value_changed.connect(_preview_volume)
	volume_slider.drag_ended.connect(_commit_volume)
	vsync_toggle.toggled.connect(_toggle_vsync)
	preview_toggle.toggled.connect(_toggle_attack_preview)
	close_button.pressed.connect(close)
	delete_button.pressed.connect(_request_delete)
	display_menu.menu_closed.connect(_on_display_closed)
	for button: BaseButton in [display_button, language_button, preview_toggle, vsync_toggle, delete_button, close_button]:
		button.mouse_entered.connect(button.grab_focus)
	refresh()

func open() -> void:
	visible = true
	refresh()
	display_button.grab_focus()

func close() -> void:
	if not visible:
		return
	if display_menu.visible:
		display_menu.close()
		return
	GameState.save_settings()
	visible = false
	closed.emit()

func refresh() -> void:
	_refreshing = true
	title_label.text = Loc.ui("ui.options.title")
	display_label.text = Loc.ui("ui.options.display")
	display_button.text = Loc.ui("ui.options.display_value") % DisplayMenu.option_label(GameState.display_mode_id)
	language_label.text = Loc.ui("ui.options.language")
	language_button.text = Loc.ui("ui.options.language_fr") if GameState.language == "fr" else Loc.ui("ui.options.language_en")
	volume_label.text = Loc.ui("ui.options.master_volume")
	volume_slider.value = GameState.master_volume * 100.0
	volume_value.text = "%d%%" % roundi(volume_slider.value)
	preview_label.text = Loc.ui("ui.options.attack_preview")
	preview_toggle.button_pressed = GameState.attack_preview_enabled
	preview_toggle.text = Loc.ui("ui.options.on") if GameState.attack_preview_enabled else Loc.ui("ui.options.off")
	vsync_label.text = Loc.ui("ui.options.vsync")
	vsync_toggle.button_pressed = GameState.vsync_enabled
	vsync_toggle.text = Loc.ui("ui.options.on") if GameState.vsync_enabled else Loc.ui("ui.options.off")
	delete_button.text = Loc.ui("ui.main.delete_game")
	delete_button.visible = allow_delete
	# Rien a effacer: le bouton reste visible mais inerte, plutot que de
	# disparaitre et faire sauter le reste du menu d'une ligne.
	delete_button.disabled = not GameState.has_any_save()
	close_button.text = Loc.ui("ui.common.back")
	_refreshing = false

## Une aide de lecture, pas une regle: rien du combat ne change, seulement ce
## que le joueur voit avant de frapper.
func _toggle_attack_preview(enabled: bool) -> void:
	if _refreshing:
		return
	GameState.set_attack_preview_enabled(enabled)
	refresh()
	settings_changed.emit()

func _request_delete() -> void:
	GameState.save_settings()
	visible = false
	delete_requested.emit()

func _toggle_language() -> void:
	GameState.set_language("en" if GameState.language == "fr" else "fr")
	refresh()
	settings_changed.emit()
	language_button.grab_focus()

func _preview_volume(value: float) -> void:
	if _refreshing:
		return
	GameState.master_volume = clampf(value / 100.0, 0.0, 1.0)
	GameState.apply_audio_settings()
	volume_value.text = "%d%%" % roundi(value)

func _commit_volume(_value_changed: bool) -> void:
	GameState.save_settings()
	settings_changed.emit()

func _toggle_vsync(enabled: bool) -> void:
	if _refreshing:
		return
	GameState.set_vsync_enabled(enabled)
	vsync_toggle.text = Loc.ui("ui.options.on") if enabled else Loc.ui("ui.options.off")
	settings_changed.emit()

func _on_display_closed() -> void:
	refresh()
	settings_changed.emit()
	display_button.grab_focus()

func _unhandled_input(event: InputEvent) -> void:
	if not visible or display_menu.visible:
		return
	if event.is_action_pressed("pause") or event.is_action_pressed("ui_cancel"):
		close()
		get_viewport().set_input_as_handled()
