local api = vim.api
local wk = require('which-key')

-- No one likes Esc
api.nvim_set_keymap('i', 'jk', [[<Esc>]], {noremap = true, silent = true})

-- Escape to normal mode in terminal buffer
api.nvim_set_keymap('t', '<Esc>', '<C-\\><C-n>', {noremap = true, silent = true})

-- Continuous indent
api.nvim_set_keymap('v', '<', '<gv', {noremap = true, silent = true})
api.nvim_set_keymap('v', '>', '>gv', {noremap = true, silent = true})

-- Clear search results
-- api.nvim_set_keymap('n', '<Esc>', '<Cmd>noh<CR>', {noremap = true, silent = true})

-----------------
-- Normal mode --
-----------------
wk.register({
    -- Better Y
    Y = {'y$', 'Yank to eol'},

    -- Easier start and end of line
    H = {'^', 'Start of the line'},
    L = {'$', 'End of the line'},

    -- Easier moving between windows
    -- ['<C-h>'] = {'<C-w>h', 'Go to the left window'},
    -- ['<C-l>'] = {'<C-w>l', 'Go to the right window'},
    -- ['<C-j>'] = {'<C-w>j', 'Go to the down window'},
    -- ['<C-k>'] = {'<C-w>k', 'Go to the up window'},

    -- Copy the whole buffer
    ['<C-a>'] = {'<Cmd>%y+<CR>', 'Copy whole buffer'},

    -- 'Legacy' save buffer
    -- ['<C-s>'] = {':w<CR>', 'Write buffer'},

    -- Close buffer
    ['<C-x>'] = {':bd!<CR>', 'Close buffer'},

    -- Remove trailing whitespace
    ['<A-w>'] = {':%s/\\s\\+$//e<CR>', 'Remove trailing'},

    -- Resize buffer
    ['<A-j>'] = {':resize -2<CR>', 'Resize vertical -2'},
    ['<A-k>'] = {':resize +2<CR>', 'Resize vertical +2'},
    ['<A-h>'] = {':vertical resize -2<CR>', 'Resize horizontal -2'},
    ['<A-l>'] = {':vertical resize +2<CR>', 'Resize horizontal +2'},

    -- Switch between tabs and spaces
    ['<A-t>'] = {
        function()
            if vim.o.expandtab == true then
                vim.cmd('set noexpandtab nosmarttab softtabstop& shiftwidth&')
                vim.cmd('echomsg "Switched to indent with tabs"')
            else
                vim.opt.expandtab = true
                vim.opt.smarttab = true
                vim.opt.softtabstop = 4
                vim.opt.shiftwidth = 4
                vim.cmd('echomsg "Switched to indent with 4 spaces"')
            end
        end,
        'Switch indent style'
    },

    -- Naming common keys
    ['['] = {
        name = 'Block motions (previous)',
        d = 'Previous diagnostics',
        g = 'Previous git hunk'
    },
    [']'] = {
        name = 'Block motions (next)',
        d = 'Next diagnostics',
        g = 'Next git hunk'
    },
    g = {
        name = 'Goto motions',
        d = 'Go to definition',
        D = 'Go to declaration',
        i = 'Go to implementation',
        r = 'Go to references',
        R = {'<Cmd>TroubleToggle lsp_references<CR>', 'Reference list'}
    },
    K = {name = 'Hover'},
    z = {name = 'Misc utils'},

    -- Move between tabs
    ['<TAB>'] = {'<Cmd>BufferLineCycleNext<CR>', 'Next buffer'},
    ['<S-TAB>'] = {'<Cmd>BufferLineCyclePrev<CR>', 'Previous buffer'},

    -- NvimTree
    ['<C-n>'] = {':NvimTreeToggle<CR>', 'NvimTree'},

    -- ToggleTerm
    ['<C-\\>'] = {':ToggleTerm<CR>', 'Toggle terminal'},

    -- hop.nvim
    s = {':HopWord<CR>', 'Hop to word'},
    S = {':HopChar1<CR>', 'Hop to character'},
    ['<A-s>'] = {':HopPattern<CR>', 'Hop to pattern'}
})

