local lsp = require("lsp-zero")

vim.diagnostic.config { virtual_text = true }

lsp.preset({
    name = "recommended",
    set_lsp_keymaps = false,
    suggest_lsp_servers = true
})
lsp.on_attach(function(client, bufnr)
    require("lsp-format").on_attach(client, bufnr)
    local map = vim.keymap.set
    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' })

    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.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' })
end)
lsp.nvim_workspace()
-- ensure python virtualenv is determined automatically on lsp start
lsp.configure("pyright", {
    on_attach = function(client, _)
        local python_path, msg = require('util.pyenv').get_path(client.config
        .root_dir)
        vim.notify(string.format('%s\n%s', msg, python_path))
        client.config.settings.python.pythonPath = python_path
    end
})
-- set up arduino with the help of arduino.nvim plugin
lsp.configure("arduino_language_server",
    { on_new_config = require('arduino').on_new_config })
lsp.setup_nvim_cmp({
    sources = {
        { name = 'path' }, { name = 'nvim_lsp', keyword_length = 2 },
        { name = 'pandoc_references' }, { name = 'buffer', keyword_length = 3 },
        { name = 'luasnip', keyword_length = 2 }, { name = 'tmux' },
        { name = 'otter' }, { name = 'latex_symbols' }, { name = 'vCard' },
        { name = 'nvim_lua' }, { name = 'buffer' }, { name = 'spell' }
    },
    documentation = {
        max_height = 50,
        max_width = 90,
        border = 'rounded',
        col_offset = 0,
        side_padding = 1,
        winhighlight = 'Normal:Normal,FloatBorder:Normal,CursorLine:Visual,Search:None',
        zindex = 1001
    }
})
lsp.setup()

local cmp = require 'cmp'
-- `/` cmdline setup.
cmp.setup.cmdline('/', {
    mapping = cmp.mapping.preset.cmdline(),
    sources = { { name = 'buffer' } }
})
-- `:` cmdline setup.
cmp.setup.cmdline(':', {
    mapping = cmp.mapping.preset.cmdline(),
    sources = cmp.config.sources({ { name = 'path' } }, {
        { name = 'cmdline', option = { ignore_cmds = { 'Man', '!' } } }
    })
})
