@tool
class_name OverlaidWindow
extends WindowContainer

@export var pauses_game : bool = false :
	set(value):
		pauses_game = value
		if pauses_game:
			process_mode = PROCESS_MODE_ALWAYS
		else:
			process_mode = PROCESS_MODE_INHERIT
@export var makes_mouse_visible : bool = true
@export var exclusive : bool = true
@export var exclusive_background_color : Color
@export var ignore_siblings : bool = false

var _initial_pause_state : bool = false
var _initial_mouse_mode : Input.MouseMode
var _initial_focus_control
var _initial_node_focus_modes : Dictionary
var _scene_tree : SceneTree 
var _exclusive_control_node : ColorRect

func _set_focus_none(node : Node) -> void:
	var all_children := node.get_children()
	if ignore_siblings and self in all_children:
		return
	for child in all_children:
		if child == self:
			continue
		if child is Control:
			_initial_node_focus_modes[child] = child.focus_mode
			child.focus_mode = Control.FOCUS_NONE
		_set_focus_none(child)

func _set_focus_initial() -> void:
	for node in _initial_node_focus_modes:
		if is_instance_valid(node) and node is Control:
			node.focus_mode = _initial_node_focus_modes[node]
	_initial_node_focus_modes.clear()

func close() -> void:
	if not visible: return
	if pauses_game:
		_scene_tree.paused = _initial_pause_state
	Input.set_mouse_mode(_initial_mouse_mode)
	_set_focus_initial()
	if is_instance_valid(_initial_focus_control) and _initial_focus_control.is_inside_tree():
		_initial_focus_control.grab_focus()
	if _exclusive_control_node:
		_exclusive_control_node.queue_free()
	super.close()

func _overlaid_window_setup():
	if _scene_tree:
		_initial_pause_state = _scene_tree.paused
	_initial_mouse_mode = Input.get_mouse_mode()
	_initial_focus_control = get_viewport().gui_get_focus_owner()
	if _initial_focus_control:
		_initial_focus_control.release_focus()
	if Engine.is_editor_hint(): return
	_scene_tree.paused = pauses_game or _initial_pause_state
	if makes_mouse_visible:
		Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
	if exclusive:
		_set_focus_none(get_tree().current_scene)
		_exclusive_control_node = ColorRect.new()
		_exclusive_control_node.name = self.name + "ExclusiveControl"
		_exclusive_control_node.color = exclusive_background_color
		_exclusive_control_node.set_anchors_preset(PRESET_FULL_RECT)
		add_sibling.call_deferred(_exclusive_control_node)
		await _exclusive_control_node.draw
		get_parent().move_child(_exclusive_control_node, get_index())

func _on_visibility_changed() -> void:
	if is_visible_in_tree():
		_overlaid_window_setup()

func _enter_tree() -> void:
	_scene_tree = get_tree()
	if not visibility_changed.is_connected(_on_visibility_changed):
		visibility_changed.connect(_on_visibility_changed)
	_on_visibility_changed()
