@tool
extends FlexContainer3D
class_name Pagination3D

signal on_page_changed(page: int)

const ButtonScene = preload ("res://content/ui/components/button/button.tscn")
const LabelScene = preload ("res://content/ui/components/label_container/label_container.tscn")

@onready var prev_button = $Prev
@onready var next_button = $Next

@export var page: int = 0:
	set(value):
		if page == value: return

		page = clamp(value, 0, pages - 1)
		_update()
@export var pages: int = 5:
	set(value):
		if pages == value: return

		pages = max(1, value)
		_update()
@export var visible_pages: int = 5:
	set(value):
		if visible_pages == value: return

		visible_pages = max(5, value)
		_update()

func _ready():
	_update()

	prev_button.on_button_up.connect(func():
		page -= 1
		on_page_changed.emit(page)
	)

	next_button.on_button_up.connect(func():
		page += 1
		on_page_changed.emit(page)
	)

func _update():
	if !is_node_ready(): return

	for child in get_children():
		if child != prev_button&&child != next_button:
			remove_child(child)
			child.queue_free()

	var display_pages = min(pages, visible_pages)
	var center_pos = floor(display_pages / 2)
	var start_dots = pages > visible_pages&&page > visible_pages - center_pos - 1
	var end_dots = pages > visible_pages&&page < pages - visible_pages + floor((display_pages - 1) / 2)

	var at_start = page == 0
	prev_button.disabled = at_start
	prev_button.visible = !at_start

	var at_end = page == pages - 1
	next_button.disabled = at_end
	next_button.visible = !at_end

	prev_button.size = Vector3(size.y, size.y, size.z)
	next_button.size = Vector3(size.y, size.y, size.z)

	for i in range(display_pages):
		if (start_dots&&i == 1)||(end_dots&&i == display_pages - 2):
			var container = Container3D.new()
			container.size = Vector3(size.y, size.y, size.z)
			add_child(container)
			move_child(container, -2)

			var dots = LabelScene.instantiate()
			dots.text = "..."
			container.add_child(dots)
			continue
		
		var button = ButtonScene.instantiate()
		button.size = Vector3(size.y, size.y, size.z)
		button.toggleable = true

		if i == 0:
			button.label = "1"
		elif i == display_pages - 1:
			button.label = str(pages)
		elif pages <= visible_pages:
			button.label = str(i + 1)
		elif visible_pages % 2 == 1:
			button.label = str(clamp(page, center_pos, pages - 1 - center_pos) - center_pos + i + 1)
		else:
			button.label = str(clamp(page + 1, 3, pages - 3) - center_pos + i + 1)

		button.on_button_down.connect(func():
			page=int(button.label) - 1
			on_page_changed.emit(page)
		)

		if (int(button.label) - 1) == page:
			button.initial_active = true
			button.disabled = true

		add_child(button)
		move_child(button, -2)

	super._update()