-- Start quarto session
local startsession = function(file, args)
    file = file or "/tmp/jupyter-magma-session.json"
    if args then file = args[0] end
    vim.fn.jobstart({ "jupyter", "console", "-f", file }, {
        on_stdout = function(_)
            vim.cmd("MagmaInit " .. file)
            vim.cmd("JupyterAttach " .. file)
        end,
        on_exit = function(_)
            vim.notify(string.format("jupyter kernel stopped: %s", file), vim.log.levels.INFO)
        end,
        stdin = nil
    })
end
vim.api.nvim_create_user_command("JupyterStart", function() startsession() end,
    {})

local map = vim.keymap.set
-- filetype mappings
-- PLUGIN: magma-nvim
-- Operate jupyter notebooks from within vim
map('n', '<localleader>cc', ':MagmaEvaluateLine<cr>', { silent = true })
map('n', '<localleader>C', '?^```{<cr>jV/```<cr>k:<C-u>MagmaEvaluateVisual<cr>',
    { silent = true, desc = 'Evaluate current code cell' })
map('x', '<localleader>c', ':<C-u>MagmaEvaluateVisual<cr>', { silent = true })
map('n', '<localleader>c', "nvim_exec('MagmaEvaluateOperator', v:true)",
    { expr = true, silent = true, desc = '+code-evaluation' })
map('n', '<localleader>cr', ':MagmaReevaluateCell<cr>', { silent = true })
map('n', '<localleader>cu', ':MagmaShowOutput<cr>', { silent = true })
map('n', '<localleader>cU', ':noautocmd :MagmaEnterOutput<cr>',
    { silent = true, desc = 'MagmaEnterOutput' })
map('n', '<localleader>cd', ':MagmaDelete<cr>', { silent = true })
map('n', '<localleader>cs', ':MagmaInterrupt<cr>')
map('n', '<localleader>ci', ':MagmaInit ')
map('n', '<localleader>cD', ':MagmaDeinit<cr>')
map('n', '<localleader>cR', ':MagmaRestart<cr>')

-- jump to beginning of previous/ next cell code
map('n', ']c', '/^```{<cr>}:nohl<cr>', { desc = 'Next quarto cell' })
map('n', '[c', '?^```<cr>n}:nohl<cr>', { desc = 'Previous quarto cell' })
-- insert cell header above/below
map('n', '<localleader>co', 'o```{python}<cr><cr>```<esc>k',
    { desc = 'Insert quarto cell below' })
map('n', '<localleader>cO', 'O```{python}<cr><cr>```<esc>k',
    { desc = 'Insert quarto cell above' })

local bufnr = 0
map('n', '[d', '<cmd>lua vim.diagnostic.goto_prev()<cr>',
    { buffer = bufnr, desc = 'Previous diagnostic' })
map('n', ']d', '<cmd>lua vim.diagnostic.goto_next()<cr>',
    { buffer = bufnr, desc = 'Next diagnostic' })
map('n', '[e',
    '<cmd>lua vim.diagnostic.goto_prev({severity = vim.diagnostic.severity.ERROR})<cr>',
    { buffer = bufnr, desc = 'Previous error' })
map('n', ']e',
    '<cmd>lua vim.diagnostic.goto_next({severity = vim.diagnostic.severity.ERROR})<cr>',
    { buffer = bufnr, desc = 'Next error' })

-- TODO find better way to enable lsp key mappings for quarto buffers
local prefix = require('which-key').register
prefix({ ['<localleader>l'] = { name = "+lsp" } })
map('n', '<localleader>li', '<cmd>LspInfo<cr>',
    { buffer = bufnr, desc = 'Lsp Info' })
map('n', '<localleader>ld', '<cmd>lua vim.diagnostic.open_float()<cr>',
    { buffer = bufnr, desc = 'Line diagnostics' })
map('n', '<localleader>la', '<cmd>lua vim.lsp.buf.code_action()<cr>',
    { buffer = bufnr, desc = 'Codeactions' })
map('n', '<localleader>ln', '<cmd>lua vim.lsp.buf.rename()<cr>',
    { buffer = bufnr, desc = 'Rename element' })
map('n', '<localleader>lr', '<cmd>lua vim.lsp.buf.references()<cr>',
    { buffer = bufnr, desc = 'References' })
if client and client.server_capabilities.document_formatting then
    map('n', '<localleader>lf', "<cmd>lua vim.lsp.buf.formatting()<CR>",
        { buffer = bufnr, desc = 'Format document' })
end

map('n', 'K', '<cmd>lua vim.lsp.buf.hover()<cr>',
    { buffer = bufnr, desc = 'Hover definition' })
map('n', 'gd', '<cmd>lua vim.lsp.buf.definition()<cr>',
    { buffer = bufnr, desc = 'Definition' })
map('n', 'gD', '<cmd>lua vim.lsp.buf.declaration()<cr>',
    { buffer = bufnr, desc = 'Declaration' })
map('n', 'gs', '<cmd>lua vim.lsp.buf.signature_help()<cr>',
    { buffer = bufnr, desc = 'Signature help' })
map('n', 'gI', '<cmd>lua vim.lsp.buf.implementation()<cr>',
    { buffer = bufnr, desc = 'Implementation' })
map('n', 'gt', '<cmd>lua vim.lsp.buf.type_definition()<cr>',
    { buffer = bufnr, desc = 'Type definition' })

if vim.b['sessionfile'] == nil then
    vim.b['sessionfile'] = vim.fn.tempname() .. '.json'
    startsession(vim.b['sessionfile'])
end
