-- lx-bundle:true

-- This file is part of Lx, created by Liqube <www.liqube.com>
-- Copyright Liqube Audio. All rights reserved.
-- Lx Interim License. See LICENSE for details.

--- Ask how recognized binary Office files should open
-- @module plugins.officeopen

local open_handler = require("core.open_handler")

local OfficeOpenView

--- Load the Office choice view only when an Office file needs it
-- @return table view_class
local function get_office_view()
	if not OfficeOpenView then
		OfficeOpenView = require("plugins.officeopen.view")
	end

	return OfficeOpenView
end

--- Return whether one Office request should show the opening choice
-- Explicit and configured handler choices apply regardless of where the file came from
-- @param request table shared open request
-- @return boolean supported
local function should_offer_office_choice(request)
	local doc = request and request.doc
	local opts = request and request.options or {}

	-- Classification has no document yet, but declarations already verified the Office format
	if not doc then
		return request and request.action == "extract"
	end

	if doc.is_binary_placeholder ~= true
		or doc.office_open_choice_finished == true
		or not get_office_view().supports(doc)
	then
		return false
	end

	if request.action == "extract" then
		return true
	end

	local requested_handler = type(request.handler) == "string" and request.handler:lower() or nil
	local configured_handler = open_handler.get_configured_name(request.format)

	if requested_handler == "office" or configured_handler == "office" then
		return true
	end

	local outside_open = opts.open_origin == "external" or opts.open_origin == "drop"

	return outside_open and opts.open_mode == nil
end

--- Create the existing Office choice view for one accepted request
-- @param request table shared open request
-- @return table view
local function create_office_choice(request)
	local options = {}

	for name, value in pairs(request.options or {}) do
		options[name] = value
	end

	local requested_options = request.options or {}
	local result_handler = requested_options.open_handler
	result_handler = type(result_handler) == "string" and result_handler:lower() or nil

	-- Only explicit choices cross the action; result-format settings resolve on the generated document
	options.result_open_mode = requested_options.open_mode
	options.result_open_handler = result_handler ~= "office" and result_handler or nil
	options.result_format_name = requested_options.result_format_name

	return get_office_view()(request.doc, options)
end

--- Return whether a document or path is supported, loading the view only on demand
-- @param target table|string|nil document or source path
-- @return boolean supported
local function supports(target)
	return get_office_view().supports(target)
end

-- Office opening now participates in the same selection path as every other specialized view
open_handler.register({
	name = "office",
	formats = { "doc", "docx", "xls", "xlsx", "xlsm", "odt", "ods", "odp", "odg" },
	kinds = { "office" },
	modes = { "edit", "view", "preview" },
	actions = { "extract" },
	probe = should_offer_office_choice,
	create_view = create_office_choice,
})

return {
	supports = supports,
}
