@tool
@icon("res://addons/custom-ui-elements/nodes/ButtonContainer.svg")
extends PanelContainer

# todo add description and docs links when ready
class_name ButtonContainer

## Emitted when button is pressed
signal pressed

## Emitted when button is toggled
## Works only if `toggle_mode` is on.
signal toggled(value: bool)

signal state_changed(state_name: StringName)

## If true, button will be disabled
@export var disabled := false:
	set(value):
		disabled = value
		if disabled:
			_change_stylebox("disabled")
			state_changed.emit(&"disabled")
			return
		
		_change_stylebox("normal")
		state_changed.emit(&"normal")

## If true, button will be in toggle mode
@export var toggle_mode := false
var _toggled := false:
	get: return _toggled

## If true, button will be in pressed state
@export var button_pressed := false:
	set(value):
		if toggle_mode:
			button_pressed = value
			_togglef(null, value)
			return
		
		emit_signal("pressed")

## Name of node group to be used as button group
## It changes all buttons with toggle_mode in group into radio buttons
@export var button_group: StringName = ""

@export_group("Styles", "style_")
@export var style_normal: StyleBox:
	set(value):
		style_normal = value
		if !disabled or !button_pressed:
			_change_stylebox("normal")

@export var style_focus: StyleBox

@export var style_pressed: StyleBox:
	set(value):
		style_pressed = value
		if !disabled and button_pressed:
			_change_stylebox("pressed")

@export var style_hover: StyleBox

@export var style_disabled: StyleBox:
	set(value):
		style_disabled = value
		if disabled:
			_change_stylebox("disabled")

var current_style: StringName

func _ready() -> void:
	_change_stylebox("normal")
	state_changed.emit(&"normal")
	Utils.connect_if_possible(self, &"mouse_entered", _on_mouse_entered)
	Utils.connect_if_possible(self, &"mouse_exited", _on_mouse_exited)
	
	if button_group: add_to_group(button_group)

func _on_mouse_exited():
	if disabled: return
	if toggle_mode and _toggled: return
	_change_stylebox("normal")
	state_changed.emit(&"normal")

func _on_mouse_entered():
	if disabled: return
	_change_stylebox("hover")
	state_changed.emit(&"hover")

func _change_stylebox(button_style: StringName = "normal"):
	# prints("changed style to:", button_style)
	var stylebox := get_theme_stylebox(button_style, "Button")
	match button_style:
		"normal":
			stylebox = style_normal if style_normal else stylebox
		"focus":
			stylebox = style_focus if style_focus else stylebox
		"pressed":
			stylebox = style_pressed if style_pressed else stylebox
		"hover":
			stylebox = style_hover if style_hover else stylebox
		"disabled":
			stylebox = style_disabled if style_disabled else stylebox

	if current_style != button_style:
		current_style = button_style
		add_theme_stylebox_override("panel", stylebox)

func _gui_input(event: InputEvent) -> void:
	if disabled: return
	if event is InputEventMouseButton:
		if event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
			if toggle_mode:
				var t := !_toggled
				_togglef(null, t)
				
				if button_group:
					get_tree().call_group(
						button_group, "_togglef", self, !t)
					return
			
			state_changed.emit(&"pressed")
			pressed.emit()

func _togglef(main_button: ButtonContainer, value: bool):
	if disabled: return
	if main_button == self: return

	_toggled = value
	if value:
		_change_stylebox("pressed")
		state_changed.emit(&"pressed")
	else:
		_change_stylebox("normal")
		state_changed.emit(&"normal")

	toggled.emit(_toggled)