---@type druid
local druid = require("druid.druid")
local monarch = require("monarch.monarch")
local default_style = require("druid.styles.default.style")

local checkbox = require("druid.extended.checkbox")
local checkbox_group = require("druid.extended.checkbox_group")
local dynamic_grid = require("druid.extended.dynamic_grid")
local input = require("druid.extended.input")
local lang_text = require("druid.extended.lang_text")
local progress = require("druid.extended.progress")
local radio_group = require("druid.extended.radio_group")
local slider = require("druid.extended.slider")
local timer_component = require("druid.extended.timer")
local data_list = require("druid.extended.data_list")

local cache_path = sys.get_save_file("druid", "cache")


local function save_cache(self)
	sys.save(cache_path, self.cache)
end


local function back_to_lobby(self)
	if gui.set_enabled(self.button_menu.node) then
		return
	end

	monarch.back()
	gui.set_enabled(gui.get_node("C_Anchor"), true)
	gui.set_enabled(self.button_menu.node, false)
	gui.set_enabled(self.button_code.node, false)
	gui.set_enabled(self.button_api.node, true)

	self.text_header:set_to("Druid")

	self.cache.last_scene = nil
	save_cache(self)
end


local function show_scene(self, scene_name, text_header)
	print("Show scene:", scene_name)

	self.current_script_url = self.scene_urls[scene_name]
	monarch.show(scene_name)
	gui.set_enabled(gui.get_node("C_Anchor"), false)
	gui.set_enabled(self.button_menu.node, true)
	gui.set_enabled(self.button_code.node, true)
	gui.set_enabled(self.button_api.node, false)

	self.text_header:set_to(text_header)

	self.cache.last_scene = scene_name
	save_cache(self)
end


local function init_top_panel(self)
	self.druid:new_blocker("panel_top")

	self.button_menu = self.druid:new_button("button_menu/button", back_to_lobby)
	self.druid:new_back_handler(back_to_lobby)
	gui.set_enabled(self.button_menu.node, false)

	self.button_api = self.druid:new_button("button_api/button", function()
		sys.open_url("https://insality.github.io/druid/")
	end)

	self.button_code = self.druid:new_button("button_code/button", function()
		local example_url = string.format("https://github.com/Insality/druid/blob/master/example/examples%s", self.current_script_url)
		sys.open_url(example_url)
	end)
	gui.set_enabled(self.button_code.node, false)

	self.text_header = self.druid:new_text("text_header", "Druid")
end


local function on_window_callback(self, event, data)
	druid.on_window_callback(event, data)
end


local function get_title(self, text)
	local prefab = gui.get_node("prefab_header")
	local nodes = gui.clone_tree(prefab)
	local root = nodes["prefab_header"]
	gui.set_enabled(root, true)
	gui.set_text(nodes["prefab_text"], text)
	return root
end


local function get_button(self, text, scene_name, script_url)
	local prefab = gui.get_node("prefab_button")
	local nodes = gui.clone_tree(prefab)
	local root = nodes["prefab_button"]
	gui.set_enabled(root, true)

	self.scene_names[scene_name] = text
	self.scene_urls[scene_name] = script_url

	self.druid:new_button(root, function()
		show_scene(self, scene_name, text)
	end):set_click_zone(self.lobby_scroll.view_node)

	gui.set_text(nodes["text_button_lobby"], text)

	return root
end


local function get_button_disabled(self, text)
	local prefab = gui.get_node("prefab_button")
	local nodes = gui.clone_tree(prefab)
	local root = nodes["prefab_button"]
	gui.play_flipbook(nodes["icon_button"], "progress_back")
	gui.set_enabled(root, true)
	gui.set_text(nodes["text_button_lobby"], text)

	return root
end


