-- lx-bundle:true

--- Optional editor commands for encoding and decoding HTML character references
-- @module plugins.htmlentities

local core = require("core")
local command = require("core.command")

--- Show one HTML command result or error
-- @param message string notice text
local function notify(message)
	if core.status_view and core.status_view.show_notice then
		core.status_view:show_notice("html: " .. message)
	else
		core.log("html: %s", message)
	end
end

--- Transform the active selection or current logical line
-- @param doc table text document
-- @param transform function transformation function
local function transform_doc(doc, transform)
	if not doc then
		return
	end
	if doc:has_selection() then
		doc:replace(function(text)
			local out, err = transform(text)
			if not out then
				notify(err or "operation failed")
				return text
			end
			return out
		end)
		return
	end

	local line, col = doc:get_selection()
	local logical, had_lf = doc:get_logical_line(line)
	local out, err = transform(logical)
	if not out then
		notify(err or "operation failed")
		return
	end
	local end_col = #logical + 1
	if had_lf then
		end_col = end_col + 1
	end
	doc:replace_range(line, 1, line, end_col, function()
		return out
	end)
	doc:set_selection(line, math.min(col, #out + 1))
end

command.register({
	["html:encode"] = {
		requires = { "doc", "edit" },
		perform = function()
			-- Build the generated entity map only when an encode command needs it
			local html_encode = require("core.lib.html_encode")
			local doc = core.active_view and core.active_view.doc
			transform_doc(doc, function(text)
			return html_encode.encode_basic(text), nil
			end)
		end,
	},
	["html:encode-full"] = {
		requires = { "doc", "edit" },
		perform = function()
			-- Reuse the generated entity map after its first requested load
			local html_encode = require("core.lib.html_encode")
			local doc = core.active_view and core.active_view.doc
			transform_doc(doc, function(text)
			return html_encode.encode_full(text), nil
			end)
		end,
	},
	["html:decode"] = {
		requires = { "doc", "edit" },
		perform = function()
			-- Build the generated decode map only when decoding is requested
			local html_decode = require("core.lib.html_decode")
			local doc = core.active_view and core.active_view.doc
			transform_doc(doc, function(text)
			return html_decode.decode(text)
			end)
		end,
	},
})
