-- Add additional capabilities supported by nvim-cmp
local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities.textDocument.completion.completionItem.snippetSupport = true

vim.lsp.config('*', {
    capabilities = capabilities,
})

-- Enable some language servers with the additional completion capabilities
local servers = { 'lua_ls', 'pyright', 'gopls', 'clangd', 'helm_ls', 'bashls', 'angularls', 'djls' }
for _, lsp in ipairs(servers) do
    vim.lsp.enable(lsp)
end

-- HTML LSP
vim.lsp.config('html', {
    filetypes = { "html", "templ", "javascript", "css" },
    capabilities = capabilities,
    init_options = {
        configurationSection = { "html", "css", "javascript" },
        embeddedLanguages = { css = true, javascript = true },
        provideFormatter = true
    }
})
vim.lsp.enable('html')

-- CSS LSP
vim.lsp.config('cssls', {
    filetypes = { "css", "scss", "less" },
    capabilities = capabilities,
})
vim.lsp.enable('cssls')

-- TypeScript LSP
vim.lsp.config('ts_ls', {
    filetypes = { "typescript", "typescriptreact", "javascript", "javascriptreact", "html" },
    capabilities = capabilities,
})
vim.lsp.enable('ts_ls')

-- JSON LSP
vim.lsp.config('jsonls', {
    capabilities = capabilities,
})
vim.lsp.enable('jsonls')

-- Emmet LSP
vim.lsp.config('emmet_ls', {
    filetypes = { "html", "template", "javascript" },
})
vim.lsp.enable('emmet_ls')

-- YAML LSP
vim.lsp.config('yamlls', {
    capabilities = capabilities,
    settings = {
        yaml = {
            schemas = {
                kubernetes = "*.yaml",
            },
        },
    }
})
vim.lsp.enable('yamlls')


vim.api.nvim_create_autocmd({"BufRead", "BufNewFile"}, {
  pattern = "*.jenkinsfile",
  command = "set filetype=groovy"
})

-- luasnip setup
local luasnip = require('luasnip')

-- nvim-cmp setup
local cmp = require('cmp')
cmp.setup {
    snippet = {
        expand = function(args)
            luasnip.lsp_expand(args.body)
        end,
    },
    mapping = cmp.mapping.preset.insert({
        ['<C-u>'] = cmp.mapping.scroll_docs(-4), -- Up
        ['<C-d>'] = cmp.mapping.scroll_docs(4), -- Down
        -- C-b (back) C-f (forward) for snippet placeholder navigation.
        ['<C-Space>'] = cmp.mapping.complete(),
        ['<CR>'] = cmp.mapping.confirm {
            behavior = cmp.ConfirmBehavior.Replace,
            select = true,
        },
        ['<Tab>'] = cmp.mapping(function(fallback)
            if cmp.visible() then
                cmp.select_next_item()
            else
                fallback()
            end
        end, { 'i', 's' }),
        ['<S-Tab>'] = cmp.mapping(function(fallback)
            if cmp.visible() then
                cmp.select_prev_item()
            else
                fallback()
            end
        end, { 'i', 's' }),
    }),
    sources = {
        { name = 'nvim_lsp' },
        { name = 'luasnip' },
        { name = 'orgmode' },
    },
    window = {
        completion = {
            style = "minimal",
            border = "rounded",
            winhighlight = 'Normal:Normal,FloatBorder:FloatBorder,CursorLine:PmenuSel,Search:None',
        },
        documentation = {
            style = "minimal",
            border = "rounded",
            winhighlight = 'Normal:Normal,FloatBorder:FloatBorder'
        }
    },
}

vim.o.winborder = "rounded"

-- Global mappings.
-- See `:help vim.diagnostic.*` for documentation on any of the below functions
vim.keymap.set('n', '<space>e', vim.diagnostic.open_float)
vim.keymap.set('n', '[d', vim.diagnostic.goto_prev)
vim.keymap.set('n', ']d', vim.diagnostic.goto_next)
vim.keymap.set('n', '<space>q', vim.diagnostic.setloclist)
vim.api.nvim_set_keymap('i', '<c-n>', '<c-x><c-o>', { noremap = true, silent = true })

-- Use LspAttach autocommand to only map the following keys
-- after the language server attaches to the current buffer
vim.api.nvim_create_autocmd('LspAttach', {
    group = vim.api.nvim_create_augroup('UserLspConfig', {}),
    callback = function(ev)
        -- Enable completion triggered by <c-x><c-o>
        vim.bo[ev.buf].omnifunc = 'v:lua.vim.lsp.omnifunc'

        -- Buffer local mappings.
        -- See `:help vim.lsp.*` for documentation on any of the below functions
        local opts = { buffer = ev.buf }
        vim.keymap.set('n', 'gD', vim.lsp.buf.declaration, opts)
        vim.keymap.set('n', 'gd', vim.lsp.buf.definition, opts)
        vim.keymap.set('n', 'K', vim.lsp.buf.hover, opts)
        vim.keymap.set('n', 'gi', vim.lsp.buf.implementation, opts)
        vim.keymap.set('n', '<space>wa', vim.lsp.buf.add_workspace_folder, opts)
        vim.keymap.set('n', '<space>wr', vim.lsp.buf.remove_workspace_folder, opts)
        vim.keymap.set('n', '<space>wl', function()
            print(vim.inspect(vim.lsp.buf.list_workspace_folders()))
        end, opts)
        vim.keymap.set('n', '<space>D', vim.lsp.buf.type_definition, opts)
        vim.keymap.set('n', '<space>rn', vim.lsp.buf.rename, opts)
        vim.keymap.set({ 'n', 'v' }, '<space>ca', vim.lsp.buf.code_action, opts)
        vim.keymap.set('n', 'gr', vim.lsp.buf.references, opts)
        vim.keymap.set('n', '<space>f', function()
            vim.lsp.buf.format { async = true }
        end, opts)
    end,
})