local function init_lobby(self)
	gui.set_enabled(gui.get_node("prefabs"), false)
	self.scene_names = {}
	self.scene_urls = {}

	self.lobby_scroll = self.druid:new_scroll("lobby_view", "lobby_content")
	self.lobby_grid = self.druid:new_dynamic_grid("lobby_content")
	self.lobby_scroll:bind_grid(self.lobby_grid)
	self.lobby_scroll.style.WHEEL_SCROLL_SPEED = 20

	self.lobby_grid:add(get_title(self, "General examples"))
	self.lobby_grid:add(get_button(self, "Overview", "general_overview", "/general/overview/overview.gui_script"))
	self.lobby_grid:add(get_button(self, "Buttons", "general_buttons", "/general/buttons/buttons.gui_script"))
	self.lobby_grid:add(get_button(self, "Sliders", "general_sliders", "/general/sliders/sliders.gui_script"))
	self.lobby_grid:add(get_button(self, "Scrolls", "general_scroll", "/general/scroll/scroll.gui_script"))
	self.lobby_grid:add(get_button(self, "Grids", "general_grid", "/general/grid/grid.gui_script"))
	self.lobby_grid:add(get_button(self, "Progress Bar", "general_progress_bar", "/general/progress_bar/progress_bar.gui_script"))
	self.lobby_grid:add(get_button(self, "Data List", "general_data_list", "/general/data_list/data_list.gui_script"))
	self.lobby_grid:add(get_button(self, "Checkboxes", "general_checkboxes", "/general/checkboxes/checkboxes.gui_script"))
	self.lobby_grid:add(get_button(self, "Input text", "general_input", "/general/input/input.gui_script"))
	self.lobby_grid:add(get_button(self, "Layout", "general_layout", "/general/layout/layout.gui_script"))
	self.lobby_grid:add(get_button(self, "Hover", "general_hover", "/general/hover/hover.gui_script"))
	self.lobby_grid:add(get_button(self, "Swipe", "general_swipe", "/general/swipe/swipe.gui_script"))
	self.lobby_grid:add(get_button(self, "Drag", "general_drag", "/general/drag/drag.gui_script"))
	self.lobby_grid:add(get_button(self, "Hotkey", "general_hotkey", "/general/hotkey/hotkey.gui_script"))

	self.lobby_grid:add(get_title(self, "Texts"))
	self.lobby_grid:add(get_button(self, "Texts", "texts_general", "/texts/texts_general/texts_general.gui_script"))
	self.lobby_grid:add(get_button(self, "Adjust types", "texts_adjust", "/texts/texts_adjust/texts_adjust.gui_script"))
	self.lobby_grid:add(get_button(self, "Lang Text", "texts_lang_text", "/texts/texts_adjust/texts_lang_text.gui_script"))

	self.lobby_grid:add(get_title(self, "Scrolls"))
	self.lobby_grid:add(get_button_disabled(self, "Nested scrolls", "scroll_scene"))
	self.lobby_grid:add(get_button_disabled(self, "With points of interest", "scroll_scene"))
	self.lobby_grid:add(get_button_disabled(self, "Without inertion", "scroll_scene"))

	self.lobby_grid:add(get_title(self, "Grids"))
	self.lobby_grid:add(get_button(self, "Static grid", "grid_static_grid", "/grid/static_grid/static_grid.gui_script"))
	self.lobby_grid:add(get_button(self, "Static with dynamic pos", "grid_static_grid_dynamic_pos", "/grid/static_grid_dynamic_pos/static_grid_dynamic_pos.gui_script"))
	self.lobby_grid:add(get_button_disabled(self, "Dynamic grid", "scroll_scene"))
	self.lobby_grid:add(get_button_disabled(self, "Scroll binding", "scroll_scene"))
	self.lobby_grid:add(get_button(self, "Add/Remove animations", "grid_animations", "/grid/grid_animations/grid_animations.gui_script"))

	self.lobby_grid:add(get_title(self, "Data list / Infinity scroll"))
	self.lobby_grid:add(get_button(self, "With static grid", "data_list_static_grid", "/data_list/static_grid/static_grid.gui_script"))
	self.lobby_grid:add(get_button(self, "With dynamic grid", "data_list_dynamic_grid", "/data_list/dynamic_grid/dynamic_grid.gui_script"))
	self.lobby_grid:add(get_button_disabled(self, "Add/remove elements", "data_list_add_remove_nodes"))
	self.lobby_grid:add(get_button(self, "Navigate over elements", "data_list_navigate", "/data_list/navigate/navigate.gui_script"))
	self.lobby_grid:add(get_button(self, "Reinit data", "data_list_reinit_data", "/data_list/reinit_data/reinit_data.gui_script"))
	self.lobby_grid:add(get_button(self, "With component", "data_list_with_component", "/data_list/with_component/with_component.gui_script"))

	self.lobby_grid:add(get_title(self, "Layouts"))
	self.lobby_grid:add(get_button(self, "Layout fit", "layout_fit", "/custom/layout_fit/layout_fit.gui_script"))

	self.lobby_grid:add(get_title(self, "Custom components"))
	self.lobby_grid:add(get_button(self, "Rich Input", "custom_rich_input", "/custom/rich_input/rich_input.gui_script"))
	self.lobby_grid:add(get_button(self, "Pin Knob", "custom_pin_knob", "/custom/pin_knob/pin_knob.gui_script"))
	self.lobby_grid:add(get_button(self, "Rich Text", "custom_rich_text", "/custom/rich_text/rich_text.gui_script"))

	self.lobby_grid:add(get_title(self, "System"))
	self.lobby_grid:add(get_button_disabled(self, "Styles"))
	self.lobby_grid:add(get_button(self, "Whitelist / Blacklist", "system_whitelist_blacklist", "/system/whitelist_blacklist/whitelist_blacklist.gui_script"))
	self.lobby_grid:add(get_button_disabled(self, "Component interests"))
	self.lobby_grid:add(get_button_disabled(self, "Nested Druids"))
	self.lobby_grid:add(get_button(self, "Message input", "system_message_input", "/system/message_input/message_input.gui_script"))
	self.lobby_grid:add(get_button_disabled(self, "Input priority"))
	self.lobby_grid:add(get_button(self, "Inner templates", "system_inner_templates", "/system/inner_templates/inner_templates.gui_script"))
	self.lobby_grid:add(get_button(self, "Late init check", "system_late_init_check", "/system/late_init_check/late_init_check.gui_script"))
