@tool
@icon("res://addons/icons-fonts/nodes/FontIconButton.svg")

# todo add description and docs links when ready
class_name FontIconButton
extends ButtonContainer

@export_group("Layout", "layout_")
@export_enum("Label-Icon", "Icon-Label", "Icon")
var layout_order := "Label-Icon":
	set(value):
		layout_order = value
		if !is_node_ready(): await ready
		_set_order(value)

@export var layout_vertical := false:
	set(value):
		layout_vertical = value
		if !is_node_ready(): await ready
		_box.vertical = value

@export var layout_alignment := BoxContainer.ALIGNMENT_CENTER:
	set(value):
		layout_alignment = value
		if !is_node_ready(): await ready
		_box.alignment = value

@export_group("Icon", "icon_")
@export var icon_settings := FontIconSettings.new():
	set(value):
		icon_settings = value
		if !is_node_ready(): await ready
		_font_icon.icon_settings = value

@export_group("Label", "label_")
@export var label_text := "":
	set(value):
		label_text = value
		if !is_node_ready(): await ready
		_label.text = label_text

@export var label_settings := LabelSettings.new():
	set(value):
		label_settings = value
		if !is_node_ready(): await ready
		_label.label_settings = label_settings

@export var button_margin := 5:
	set(value):
		button_margin = value
		if !is_node_ready(): await ready
		var margins := [
			"margin_top", "margin_left",
			"margin_bottom", "margin_right"
		]
		for margin in margins:
			_margins.add_theme_constant_override(margin, button_margin)

var _font_icon: FontIcon
var _label: Label
var _box: BoxContainer
var _margins: MarginContainer

func _get_lay_dict() -> Dictionary:
	return {
		"Label": _label,
		"Icon": _font_icon,
	}

func _add_icon(_icon_settings: FontIconSettings) -> FontIcon:
	var empty_style := StyleBoxEmpty.new()
	var _icon = FontIcon.new()
	_icon.add_theme_stylebox_override("normal", empty_style)
	Utils.connect_if_possible(_icon_settings, "changed",
		func(): update_icon(_icon_settings, _icon))
	return _icon

func _ready():
	super._ready()
	for ch: Control in get_children():
		ch.queue_free()

	ready.connect(func(): self.layout_order = layout_order)
	var empty_style := StyleBoxEmpty.new()
	_box = BoxContainer.new()
	_font_icon = _add_icon(icon_settings)

	_label = Label.new()
	_label.add_theme_stylebox_override("normal", empty_style)

	_margins = MarginContainer.new()
	_margins.add_child(_box)
	add_child(_margins)

	Utils.connect_if_possible(
		label_settings, "changed",
		func():
			if label_settings != _label.label_settings:
				_label.label_settings = label_settings
	)

func update_icon(new_icon_settings: FontIconSettings, font_icon: FontIcon):
	if new_icon_settings != font_icon.icon_settings:
		font_icon.icon_settings = new_icon_settings
	Utils.connect_if_possible(
		new_icon_settings, "changed",
		font_icon._on_icon_settings_changed)

func _clear_box():
	if _box.get_child_count() == 0: return
	for ch: Control in _box.get_children():
		_box.remove_child(ch)

func _set_order(order:String):
	_clear_box()
	await get_tree().create_timer(0.2).timeout
	_apply_layout(_crate_layout(order))

func _crate_layout(order:String) -> Array[Control]:
	var layout: Array[Control] = []
	var order_split := order.split("-")
	var dict := _get_lay_dict()
	for con in order_split:
		layout.append(dict[con])
	return layout

func _apply_layout(layout: Array[Control]):
	for control: Control in layout:
		if control.get_parent() == _box: continue
		_box.add_child(control)
		if control is FontIcon:
			control.size_flags_horizontal\
				= Control.SIZE_SHRINK_CENTER