-- Luanti
-- Copyright (C) 2018-24 rubenwardy
-- SPDX-License-Identifier: LGPL-2.1-or-later
local function get_description_hypertext(package, info, loading_error)
	-- Screenshots and description
	local hypertext = "" .. core.hypertext_escape(package.short_description) .. "\n"
	local screenshots = info and info.screenshots or {{url = package.thumbnail}}
	local winfo = core.get_window_info()
	local fs_to_px = winfo.size.x / winfo.max_formspec_size.x
	for i, ss in ipairs(screenshots) do
		local path = get_screenshot(package, ss.url, 2)
		hypertext = hypertext .. "![]() "
		if i ~= #screenshots then
			hypertext = hypertext .. "
"
		if i ~= #screenshots then
			hypertext = hypertext .. "![]() "
		end
	end
	if info then
		hypertext = hypertext .. "\n" .. info.long_description.head
		local first = true
		local function add_link_button(label, name)
			if info[name] then
				if not first then
					hypertext = hypertext .. " | "
				end
				hypertext = hypertext .. "" .. label .. ""
				info.long_description.links["link_" .. name] = info[name]
				first = false
			end
		end
		add_link_button(hgettext("Donate"), "donate_url")
		add_link_button(hgettext("Website"), "website")
		add_link_button(hgettext("Source"), "repo")
		add_link_button(hgettext("Issue Tracker"), "issue_tracker")
		add_link_button(hgettext("Translate"), "translation_url")
		add_link_button(hgettext("Forum Topic"), "forum_url")
		hypertext = hypertext .. "\n\n" .. info.long_description.body
	elseif loading_error then
		hypertext = hypertext .. "\n\n" .. hgettext("Error loading package information")
	else
		hypertext = hypertext .. "\n\n" .. hgettext("Loading...")
	end
	-- Fix the path to blank.png. This is needed for bullet indentation,
	-- and also used for screenshot spacing.
	hypertext = hypertext:gsub("
"
		end
	end
	if info then
		hypertext = hypertext .. "\n" .. info.long_description.head
		local first = true
		local function add_link_button(label, name)
			if info[name] then
				if not first then
					hypertext = hypertext .. " | "
				end
				hypertext = hypertext .. "" .. label .. ""
				info.long_description.links["link_" .. name] = info[name]
				first = false
			end
		end
		add_link_button(hgettext("Donate"), "donate_url")
		add_link_button(hgettext("Website"), "website")
		add_link_button(hgettext("Source"), "repo")
		add_link_button(hgettext("Issue Tracker"), "issue_tracker")
		add_link_button(hgettext("Translate"), "translation_url")
		add_link_button(hgettext("Forum Topic"), "forum_url")
		hypertext = hypertext .. "\n\n" .. info.long_description.body
	elseif loading_error then
		hypertext = hypertext .. "\n\n" .. hgettext("Error loading package information")
	else
		hypertext = hypertext .. "\n\n" .. hgettext("Loading...")
	end
	-- Fix the path to blank.png. This is needed for bullet indentation,
	-- and also used for screenshot spacing.
	hypertext = hypertext:gsub("![]() ",
					"
",
					"![]() ")
			hypertext = hypertext:gsub("",
					"
")
			hypertext = hypertext:gsub("",
					"![]() ")
			hypertext = hypertext:gsub("",
					"
")
			hypertext = hypertext:gsub("",
					"![]() ")
			table.insert_all(formspec, {
				"hypertext[0,0;", W, ",", tab_body_height - 0.375,
				";reviews;", core.formspec_escape(hypertext), "]",
			})
		elseif data.reviews_error then
			table.insert_all(formspec, {"label[2,2;", fgettext("Error loading reviews"), "]"} )
		else
			table.insert_all(formspec, {"label[2,2;", fgettext("Loading..."), "]"} )
		end
	else
		error("Unknown tab " .. current_tab)
	end
	formspec[#formspec + 1] = "container_end[]"
	formspec[#formspec + 1] = "container_end[]"
	return table.concat(formspec)
end
local function handle_hypertext_event(this, event, hypertext_object)
	if not (event and event:sub(1, 7) == "action:") then
		return
	end
	for i, ss in ipairs(this.data.info.screenshots) do
		if event == "action:ss_" .. i then
			core.open_url(ss.url)
			return true
		end
	end
	local base_url = core.settings:get("contentdb_url"):gsub("(%W)", "%%%1")
	for key, url in pairs(hypertext_object.links) do
		if event == "action:" .. key then
			local author, name = url:match("^" .. base_url .. "/?packages/([A-Za-z0-9 _-]+)/([a-z0-9_]+)/?$")
			if author and name then
				local package2 = contentdb.get_package_by_info(author, name)
				if package2 then
					local dlg = create_package_dialog(package2)
					dlg:set_parent(this)
					this:hide()
					dlg:show()
					return true
				end
			end
			core.open_url_dialog(url)
			return true
		end
	end
end
local function handle_submit(this, fields)
	local info = this.data.info
	local package = this.data.package
	if fields.back then
		this:delete()
		return true
	end
	if fields.open_contentdb then
		local version = core.get_version()
		local url = core.settings:get("contentdb_url") .. "/packages/" .. package.url_part ..
				"/?protocol_version=" .. core.urlencode(core.get_max_supp_proto()) ..
				"&engine_version=" .. core.urlencode(version.string)
		core.open_url(url)
		return true
	end
	if fields.install then
		install_or_update_package(this, package)
		return true
	end
	if fields.uninstall then
		local dlg = create_delete_content_dlg(package)
		dlg:set_parent(this)
		this:hide()
		dlg:show()
		return true
	end
	-- The events handled below are only valid if the package info has finished
	-- loading.
	if not info then
		return false
	end
	if fields.tabs then
		this.data.current_tab = tonumber(fields.tabs)
		return true
	end
	if handle_hypertext_event(this, fields.desc, info.long_description) or
			handle_hypertext_event(this, fields.info, info.info_hypertext) or
			(package.reviews and handle_hypertext_event(this, fields.reviews, package.reviews)) then
		return true
	end
end
local function handle_events(event)
	if event == "WindowInfoChange" then
		ui.update()
		return true
	end
	return false
end
function create_package_dialog(package)
	assert(package)
	local dlg = dialog_create("package_dialog_" .. package.id,
			get_formspec,
			handle_submit,
			handle_events)
	local data = dlg.data
	data.package = package
	data.info = nil
	data.loading = false
	data.loading_error = nil
	data.current_tab = 1
	return dlg
end
")
			table.insert_all(formspec, {
				"hypertext[0,0;", W, ",", tab_body_height - 0.375,
				";reviews;", core.formspec_escape(hypertext), "]",
			})
		elseif data.reviews_error then
			table.insert_all(formspec, {"label[2,2;", fgettext("Error loading reviews"), "]"} )
		else
			table.insert_all(formspec, {"label[2,2;", fgettext("Loading..."), "]"} )
		end
	else
		error("Unknown tab " .. current_tab)
	end
	formspec[#formspec + 1] = "container_end[]"
	formspec[#formspec + 1] = "container_end[]"
	return table.concat(formspec)
end
local function handle_hypertext_event(this, event, hypertext_object)
	if not (event and event:sub(1, 7) == "action:") then
		return
	end
	for i, ss in ipairs(this.data.info.screenshots) do
		if event == "action:ss_" .. i then
			core.open_url(ss.url)
			return true
		end
	end
	local base_url = core.settings:get("contentdb_url"):gsub("(%W)", "%%%1")
	for key, url in pairs(hypertext_object.links) do
		if event == "action:" .. key then
			local author, name = url:match("^" .. base_url .. "/?packages/([A-Za-z0-9 _-]+)/([a-z0-9_]+)/?$")
			if author and name then
				local package2 = contentdb.get_package_by_info(author, name)
				if package2 then
					local dlg = create_package_dialog(package2)
					dlg:set_parent(this)
					this:hide()
					dlg:show()
					return true
				end
			end
			core.open_url_dialog(url)
			return true
		end
	end
end
local function handle_submit(this, fields)
	local info = this.data.info
	local package = this.data.package
	if fields.back then
		this:delete()
		return true
	end
	if fields.open_contentdb then
		local version = core.get_version()
		local url = core.settings:get("contentdb_url") .. "/packages/" .. package.url_part ..
				"/?protocol_version=" .. core.urlencode(core.get_max_supp_proto()) ..
				"&engine_version=" .. core.urlencode(version.string)
		core.open_url(url)
		return true
	end
	if fields.install then
		install_or_update_package(this, package)
		return true
	end
	if fields.uninstall then
		local dlg = create_delete_content_dlg(package)
		dlg:set_parent(this)
		this:hide()
		dlg:show()
		return true
	end
	-- The events handled below are only valid if the package info has finished
	-- loading.
	if not info then
		return false
	end
	if fields.tabs then
		this.data.current_tab = tonumber(fields.tabs)
		return true
	end
	if handle_hypertext_event(this, fields.desc, info.long_description) or
			handle_hypertext_event(this, fields.info, info.info_hypertext) or
			(package.reviews and handle_hypertext_event(this, fields.reviews, package.reviews)) then
		return true
	end
end
local function handle_events(event)
	if event == "WindowInfoChange" then
		ui.update()
		return true
	end
	return false
end
function create_package_dialog(package)
	assert(package)
	local dlg = dialog_create("package_dialog_" .. package.id,
			get_formspec,
			handle_submit,
			handle_events)
	local data = dlg.data
	data.package = package
	data.info = nil
	data.loading = false
	data.loading_error = nil
	data.current_tab = 1
	return dlg
end