vim.opt.completeopt = "menuone,noselect"

local cmp_status_ok, cmp = pcall(require, "cmp")
if not cmp_status_ok then
    return
end

local snip_status_ok, luasnip = pcall(require, "luasnip")
if not snip_status_ok then
    return
end

local buffer_fts = {
    "markdown",
    "toml",
    "yaml",
    "json",
}

local icons = {
    Text          = ' ',
    Method        = ' ',
    Function      = ' ',
    Constructor   = ' ',
    Field         = '識',
    Variable      = '𝑋 ',
    Class         = ' ',
    Interface     = ' ',
    Module        = ' ',
    Property      = ' ',
    Unit          = ' ',
    Value         = ' ',
    Enum          = ' ',
    Keyword       = ' ',
    Snippet       = '﬌ ',
    Color         = ' ',
    File          = ' ',
    Reference     = ' ',
    Folder        = ' ',
    EnumMember    = ' ',
    Constant      = ' ',
    Struct        = ' ',
    Event         = ' ',
    Operator      = 'ﬦ',
    TypeParameter = ' ',
}

local function contains(t, value)
    for _, v in pairs(t) do
        if v == value then
            return true
        end
    end
    return false
end

local compare = require "cmp.config.compare"

require("luasnip/loaders/from_vscode").lazy_load()

-- local check_backspace = function()
--   local col = vim.fn.col "." - 1
--   return col == 0 or vim.fn.getline("."):sub(col, col):match "%s"
-- end

local check_backspace = function()
    local line, col = unpack(vim.api.nvim_win_get_cursor(0))
    return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match "%s" == nil
end

vim.g.cmp_active = true

cmp.setup {
    enabled = function()
        local buftype = vim.api.nvim_buf_get_option(0, "buftype")
        if buftype == "prompt" then
            return false
        end
        return vim.g.cmp_active
    end,
    preselect = cmp.PreselectMode.None,
    snippet = {
        expand = function(args)
            luasnip.lsp_expand(args.body) -- For `luasnip` users.
        end,
    },
    mapping = cmp.mapping.preset.insert {
        ["<C-Space>"] = cmp.mapping(cmp.mapping.complete(), { "i", "c" }),
        ["<CR>"] = cmp.mapping.confirm { select = false },
        ["<Right>"] = cmp.mapping.confirm { select = true },
        ["<Tab>"] = cmp.mapping(function(fallback)
            if cmp.visible() then
                cmp.select_next_item()
            elseif luasnip.jumpable(1) then
                luasnip.jump(1)
            elseif luasnip.expand_or_jumpable() then
                luasnip.expand_or_jump()
            elseif luasnip.expandable() then
                luasnip.expand()
            elseif check_backspace() then
                -- cmp.complete()
                fallback()
            else
                fallback()
            end
        end, {
            "i",
            "s",
        }),
        ["<S-Tab>"] = cmp.mapping(function(fallback)
            if cmp.visible() then
                cmp.select_prev_item()
            elseif luasnip.jumpable(-1) then
                luasnip.jump(-1)
            else
                fallback()
            end
        end, {
            "i",
            "s",
        }),
    },
    -- formatting = {
    -- 	fields = { "kind", "abbr", "menu" },
    -- 	format = function(entry, vim_item)
    -- 		-- Kind icons
    -- 		vim_item.kind = icons[vim_item.kind]
    --
    -- 		-- NOTE: order matters
    -- 		vim_item.menu = ({
    -- 			nvim_lsp = "",
    -- 			nvim_lua = "",
    -- 			luasnip = "",
    -- 			buffer = "",
    -- 			path = "",
    -- 			emoji = "",
    -- 		})[entry.source.name]
    -- 		return vim_item
    -- 	end,
    -- },
    formatting = {
        fields = { "abbr", "menu", "kind" },
        format = function(entry, vim_item)
            local kind = require("lspkind").cmp_format({ mode = "symbol_text", maxwidth = 50 })(entry, vim_item)
            local strings = vim.split(kind.kind, "%s", { trimempty = true })
            kind.kind = " " .. (strings[1] or "") .. " "
            kind.menu = "    (" .. (strings[2] or "") .. ")"

            return kind
        end,
    },
    sources = {
        { name = "copilot", group_index = 2 },
        {
            name = "nvim_lsp",
            filter = function(entry, ctx)
                local kind = require("cmp.types.lsp").CompletionItemKind[entry:get_kind()]
                if kind == "Snippet" and ctx.prev_context.filetype == "java" then
                    return true
                end

                if kind == "Text" then
                    return true
                end
            end,
            group_index = 2,
        },
        -- { name = 'omni', group_index = 2 },
        { name = "nvim_lua",       group_index = 2 },
        { name = "luasnip",        group_index = 2 },
        -- {
        --   name = "buffer",
        --   group_index = 2,
        --   filter = function(entry, ctx)
        --     if not contains(buffer_fts, ctx.prev_context.filetype) then
        --       return true
        --     end
        --   end,
        -- },
        { name = "path",           group_index = 2 },
        { name = "lab.quick_data", keyword_length = 4, group_index = 2 },
    },
    sorting = {
        priority_weight = 2,
        comparators = {
            -- require("copilot_cmp.comparators").prioritize,
            -- require("copilot_cmp.comparators").score,
            compare.offset,
            compare.exact,
            -- compare.scopes,
            compare.score,
            compare.recently_used,
            compare.locality,
            -- compare.kind,
            compare.sort_text,
            compare.length,
            compare.order,
        },
    },
    confirm_opts = {
        behavior = cmp.ConfirmBehavior.Replace,
        select = false,
    },
    view = {
        entries = {
            follow_cursor = true,
        }
    },
    -- window = {
    --     completion = {
    --         border = "rounded",
    --         winhighlight = "Normal:CmpMenu,CursorLine:CmpMenuSel,Search:None",
    --     },
    --     documentation = {
    --         border = "rounded",
    --         winhighlight = "Normal:CmpDoc",
    --     },
    -- },
    -- window = {
    --   documentation = true,
    --   -- documentation = {
    --   --   border = "rounded",
    --   --   winhighlight = "NormalFloat:Pmenu,NormalFloat:Pmenu,CursorLine:PmenuSel,Search:None",
    --   -- },
    --   completion = {
    --     winhighlight = "NormalFloat:Pmenu,NormalFloat:Pmenu,CursorLine:PmenuSel,Search:None",
    --   },
    --
    -- },
    -- window = {
    -- 	documentation = cmp.config.window.bordered {
    -- 		winhighlight = 'Normal:Normal,FloatBorder:FloatBorder,CursorLine:Visual,Search:None',
    -- 	},
    -- 	completion = {
    -- 		side_padding = 0,
    -- 		col_offset = -3,
    -- 	},
    -- },
}
