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

--- Live-context Lua scratch editor with structured results
-- @module plugins.luapad

local common = require("core.common")
local config = require("core.config")
local core = require("core")
local command = require("core.command")
local Doc = require("core.doc")
local keymap = require("core.keymap")
local dump = require("plugins.luapad.dump")
local evaluator = require("plugins.luapad.evaluator")

local luapad = {}

config.plugins.lua_pad = common.merge({
	panel_height_ratio = 0.32,
	minimum_panel_height = 120,
	minimum_editor_height = 120,
	timeout_seconds = 0.25,
	dump_max_depth = 5,
	dump_max_items = 100,
	dump_max_string_length = 1000,
	dump_max_nodes = 1000,
	dump_include_metatable = false,
}, config.plugins.lua_pad)

--- Return whether commands currently target a LuaPad editor
-- @return boolean active
local function is_active_lua_pad()
	local active_view = core.active_view

	return active_view and active_view.is_lua_pad == true or false
end

--- Open one new unsaved LuaPad in the active document pane
-- @return table view
function luapad.open()
	local LuaPadView = require("plugins.luapad.view")
	local previous_view = core.active_view
	local doc = Doc.create(nil, {
		format_name = "lua",
	})
	local ordinary_view = core.workspace_view:open_doc(doc)
	local node = core.workspace_view.root_node:get_node_for_view(ordinary_view)
	local view_index = node and node:get_view_idx(ordinary_view)
	local view = LuaPadView(doc)

	assert(node and view_index, "LuaPad could not resolve its new editor tab")

	-- Replace the temporary ordinary editor before the next frame so the tab never flashes
	node.views[view_index] = view
	node:set_active_view(view)
	-- The temporary ordinary editor was never user-visible and must not replace the real previous view
	core.last_active_view = previous_view
	core.workspace_view.root_node:update_layout()
	core.redraw = true

	return view
end

--- Dump a value into LuaPad's bounded tree model
-- @param value any source value
-- @param options table|nil dump limits
-- @return table node
function luapad.dump(value, options)
	return dump.inspect(value, options)
end

--- Evaluate source for callers that want LuaPad's captured result model
-- @param source string Lua source
-- @param options table|nil execution options
-- @return table result
function luapad.evaluate(source, options)
	return evaluator.run(source, options)
end

command.register({
	["luapad:open"] = function()
		luapad.open()
	end,
	["luapad:execute"] = {
		predicate = is_active_lua_pad,
		perform = function()
			return core.active_view:execute()
		end,
	},
})

-- LuaPad owns Ctrl+Enter only while its editor is the focused tab
keymap.bind("plugin", {
	lua_pad = {
		["ctrl+enter"] = "luapad:execute",
	},
})

return luapad
