-- 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.

--- OpenDocument spreadsheet extractor
-- @module plugins.odfutils.ods

local odf = require("plugins.odfutils.package")

local reader = {}

--- Load one ODS workbook
-- @param filename string archive path
-- @return table|nil workbook parsed workbook
-- @return string|nil error extraction error
local function load(filename)
	local archive, document, err = odf.open(filename)
	if not archive then
		return nil, err
	end
	local archive_guard <close> = archive
	local body = odf.body(document, "office:spreadsheet")
	if not body then
		return nil, "missing OpenDocument spreadsheet body"
	end

	local sheets = {}
	for table_node in odf.children(body, "table:table") do
		sheets[#sheets + 1] = odf.parse_table(table_node)
	end
	if #sheets == 0 then
		return nil, "no sheets found"
	end

	return { sheets = sheets }
end

--- Render one ODS workbook
-- @param workbook table parsed workbook
-- @param mode string text, markdown, or tsv
-- @return string content rendered content
local function render(workbook, mode)
	local out = {}
	local show_tsv_headers = mode ~= "tsv" or #workbook.sheets > 1

	for index, sheet in ipairs(workbook.sheets) do
		if index > 1 then
			out[#out + 1] = ""
		end

		if show_tsv_headers then
			if mode == "markdown" then
				out[#out + 1] = "## " .. odf.markdown_escape(sheet.name)
			else
				out[#out + 1] = mode == "tsv" and "Sheet:\t" .. sheet.name or "Sheet: " .. sheet.name
			end
			out[#out + 1] = ""
		end

		for _, line in ipairs(odf.render_table(sheet, mode)) do
			out[#out + 1] = line
		end
	end

	return odf.finish(out)
end

--- Read one ODS file as plain text
-- @param filename string archive path
-- @return string|nil content extracted text
-- @return string|nil error extraction error
function reader.extract_text(filename)
	local workbook, err = load(filename)

	return workbook and render(workbook, "text") or nil, err
end

--- Read one ODS file as Markdown
-- @param filename string archive path
-- @return string|nil content extracted Markdown
-- @return string|nil error extraction error
function reader.extract_markdown(filename)
	local workbook, err = load(filename)

	return workbook and render(workbook, "markdown") or nil, err
end

--- Read one ODS file as TSV
-- @param filename string archive path
-- @return string|nil content extracted TSV
-- @return string|nil error extraction error
function reader.extract_tsv(filename)
	local workbook, err = load(filename)

	return workbook and render(workbook, "tsv") or nil, err
end

return reader