-----------------------------------
-- Normal mode (with leader key) --
-----------------------------------
wk.register({
    b = {
        name = 'Buffer',
        c = {':ColorizerToggle<CR>', 'Colorizer'},
        d = {':bdelete<CR>', 'Close buffer'},
        j = {':BufferLineCyclePrev<CR>', 'Previous buffer'},
        k = {':BufferLineCycleNext<CR>', 'Next buffer'},
        n = {':DashboardNewFile<CR>', 'New file'},
        z = {':ZenMode<CR>', 'Zen mode'}
    },

    -- Telescope
    f = {
        name = 'Telescope',
        a = {':Telescope autocommands<CR>', 'Autocommands'},
        b = {':Telescope buffers<CR>', 'Buffers'},
        c = {':Telescope commands<CR>', 'Commands'},
        e = {':Telescope file_browser<CR>', 'File browser'},
        f = {':Telescope find_files<CR>', 'Find files'},
        g = {':Telescope live_grep<CR>', 'Live grep'},
        h = {':Telescope help_tags<CR>', 'Help tags'},
        i = {':Telescope highlights<CR>', 'Highlight groups'},
        j = {':Telescope symbols<CR>', 'Pick emojis'},
        k = {':Telescope keymaps<CR>', 'Normal keymaps'},
        m = {':Telescope marks<CR>', 'Bookmarks'},
        n = {':Telescope man_pages<CR>', 'Man pages'},
        o = {':Telescope oldfiles<CR>', 'Recent files'},
        p = {':Telescope project display_type=full<CR>', 'Projects'},
        r = {':Telescope reloader<CR>', 'Reload lua modules'},
        s = {':Telescope treesitter<CR>', 'Treesitter'},
        t = {':Telescope<CR>', 'Telescope'},
        u = {':Telescope current_buffer_fuzzy_find<CR>', 'Search current buffer'},
        v = {':Telescope vim_options<CR>', 'Vim options'},
        y = {':Telescope filetypes<CR>', 'Filetypes'},
        z = {':Telescope registers<CR>', 'Vim registers'}
    },

    -- Git
    g = {
        name = 'Git',
        b = 'Blame current line',
        p = 'Preview hunk',
        r = 'Reset hunk',
        R = 'Reset all hunks in buffer',
        s = 'Stage hunk',
        u = 'Undo hunk',
        n = {':Neogit<CR>', 'Neogit'},
        f = {
            name = 'Telescope',
            a = {':Telescope git_stash<CR>', 'Stash'},
            b = {':Telescope git_bcommits<CR>', 'Buffer commits'},
            c = {':Telescope git_commits<CR>', 'Commits'},
            m = {':Telescope git_branches<CR>', 'Branches'},
            s = {':Telescope git_status<CR>', 'Status'}
        }
    },

    -- translate-shell.vim
    j = {
        name = 'Translate',
        t = {':Trans<CR>', 'Translate'},
        d = {':TransSelectDirection<CR>', 'Translate with direction'},
        r = {'cw<C-R>=system(\'trans -brief -no-ansi\', getreg(""))[:-2]<CR>', 'Translate and replace'},
        c = {'cw<C-R>=system(\'trans -brief -no-ansi :\', getreg(""))[:-2]<S-Left><S-Left><Right>', 'Translate and replace with direction'}
    },

    l = {
        name = 'LSP',
        a = 'Add workspace folder',
        d = 'Type definition',
        e = 'Line diagnostics',
        l = 'Set diagnostics loclist',
        n = 'Rename in buffer',
        o = 'Format buffer',
        r = 'Remove workspace folder',
        s = 'Signature help',
        w = 'List workspace folders',
        f = {
            name = 'Telescope',
            a = {':Telescope lsp_code_actions<CR>', 'Code actions'},
            A = {':Telescope lsp_range_code_actions<CR>', 'Range code actions'},
            d = {':Telescope lsp_document_diagnostics<CR>', 'Buffer diagnostics'},
            D = {':Telescope lsp_workspace_diagnostics<CR>', 'Workspace diagnostics'},
            e = {':Telescope lsp_dynamic_workspace_symbols<CR>', 'Dynamic workspace symbols'},
            i = {':Telescope lsp_implementations<CR>', 'Implementations'},
            n = {':Telescope lsp_definitions<CR>', 'Definitions'},
            r = {':Telescope lsp_references<CR>', 'References'},
            s = {':Telescope lsp_document_symbols<CR>', 'Buffer symbols'},
            S = {':Telescope lsp_workspace_symbols<CR>', 'Workspace symbols'}
        },
        g = {':SymbolsOutline<CR>', 'Symbol outline'},
        D = {'<Cmd>TroubleToggle lsp_definitions<CR>', 'Definition list'},
        E = {'<Cmd>TroubleToggle lsp_document_diagnostics<CR>', 'Document diagnostics list'},
        W = {'<Cmd>TroubleToggle lsp_workspace_diagnostics<CR>', 'Workspace diagnostics list'},
        L = {'<Cmd>TroubleToggle loclist<CR>', 'Location list items'},
        Q = {'<Cmd>TroubleToggle quickfix<CR>', 'Quickfix list'}
    },

    n = {':NnnPicker %:p:h<CR>', 'File picker'},

    -- Tab related
    t = {
        name = 'Tab',
        c = {'<Cmd>tabclose<CR>', 'Close tab'},
        j = {'<Cmd>tabprev<CR>', 'Previous tab'},
        k = {'<Cmd>tabnext<CR>', 'Next tab'},
        n = {'<Cmd>tabnew<CR>', 'New tab'}
    }
}, {prefix = '<leader>'})

