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

--- Shared OpenDocument page extractor for presentations and drawings
-- @module plugins.odfutils.pages

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

local pages = {}

--- Collect visible page text without repeating paragraph descendants
-- @param node userdata page or notes node
-- @param out table collected blocks
local function collect_blocks(node, out)
	for child in odf.children(node) do
		local name = child:name()

		if name == "text:p" or name == "text:h" then
			local text = odf.text(child)
			if text ~= "" then
				out[#out + 1] = text
			end
		elseif name ~= "presentation:notes" then
			collect_blocks(child, out)
		end
	end
end

--- Extract pages from one presentation or drawing
-- @param filename string archive path
-- @param mode string text or markdown
-- @param body_name string qualified OpenDocument body name
-- @param page_label string visible page label
-- @param include_notes boolean whether speaker notes are included
-- @return string|nil content extracted content
-- @return string|nil error extraction error
function pages.extract(filename, mode, body_name, page_label, include_notes)
	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, body_name)
	if not body then
		return nil, "missing " .. body_name .. " body"
	end

	local out = {}
	local page_number = 0
	for page in odf.children(body, "draw:page") do
		page_number = page_number + 1
		local name = page:attribute("draw:name")
		local title = page_label .. " " .. page_number .. (name and name ~= "" and ": " .. name or "")
		out[#out + 1] = mode == "markdown" and "## " .. odf.markdown_escape(title) or title
		out[#out + 1] = ""

		local blocks = {}
		collect_blocks(page, blocks)
		for _, text in ipairs(blocks) do
			out[#out + 1] = mode == "markdown" and odf.markdown_escape(text) or text
			out[#out + 1] = ""
		end

		if mode == "markdown" then
			for _, image in ipairs(odf.images(page, filename)) do
				out[#out + 1] = image
				out[#out + 1] = ""
			end
		end

		local notes = include_notes and page:first_child("presentation:notes") or nil
		if notes then
			local note_blocks = {}
			collect_blocks(notes, note_blocks)
			if #note_blocks > 0 then
				out[#out + 1] = mode == "markdown" and "### Notes" or "Notes:"
				out[#out + 1] = ""
				for _, text in ipairs(note_blocks) do
					out[#out + 1] = mode == "markdown" and odf.markdown_escape(text) or text
					out[#out + 1] = ""
				end
			end
		end
	end

	if page_number == 0 then
		return nil, "no pages found"
	end

	return odf.finish(out)
end

return pages
