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

local core = require("core")
local command = require("core.command")
local config = require("core.config")
local Doc = require("core.doc")
local hook = require("core.hook")

config.reopenlastdoc_history_size = config.reopenlastdoc_history_size or 200

local closed_doc_paths = {}

--- Return a normalized absolute path without changing its filesystem root
-- @param path string|nil raw document path
-- @return string|nil normalized_path path safe to reopen
local function normalize_path(path)
	if type(path) ~= "string" or path == "" then
		return nil
	end

	return system.normalize_path(system.absolute_path(path) or path)
end

--- Return true when the path is currently open in any existing document
-- @param path string document path
-- @return boolean open true when an open document owns the path
local function is_path_open(path)
	local target = normalize_path(path)
	if not target then
		return false
	end
	local target_key = system.path_key(target)

	for i = 1, #core.docs do
		local doc = core.docs[i]
		local filename = normalize_path(doc and doc.filename)

		if filename and system.path_key(filename) == target_key then
			return true
		end
	end
	return false
end

--- Push one closed document path and trim history to the configured limit
-- @param path string document path
local function push_closed_path(path)
	local normalized = normalize_path(path)
	if not normalized then
		return
	end
	closed_doc_paths[#closed_doc_paths + 1] = normalized
	local max_items = tonumber(config.reopenlastdoc_history_size) or 200
	max_items = math.max(1, math.floor(max_items))
	while #closed_doc_paths > max_items do
		table.remove(closed_doc_paths, 1)
	end
end

--- Pop and reopen the newest path that is not already open
-- @return boolean reopened true when a document was reopened
local function reopen_last_closed_doc()
	while #closed_doc_paths > 0 do
		local path = table.remove(closed_doc_paths)
		if not is_path_open(path) then
			local doc = Doc.open_file(path)
			if doc then
				core.workspace_view:open_doc(doc)
				return true
			end
		end
	end
	return false
end

-- Track closed docs through the core doc.close hook lifecycle
hook.add("doc.close", {
	id = "reopenlastdoc-track",
	priority = 100,
	after = function(event)
		local path = event and event.filename or nil
		if path == nil then
			return
		end
		push_closed_path(path)
	end,
})

command.register({
	["core:reopen-last-doc"] = {
		perform = function()
			return reopen_last_closed_doc()
		end,
	},
})

return true
