# Hurry Curry! - a game about cooking
# Copyright (C) 2025 Hurry Curry! contributors
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, version 3 of the License only.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
#
class_name Menu
extends Control


#enum Anim { NONE, FADE }
#@export var animation: Anim = Anim.NONE
@export var support_anim := true
@export var auto_anim := true

var data

signal submenu_close()

const transition_scene = preload("res://gui/menus/transition/scene_transition.tscn")
var transition: SceneTransition
var parent_menu: Menu = null
var previous_path = null # : String
var open_since = 0

func _ready():
	open_since = Time.get_ticks_msec()
	Global.focused_menu = self
	focus_first(self)
	connect_button_sounds(self)
	disable_context_menus(self)
	update_parent_menu(self.get_parent())
	if support_anim: anim_setup()
	if auto_anim: _menu_open()
	_menu_music()
	get_tree().get_root().go_back_requested.connect(exit_maybe)

func anim_setup():
	transition = transition_scene.instantiate()
	add_child(transition)
func _menu_open():
	if transition != null: await transition.fade_in()
func _menu_exit():
	if transition != null: await transition.fade_out()
func _menu_cover(_state: bool):
	pass
func _menu_music():
	pass

var popup: Menu = null
var covered := false
func submenu(path: String, data_ = null):
	var prev_focus = Global.focused_node
	if popup != null: return
	_disable_recursive(self, true)
	covered = true
	await _menu_cover(true)
	popup = load(path).instantiate()
	popup.data = data_
	add_child(popup)
	# print("Submenu opened ", path)
	await submenu_close
	# print("Submenu closed ", path)
	covered = false
	await _menu_cover(false)
	Global.focused_menu = self
	_menu_music()
	_disable_recursive(self, false)
	if prev_focus != null: prev_focus.grab_focus()

func _disable_recursive(node: Node, state: bool):
	if node is BaseButton: 
		if state and node.disabled: node.add_to_group("was_disabled")
		else: node.remove_from_group("was_disabled")
		node.disabled = state or node.is_in_group("was_disabled")
	for c in node.get_children(): _disable_recursive(c, state)

func exit():
	_disable_recursive(self, true)
	if transition and transition.fading:
		push_error("menu exit() called twice")
		return
	if popup != null: await popup.exit()
	await self._menu_exit()
	if previous_path != null:
		replace_menu(previous_path)
	else:
		get_parent().submenu_close.emit()
		queue_free()

func quit():
	await exit()
	get_parent().quit()

func replace_menu(path: String, data_ = null, prev_path = null): # prev_path: String?
	print("Replace menu: ", path)
	if popup != null: await popup.exit()
	_disable_recursive(self, true)
	await _menu_exit()
	var new_menu: Menu = load(path).instantiate()
	new_menu.data = data_
	if prev_path != null: new_menu.previous_path = prev_path
	get_parent().add_child(new_menu)
	if parent_menu != null: parent_menu.popup = new_menu
	queue_free()

var focus_auto_changed := false
func focus_first(node: Node) -> bool:
	focus_auto_changed = true
	if node.is_in_group("no_auto_focus"):
		return false
	if (node is Button and not node.focus_mode == FocusMode.FOCUS_NONE) or node.is_in_group("autoselect"):
		node.grab_focus()
		# print("Node %s (%s) was selected for focus" % [node.name, node])
		return true
	for c in node.get_children():
		if focus_first(c):
			return true
	return false

func connect_button_sounds(node: Node):
	if node is Button or node is TextureButton:
		if not node.is_in_group("no_click_sound"):
			node.pressed.connect(Sound.play_click)
	if (node is Button and not node.disabled) or (node is LineEdit and node.editable) or node is Slider:
		if not node.is_in_group("no_click_sound"):
			node.mouse_entered.connect(Sound.play_hover)
	for c in node.get_children():
		connect_button_sounds(c)

func disable_context_menus(node: Node):
	if node is LineEdit:
		node.context_menu_enabled = false
	for c in node.get_children():
		disable_context_menus(c)

func update_parent_menu(node: Node):
	if node is Menu: parent_menu = node
	elif node.get_parent() != null: update_parent_menu(node.get_parent())

func _input(_event):
	if Input.is_action_just_pressed("menu"):
		exit_maybe()

func exit_maybe() -> void:
	# Exit menu if all conditions are met
	if popup != null: return
	if transition and transition.fading: return
	var time := Time.get_ticks_msec()
	if time - open_since < 100: return
	Sound.play_click()
	exit()
