tool
class_name ButtonContainer
extends PanelContainer

signal pressed

export(Color) var color_normal: Color setget set_normal_color
export(Color) var color_hovered: Color setget set_hovered_color
export(Color) var color_pressed: Color setget set_pressed_color
export(Color) var modulation_disabled: Color = Color(0.8, 0.8, 0.8, 0.5)
export(bool) var disabled: bool setget set_disabled


var _pressed: bool = false
var _is_ready: bool = false


func _ready() -> void:
	if Engine.is_editor_hint():
		set_process_input(false)
	else:
		connect("mouse_entered", self, "_on_mouse_entered")
		connect("mouse_exited", self, "_on_mouse_exited")
	
	# Must duplicate the style so changes aren't applied to all instances of
	# this scene
	var style = get("custom_styles/panel").duplicate()
	set("custom_styles/panel", style)
	get("custom_styles/panel").set_bg_color(color_normal)
	
	# If input processing was disabled must disable it again in `_ready()`
	# since attempts to disable it before `_ready()` are ignored
	if disabled:
		set_process_input(false)
	_is_ready = true


func _gui_input(event: InputEvent) -> void:
	# Only pressed if the mouse button is consecutively pressed and released
	# within the node's `Rect2`
	if (
			not disabled
			and event is InputEventMouseButton
			and event.get_button_index() == BUTTON_LEFT
	):
		var mouse_in_rect: bool = \
				get_global_rect().has_point(get_global_mouse_position())
		if mouse_in_rect and event.is_pressed():
			_pressed = true
			get("custom_styles/panel").set_bg_color(color_pressed)
		elif mouse_in_rect and not event.is_pressed() and _pressed:
			_pressed = false
			get("custom_styles/panel").set_bg_color(color_hovered)
			emit_signal("pressed")
		else:
			_pressed = false


func _enter_tree() -> void:
	if _is_ready:
		# Since this node may be removed from the scene when pressed, it may
		# not get the mouse button up event so would still be using its pressed
		# color when re-entering the scene. This fixes that
		get("custom_styles/panel").set_bg_color(color_normal)


func set_normal_color(color: Color) -> void:
	color_normal = color
	if Engine.is_editor_hint():
		get("custom_styles/panel").set_bg_color(color_normal)


func set_hovered_color(color: Color) -> void:
	color_hovered = color


func set_pressed_color(color: Color) -> void:
	color_pressed = color


func is_disabled() -> bool:
	"""
	Returns:
		If the button is disabled
	"""
	return disabled


func set_disabled(disable: bool) -> void:
	disabled = disable
	if not Engine.is_editor_hint():
		set_process_input(not disabled)
	
	if disabled:
		set_modulate(modulation_disabled)
	else:
		set_modulate(Color(1, 1, 1, 1))


func _on_mouse_entered() -> void:
	if not is_disabled():
		get("custom_styles/panel").set_bg_color(color_hovered)


func _on_mouse_exited() -> void:
	if not is_disabled():
		get("custom_styles/panel").set_bg_color(color_normal)
