vim.o.sessionoptions="blank,buffers,curdir,folds,help,tabpages,winsize,winpos,terminal,localoptions"


vim.filetype.add({
  extension = {
    mdx = "markdown",
  }
})


-- key mapping
local keymap = vim.api.nvim_set_keymap
local opts = { noremap = true, silent = true }
local builtin = require('telescope.builtin')
  
-- comment
local esc = vim.api.nvim_replace_termcodes(
    '<ESC>', true, false, true
)
local api = require('Comment.api')

vim.keymap.set("n", "<C-_>", ":lua require('Comment.api').toggle.linewise.current()<CR> j", { remap = true })
vim.keymap.set("i", "<C-_>", "<c-o>:lua require('Comment.api').toggle.linewise.current()<CR>", { remap = true })
vim.keymap.set("x", "<C-_>", function()
    vim.api.nvim_feedkeys(esc, 'nx', false)
    api.toggle.linewise(vim.fn.visualmode())
end, { remap = true })

vim.keymap.set('n', 'gr', (function() builtin.lsp_references({jump_type="vsplit"}) end), {})
vim.keymap.set('n', 'gd', (function() builtin.lsp_definitions({jump_type="vsplit"}) end), {})
vim.keymap.set('n', 'gt', (function() builtin.lsp_type_definitions({jump_type="vsplit"}) end), {})

local barbar_state = require("barbar.state")
function find_windows_with_buffer(bufnum)
    windows = {}

    local window_list = vim.api.nvim_list_wins()

    for _, window in ipairs(window_list) do
        local win_info = vim.fn.getwininfo(window)

        if win_info ~= nil then
            for _, buf in ipairs(win_info) do
                if buf.bufnr == bufnum then
                    table.insert(windows, window)
                end
            end
        end
    end

    return windows
end

function num_useful_windows()
    local window_list = vim.api.nvim_tabpage_list_wins(0)
    local num = 0

    for _, window in ipairs(window_list) do
        local win_info = vim.fn.getwininfo(window)

        if win_info ~= nil then
            for _, win_info in ipairs(win_info) do
                if buf_is_useful(win_info.bufnr) then
                    num = num + 1
                end
            end
        end
    end

    return num
end

function buf_is_useful(bufnr)
    local bufname = vim.api.nvim_buf_get_name(bufnr)

    -- if the window's buffer has no name, it's not useful
    if bufname == '' then
        return false
    end

    -- print("bufname: ", bufname)

    -- if the window's buffer is read only, it's not useful
    local readonly = vim.api.nvim_buf_get_option(bufnr, 'readonly')
    if readonly then
        -- print("=readonly")
        return false
    end

    -- -- if the buffer is not listed, it's not useful
    local listed = vim.api.nvim_buf_get_option(bufnr, 'buflisted')
    if not listed then
        -- print("=unlisted")
        return false
    end

    local buftype = vim.api.nvim_buf_get_option(bufnr, 'buftype')
    if buftype == "quickfix" then
        -- print("=readonly")
        return false
    end

    local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
    if #lines > 1 or (#lines == 1 and #lines[1] > 0) then
        return true -- If the buffer has content, return false
    else
        return false
    end

    -- the window contains a useful buffer
    return true
end

function quit_window(window)
    vim.api.nvim_win_call(window, function() 
        vim.cmd "quit"
    end)
end

vim.api.nvim_create_user_command('CloseBuffer', function (opts)
    if num_useful_windows() > 1 then
        vim.cmd {
            cmd = "quit",
            bang = opts.bang,
        }
    else
        vim.cmd {
            cmd = "BufferDelete",
            bang = opts.bang,
        }
        if not buf_is_useful(vim.api.nvim_get_current_buf()) then
            vim.cmd {
                cmd = "quit",
                bang = opts.bang,
            }
        end
    end
end, { desc = "Close Current Buffer", bang = true, })

local function close_floating()
  for _, win in ipairs(vim.api.nvim_list_wins()) do
    local config = vim.api.nvim_win_get_config(win)
    if config.relative ~= "" then
      vim.api.nvim_win_close(win, false)
    end
  end
end

vim.keymap.set("n", "<Esc>", close_floating, { desc = "Close floats, clear highlights" })

local builtin = require('telescope.builtin')

vim.keymap.set("n", "<leader>x", require("telescope.builtin").resume, {
  noremap = true,
  silent = true,
  desc = "Resume",
})

-- local gitsigns = require('gitsigns')
-- vim.keymap.set('n', '<leader>gr', gitsigns.reset_hunk)
-- vim.keymap.set('n', '<leader>gd', gitsigns.diffthis)
-- vim.keymap.set({'o', 'x'}, 'ig', ':<C-U>Gitsigns select_hunk<CR>')


-- better search
vim.cmd([[
  " Better search
  set incsearch
  set ignorecase
  set smartcase
  set gdefault

  nnoremap <silent> n n:call BlinkNextMatch()<CR>
  nnoremap <silent> N N:call BlinkNextMatch()<CR>

  function! BlinkNextMatch() abort
    highlight JustMatched ctermfg=white ctermbg=magenta cterm=bold

    let pat = '\c\%#' . @/
    let id = matchadd('JustMatched', pat)
    redraw

    exec 'sleep 150m'
    call matchdelete(id)
    redraw
  endfunction

  nnoremap <silent> <Space> :silent noh<Bar>echo<CR>
  nnoremap <silent> <Esc> :silent noh<Bar>echo<CR>

  nnoremap <silent> n nzz
  nnoremap <silent> N Nzz
  nnoremap <silent> * *zz
  nnoremap <silent> # #zz
  nnoremap <silent> g* g*zz
]])

vim.cmd([[
  inoremap <silent> <F1> <CMD>FloatermToggle<CR>
  nnoremap <silent> <F1> <CMD>FloatermToggle<CR>
  tnoremap <silent> <F1> <C-\><C-n><CMD>FloatermToggle<CR>
]])

vim.cmd([[
    let g:suda_smart_edit = 1
    filetype plugin indent on
]])


-- multicursor
vim.g.VM_default_mappings = 1
vim.g.VM_reselect_first = 1
vim.g.VM_notify_previously_selected = 1
vim.g.VM_theme = "iceblue"



-- workaround for rust-analyzer server cancelled request
for _, method in ipairs { 'textDocument/diagnostic', 'workspace/diagnostic' } do
    local default_diagnostic_handler = vim.lsp.handlers[method]
    vim.lsp.handlers[method] = function(err, result, context, config)
        if err ~= nil and err.code == -32802 then
            return
        end
        return default_diagnostic_handler(err, result, context, config)
    end
end

require("hover").setup {
    init = function()
      require("hover.providers.lsp")
      require('hover.providers.gh')
      require('hover.providers.diagnostic')
    end,
    preview_opts = {
        border = 'rounded'
    },
    -- Whether the contents of a currently open hover window should be moved
    -- to a :h preview-window when pressing the hover keymap.
    preview_window = false,
    title = true,
}

-- Setup keymaps
vim.keymap.set("n", "K", require("hover").hover, {desc = "hover.nvim"})
vim.keymap.set("n", "gK", require("hover").hover_select, {desc = "hover.nvim (select)"})
-- vim.keymap.set("n", "<C-p>", function() require("hover").hover_switch("previous") end, {desc = "hover.nvim (previous source)"})
-- vim.keymap.set("n", "<C-n>", function() require("hover").hover_switch("next") end, {desc = "hover.nvim (next source)"})
