-- lx-bundle:true

local core = require("core")

local navigate = {}

-- Jump to a 1-based line/column with bounds validation
-- Returns true on success, or false plus an error string
function navigate.jump_to_line_col(line, col, view, instant)
	view = view or core.active_view
	if not (view and view.doc) then
		return false, "No active document view"
	end

	local doc = view.doc
	if type(line) ~= "number" then
		return false, "Invalid line number"
	end
	line = math.floor(line)
	if line < 1 or line > #doc.lines then
		return false, string.format("Line out of range: %d (1-%d)", line, #doc.lines)
	end

	if col == nil then
		col = 1
	end
	if type(col) ~= "number" then
		return false, "Invalid column number"
	end
	col = math.floor(col)

	local maxcol = #doc.lines[line]
	if line == #doc.lines and doc.lines[line]:sub(-1) ~= "\n" then
		maxcol = maxcol + 1
	end
	if col < 1 or col > maxcol then
		return false, string.format("Column out of range on line %d: %d (1-%d)", line, col, maxcol)
	end

	doc:set_selection(line, col)
	view:scroll_to_line(line, false, instant)
	view:scroll_to_make_visible(line, col)
	return true
end

-- Parses 'line' or 'line:column' user input into numeric coordinates
function navigate.parse_line_col(text)
	local trimmed = text:match("^%s*(.-)%s*$")
	if trimmed == "" then
		return nil, nil, "empty"
	end

	local line, col = trimmed:match("^(%d+)%s*:%s*(%d+)$")
	if line and col then
		return tonumber(line), tonumber(col)
	end

	line = trimmed:match("^(%d+)$")
	if line then
		return tonumber(line), nil
	end

	return nil, nil, "invalid"
end

-- Build translation map used by move/select/delete command families
function navigate.get_translations(translate, doc_view_translate)
	return {
		["previous-char"] = translate.previous_char,
		["next-char"] = translate.next_char,
		["previous-word-start"] = translate.previous_word_start,
		["next-word-end"] = translate.next_word_end,
		["previous-block-start"] = translate.previous_block_start,
		["next-block-end"] = translate.next_block_end,
		["start-of-doc"] = translate.start_of_doc,
		["end-of-doc"] = translate.end_of_doc,
		["start-of-line"] = translate.start_of_line,
		["end-of-line"] = translate.end_of_line,
		["start-of-word"] = translate.start_of_word,
		["end-of-word"] = translate.end_of_word,
		["previous-line"] = doc_view_translate.previous_line,
		["next-line"] = doc_view_translate.next_line,
		["previous-page"] = doc_view_translate.previous_page,
		["next-page"] = doc_view_translate.next_page,
	}
end

return navigate
