--- Ableton Live Set gzip extraction
-- @module format.als

local format = require("core.format")
local open_handler = require("core.open_handler")

--- Accept only gzip-backed Ableton files and keep them on the text loading path
-- @param ctx table detection context with raw source bytes
-- @return table|false detection result
local function detect_als(ctx)
	local data = ctx and ctx.data or ""

	if pack.detect(data) == "gzip" then
		return {
			action = "accept",
			force_text_open = true,
		}
	end

	return false
end

--- Open an immutable Ableton source as one editable or read-only XML document
-- @param request table shared open request with filename and complete source bytes
-- @return table|nil result generated document description
-- @return string|nil err decompression failure
local function open_als(request)
	local filename = tostring(request and request.filename or "")
	local data = request and request.data or ""

	if pack.detect(data) ~= "gzip" then
		return nil, "Ableton Live Set does not contain a gzip stream"
	end

	local xml, decompress_error = pack.gzip.decompress(data)
	if not xml then
		return nil, decompress_error or "Ableton Live Set could not be decompressed"
	end

	local base_filename = filename:match("^(.*)%.[Aa][Ll][Ss]$") or filename

	return {
		data = xml,
		filename = base_filename .. ".xml",
		source_filename = filename,
		source_read_only = true,
		is_actual_file = false,
		save_as_required = true,
		initial_word_wrap = false, -- Keep generated Ableton XML on its original wide rows
	}
end

format.register({
	name = "Ableton Live Set",
	shortname = "ALS",
	extensions = { "als" },

	-- Pattern breakdown: the three escaped bytes are the gzip signature and DEFLATE method
	headers = "^\031\139\008",
	require_file_match = true,
	detect = detect_als,
})

-- Core keeps the ordinary ALS behavior behind the same handler boundary available to plugins
open_handler.register({
	name = "als",
	priority = 0,
	formats = { "als" },
	modes = { "edit", "view", "preview" },
	actions = { "unpack" },
	open = open_als,
})