end


local function check_url(self)
	if not html5 then
		return
	end

	local example_arg = html5.run("new URLSearchParams(window.location.search).get('example')")
	if example_arg and self.scene_names[example_arg] then
		print("Start example: ", example_arg)
		show_scene(self, example_arg, self.scene_names[example_arg] or "unknown")
		return true
	end
end


local function check_cache(self)
	local scroll_position = self.cache.scroll_position
	if scroll_position then
		self.lobby_scroll:scroll_to_percent(vmath.vector3(0, scroll_position, 0), true)
	end

	local last_scene = self.cache.last_scene
	if last_scene then
		show_scene(self, last_scene, self.scene_names[last_scene] or "unknown")
		return true
	end
end


local function check_loading(self)
	if check_url(self) then
		return
	end

	if check_cache(self) then
		return
	end
end


local function register_druid_extended_components(self)
	druid.register("checkbox", checkbox)
	druid.register("checkbox_group", checkbox_group)
	druid.register("dynamic_grid", dynamic_grid)
	druid.register("input", input)
	druid.register("lang_text", lang_text)
	druid.register("progress", progress)
	druid.register("radio_group", radio_group)
	druid.register("slider", slider)
	druid.register("timer", timer_component)
	druid.register("data_list", data_list)
end



function init(self)
	-- Main lobby have more render priority (top panel)
	gui.set_render_order(10)

	window.set_listener(on_window_callback)
	druid.set_default_style(default_style)
	register_druid_extended_components(self)
	self.druid = druid.new(self)
	self.cache = sys.load(cache_path) or {}

	init_top_panel(self)
	init_lobby(self)
	self.current_script_url = ""

	timer.delay(0, false, check_loading)
end


function update(self, dt)
	self.druid:update(dt)
end


function final(self)
	self.cache.scroll_position = self.lobby_scroll:get_percent().y
	save_cache(self)

	self.druid:final()
end


function on_message(self, message_id, message, sender)
	self.druid:on_message(message_id, message, sender)
end


function on_input(self, action_id, action)
	self.druid:on_input(action_id, action)
end
