local function is_dap_buffer()
    return require("cmp_dap").is_dap_buffer()
end

return {
    {
        'saghen/blink.compat',
        lazy = true,
        opts = {},
    },
    {
        'saghen/blink.cmp',
        branch = 'v1',
        version = "1.*",
        dependencies = {
            'rafamadriz/friendly-snippets',
            'honza/vim-snippets',
            'neovim/nvim-lspconfig',
            'williamboman/mason-lspconfig.nvim',
            "rcarriga/cmp-dap",
            "mfussenegger/nvim-dap",
            'Kaiser-Yang/blink-cmp-avante',
        },
        build = 'nix run --extra-experimental-features flakes --extra-experimental-features nix-command .#build-plugin',
        keys = {
            { "<leader>n",      function() vim.diagnostic.jump({ count = 1 }) end },
            { "<leader>p",      function() vim.diagnostic.jump({ count = -1 }) end },
            { "<leader>f",      vim.lsp.buf.code_action },
            { "gd",             vim.lsp.buf.definition },
            { "gi",             vim.lsp.buf.implementation },
            { "gr",             vim.lsp.buf.references },
            { "<space><space>", vim.lsp.buf.hover },
            { "<leader>rn",     vim.lsp.buf.rename },
        },
        opts = {
            keymap = {
                ['<Tab>'] = { 'select_next', 'snippet_forward', 'fallback' },
                ['<S-Tab>'] = { 'snippet_backward', 'fallback' },
                ['<Up>'] = { 'select_prev', 'fallback' },
                ['<Down>'] = { 'select_next', 'fallback' },
                ['<C-k>'] = { 'select_prev', 'fallback' },
                ['<C-j>'] = { 'select_next', 'fallback' },
                ['<C-S-k>'] = { 'scroll_documentation_up', 'fallback' },
                ['<C-S-j>'] = { 'scroll_documentation_down', 'fallback' },
                ['<C-CR>'] = { 'accept', 'fallback' },
            },
            appearance = {
                nerd_font_variant = 'mono'
            },
            enabled = function()
                return vim.bo.buftype ~= "prompt" or is_dap_buffer()
            end,
            sources = {
                default = function(_)
                    if is_dap_buffer() then
                        return { "dap", "snippets", "buffer" }
                    else
                        return { "avante", "lsp", "path", "snippets", "buffer" }
                    end
                end,
                providers = {
                    dadbod = { name = "Dadbod", module = "vim_dadbod_completion.blink" },
                    dap = { name = "dap", module = "blink.compat.source" },
                    avante = {
                        module = 'blink-cmp-avante',
                        name = 'Avante',
                        opts = {} -- options for blink-cmp-avante
                    }
                },
            },
            completion = {
                menu = {
                    min_width = 25,
                    draw = {
                        treesitter = { 'lsp' }
                    }
                },
                documentation = {
                    auto_show_delay_ms = 0,
                },
                list = {
                    selection = { preselect = false, auto_insert = true }
                }
            },
            -- experimental signature help support
            signature = { enabled = true }
        },
        opts_extend = { "sources.default" },
        lazy = false,
        config = function(_, opts)
            require('blink.cmp').setup(opts)
            local filetypes = { "bibtex", "gitcommit", "markdown", "org", "tex", "restructuredtext", "rsweave", "latex",
                "quarto", "rmd", "context", "html", "xhtml", "typst", "mail" }
            local lsp_opts = {
                servers = {
                    basedpyright = {
                        settings = {
                            basedpyright = {
                                analysis = {
                                    typeCheckingMode = "basic",
                                    autoImportCompletions = true
                                }
                            }
                        }
                    },
                    emmet_ls = {
                        filetypes = { "css", "eruby", "html", "javascript", "javascriptreact", "less", "sass", "scss", "svelte", "pug", "typescriptreact", "vue" },
                        init_options = {
                            html = {
                                options = {
                                    ["bem.enabled"] = true,
                                },
                            },
                        }
                    },
                    clangd = {
                        cmd = {
                            "clangd",
                            "--background-index",
                            "--clang-tidy",
                            "-j=8",
                            "--clang-tidy-checks=*",
                            "--all-scopes-completion",
                            "--completion-style=bundled",
                            "--cross-file-rename",
                            "--completion-style=detailed",
                            "--header-insertion-decorators",
                            "--header-insertion=iwyu",
                            "--pch-storage=memory"
                        }
                    },
                    tinymist = {
                        offset_encoding = "utf-8",
                    },
                    lua_ls = {
                        settings = {
                            Lua = {
                                runtime = {
                                    -- Tell the language server which version of Lua you're using (most likely LuaJIT in the case of Neovim)
                                    version = 'LuaJIT',
                                },
                                diagnostics = {
                                    -- Get the language server to recognize the `vim` global
                                    globals = { 'vim', 'use', 'awesome', 'client', 'root' },
                                },
                                workspace = {
                                    -- Make the server aware of Neovim runtime files
                                    library = {
                                        ['/usr/share/nvim/runtime/lua'] = true,
                                        ['/usr/share/nvim/runtime/lua/lsp'] = true,
                                        ['/usr/share/awesome/lib'] = true
                                    }
                                },
                                -- Do not send telemetry data containing a randomized but unique identifier
                                telemetry = {
                                    enable = false,
                                },
                            },
                        },
                    },
                    ltex = {
                        on_attach = function(_, _)
                            require("ltex_extra").setup {
                                load_langs = { "nl-BE", "en-US", "en-GB" },
                                init_check = true,
                            }
                        end,
                        settings = {
                            ltex = {
                                enabled = filetypes,
                                language = "en-GB"
                            },
                        },
                        filetypes = filetypes
                    },
                    bashls = {
                        filetypes = { "sh", "bash", "zsh" },
                    },
                    texlab = {},
                    nixd = {},
                    csharp_ls = {},
                    cmake = {},
                    jsonls = {},
                    kotlin_language_server = {},
                    dockerls = {},
                    vimls = {},
                    html = {},
                    yamlls = {},
                    cssls = {},
                    jdtls = {},
                    rust_analyzer = {},
                    gopls = {},
                    ruff = {},
                    ts_ls = {},
                }
            }
            for server, config in pairs(lsp_opts.servers) do
                config.capabilities = require('blink.cmp').get_lsp_capabilities(config.capabilities)
                vim.lsp.enable(server)
                vim.lsp.config(server, config)
            end
            vim.diagnostic.config({
                virtual_text = false
            })
            vim.cmd("autocmd CursorHold,CursorHoldI * lua vim.diagnostic.open_float(nil, {focus=false})")
            vim.api.nvim_create_autocmd('LspAttach', {
                callback = function(args)
                    vim.bo[args.buf].formatexpr = nil
                end,
            })
        end
    }
}
