extends Control

signal date_selected(date: Calendar.DateObj)

@onready var _main: Main = get_tree().get_current_scene()
@onready var _month_label: Label = $VBoxContainer/HBoxContainer/MonthLabel
@onready var _days_grid: GridContainer = $VBoxContainer/DaysGrid
@onready var _prev_month_button: Button = $VBoxContainer/HBoxContainer/PrevMonthButton
@onready var _next_month_button: Button = $VBoxContainer/HBoxContainer/NextMonthButton
@onready var _vertical_box: VBoxContainer = $VBoxContainer
@onready var _horizontal_box: HBoxContainer = $VBoxContainer/HBoxContainer

var cal: Calendar = Calendar.new()
var current_date: Calendar.DateObj = Calendar.DateObj.today()
var selected_date_label: Label
var weekdays_formatted: Array[String]
var months_formatted: Array[String]

func _process(delta):
	_process_grid_size()
	_process_font_size(_month_label, 32)
	_process_font_size(_prev_month_button, 32)
	_process_font_size(_next_month_button, 32)

func _process_grid_size():
	for day_label in _days_grid.get_children():
		var font_size = day_label.label_settings.font_size
		var new_font_size = get_viewport_rect().size.y/32
		if font_size != new_font_size:
			day_label.label_settings.font_size = new_font_size

		for selection in day_label.get_children():
			var selection_size = selection.size.x
			var new_selection_size = get_viewport_rect().size.y/32
			if selection_size != new_selection_size:
				selection.size.x = new_selection_size
				selection.size.y = new_selection_size

func _process_font_size(obj, k):
	var font_size = obj.get_theme_default_font_size()
	var new_font_size = get_viewport_rect().size.y/k
	if font_size != new_font_size:
		obj.add_theme_font_size_override("font_size", new_font_size)

func _ready() -> void:
	cal.set_calendar_locale("res://addons/calendar_library/demo/calendar_locale_RU.tres")
	cal.set_first_weekday(Time.WEEKDAY_MONDAY)
	cal.week_number_system = Calendar.WeekNumberSystem.WEEK_NUMBER_FOUR_DAY
	weekdays_formatted = cal.get_weekdays_formatted(Calendar.WeekdayFormat.WEEKDAY_FORMAT_SHORT)
	months_formatted = cal.get_months_formatted(Calendar.MonthFormat.MONTH_FORMAT_FULL)

	_prev_month_button.pressed.connect(_on_prev_month_pressed)
	_next_month_button.pressed.connect(_on_next_month_pressed)

	update_calendar()

func update_calendar() -> void:
	for child in _days_grid.get_children():
		child.queue_free()

	_month_label.text = "%s %d" % [months_formatted[current_date.month - 1], current_date.year]

	var month_calendar = cal.get_calendar_month(current_date.year, current_date.month, true)
	var today = Calendar.DateObj.today()

	for weekday in weekdays_formatted:
		var label = CalendarLabel.new(weekday)
		_days_grid.add_child(label)

	for week in month_calendar:
		for date_obj in week:
			var day_label = create_day_label(date_obj, today)
			_days_grid.add_child(day_label)

	_cancel_selection()

func _cancel_selection():
	for day_label in _days_grid.get_children():
		for selection in day_label.get_children():
			selection.queue_free()

func create_day_label(date_obj: Calendar.DateObj, today: Calendar.DateObj) -> CalendarLabel:
	var label = CalendarLabel.new(str(date_obj.day), true)

	if date_obj.month != current_date.month:
		label.label_settings.font_color = Color("#414853")
	else:
		if date_obj.is_equal(today):
			label.label_settings.font_color = Color("#70bafa")
		else:
			label.label_settings.font_color = Color("#cdced2")

	if date_obj.is_equal(current_date):
		set_selected_state(label)
		selected_date_label = label

	label.pressed.connect(_on_date_pressed.bind(date_obj, label))
	return label

func set_selected_state(label: Label) -> void:
	if selected_date_label and selected_date_label.get_child_count() > 0:
		selected_date_label.get_child(0).queue_free()

	var selection = ColorRect.new()
	selection.size = Vector2(60, 60)
	selection.color = Color("#414853")
	selection.show_behind_parent = true
	label.add_child(selection)
	selected_date_label = label

func _on_date_pressed(date: Calendar.DateObj, label: Label) -> void:
	current_date = date
	set_selected_state(label)
	date_selected.emit(date)
	update_calendar()

	_main.go_to_previous_page(true)

func _on_prev_month_pressed() -> void:
	current_date.add_months(-1)
	update_calendar()

func _on_next_month_pressed() -> void:
	current_date.add_months(1)
	update_calendar()

func update():
	_cancel_selection()

class CalendarLabel:
	extends Label
	signal pressed()

	var clickable: bool = false

	func _init(p_text: String, p_clickable: bool = false):
		text = p_text
		horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
		mouse_filter = MOUSE_FILTER_PASS if p_text.is_empty() else MOUSE_FILTER_STOP

		var settings = LabelSettings.new()
		settings.font_size = 46
		settings.font_color = Color.WHITE
		label_settings = settings

		if p_clickable and not p_text.is_empty():
			clickable = true
			mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
	
	func _gui_input(event: InputEvent) -> void:
		if clickable and event is InputEventMouseButton:
			if event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
				pressed.emit()