-----------------------------------
-- Visual mode (with leader key) --
-----------------------------------
wk.register({
    -- GitSigns
    g = {
        name = 'Git',
        r = 'Reset hunk',
        s = 'Stage hunk'
    },

    -- translate-shell.vim
    j = {
        name = 'Translate',
        t = {':Trans<CR>', 'Translate'},
        d = {':TransSelectDirection<CR>', 'Translate with direction'},
        r = {'c<C-R>=system(\'trans -brief -no-ansi\', getreg(""))[:-2]<CR>', 'Translate and replace'},
        c = {'c<C-R>=system(\'trans -brief -no-ansi :\', getreg(""))[:-2]<S-Left><S-Left><Right>', 'Translate and replace with direction'}
    }
}, {mode = 'v', prefix = '<leader>'})

------------------------
-- Filetype specified --
------------------------
vim.cmd(([[
autocmd FileType org lua whichkeyOrg()
autocmd FileType markdown lua whichkeyMarkdown()
autocmd FileType html lua whichkeyHtml()
]]))

_G.whichkeyOrg = function()
    wk.register({
        ['<leader>o'] = {
            name = 'Org',
            a = 'Agenda',
            A = 'Toggle ARCHIVE',
            c = 'Capture',
            e = 'Export',
            i = {
                name = 'Insert',
                h = 'Add headline',
                t = 'Add TODO heading and content',
                T = 'Add TODO heading',
            },
            J = 'Move subtree down',
            K = 'Move subtree up',
            o = 'Open at point',
            r = 'Refile',
            t = 'Set tags',
            ['$'] = 'Archive current headline'
        },
        ['<leader><CR>'] = 'Org meta return',
        ['<C-a>'] = 'Org increase date',
        ['<C-x>'] = 'Org decrease date',
        ['cid'] = 'Org change date',
        ['cit'] = 'Org TODO',
        ['ciT'] = 'Org TODO prev',
        ['<C-Space>'] = 'Org toggle checkbox',
        ['<TAB>'] = 'Org cycle folding',
        ['<S-TAB>'] = 'Org cycle global folding',
        ['<<'] = 'Org promote headline',
        ['>>'] = 'Org demote headline',
        ['<s'] = 'Org prmote subtree',
        ['>s'] = 'Org demote subtree',
        ['}'] = 'Org next visible heading',
        ['{'] = 'Org previous visible heading',
        [']]'] = 'Org forward heading',
        ['[['] = 'Org backward heading',
        ['g{'] = 'Org parent heading',
        ['?'] = 'Org help'
    })
end

_G.whichkeyMarkdown = function()
    wk.register({
        ['<leader>bp'] = {':MarkdownPreviewToggle<CR>', 'Preview markdown'}
    })
end

_G.whichkeyHtml = function()
    wk.register({
        ['<leader>bp'] = {':Bracey<CR>', 'Preview html'}
    })
end
