local map = require 'cartographer'

-- The general ideas behind these mappings:
--
-- * Leader prefix is the generally preferred way to map new things, however
--   only for those that affect all of vim
--
-- * Localleader prefix is used for mappings which only affect single buffers,
--   in other words mostly filetype specific mappings
--
-- many of these mapping ideas come from Tom Ryder who has them nicely
-- documented

-- backspace to switch to alternate (last) buffer
map.n.nore['<BS>'] = '<C-^>'

-- since u undoes, would it not make sense that U redoes?
map.n.nore['U'] = '<C-r>'

-- d-motion puts the last 'deleted' thing into the default register to paste;
-- use D-motion to truly delete something into nothingness and keep whatever
-- you want in your register, ready to paste
map.n.nore['D'] = '"_d'

-- I don't particularly need ex mode (at least, yet) but faster macro access
-- is nice
map.n.nore['Q'] = '@'

-- stronger versions of left,right - move all the way to beginning/end of line
map.n.nore['H'] = '^'
map.n.nore['L'] = '$'

-- when in softwrapped files, allow moving through the visible lines with j/k
-- but when prepending a number jump *exactly* as many lines, wrapped or not
-- This makes relative linenumbers much more useful in prose docs since they
-- are always exactly correct
local function wrap_up()
    if vim.v.count == 0 then return 'gk' end
    return 'k'
end

local function wrap_down()
    if vim.v.count == 0 then return 'gj' end
    return 'j'
end

map.n.nore.expr['k'] = wrap_up
map.n.nore.expr['j'] = wrap_down

-- move around between matching brackets with tab
map.n.nore['<tab>'] = '%'

-- when in insertion mode, C-u uppercases the current word, C-l lowercases it,
map.i.nore['<C-u>'] = '<esc>gUiw`]a'
map.i.nore['<C-l>'] = '<esc>guiw`]a'

-- let me save stuff as sudo when I forget to call vim with it
map.c.nore['w!!'] =
[[execute 'silent! write !sudo tee % >/dev/null' <bar> edit!]]

-- yank current filename/filepath to f buffer
map.n.nore['yp'] = ':let @p = expand("%")<Cr>'
map.n.nore['yP'] = ':let @p = expand("%:p")<Cr>'

-- repeat the last substitute command with all its flags preserved
map.n.nore['&'] = ':&&<cr>'

-- bracket pairings to go to the next/previous of:
-- (works with count prefixes)
-- Argument list
map.n.nore['[a'] = ':previous<cr>'
map.n.nore[']a'] = ':next<cr>'
-- Buffers
map.n.nore['[b'] = ':bprevious<cr>'
map.n.nore[']b'] = ':bnext<cr>'
-- Quickfix list
map.n.nore['[q'] = ':cprevious<cr>'
map.n.nore[']q'] = ':cnext<cr>'
-- Location list
map.n.nore['[l'] = ':lprevious<cr>'
map.n.nore[']l'] = ':lnext<cr>'

-- set our leader key to space since with hjkl, space is largely useless
vim.g.mapleader = " "

-- maps the leader for buffer local mappings
-- since we are (atm) using sneak to go fwd/bwd in fFtT searches, comma does
-- not do too many useful things and can be taken up as localleader
vim.g.maplocalleader = ","

-- If we mapped localleader to comma, we can still get to its original function
-- by douple-tapping it.
if vim.g.maplocalleader == ',' then
    map.nore[',,'] = ','
    map.s[',,'] = nil
end

-- remove search highlights by pressing space+/
map.n.nore['<leader>/'] = ':noh<cr>'

-- split buffers vertically/horizontally with the leader \ or - (mirrors my
-- tmux setup)
map.n.nore['<leader>-'] = ':sp<cr>'
map.n.nore['<leader>\\'] = ':vsp<cr>'
-- 'open new buffer' with leader-t (opens new buffer containing current dir and switches to it)
map.n.nore['<leader>t'] = ':vsp .<cr>'
-- open actual new tab with leader-T
map.n.nore['<leader>T'] = ':tabedit .<cr>'

-- select the whole buffer with <leader>-a
map.n.nore['<leader>a'] = 'ggVG'

-- CONFIG EDITING
-- quickly edit vimrc with leader+V
map.n.nore['<leader>V'] = ':vsp $MYVIMRC<cr>'
-- source vimrc with keystroke combination
map.n.nore['<leader>VV'] = ':source $MYVIMRC<cr>'

-- PLUGIN: Vifm.vim
-- open/close file tree with leader-e
map.n.nore['<leader>e'] = ':Vifm<cr>'
-- open current file tree with current file directory
map.n.nore['<leader>E'] = ':Vifm getcwd()<cr>'

-- PLUGIN: Telescope GLOBAL FUZZY FINDING
-- buffers and files in current workdir
map.n.nore['<leader>s'] =
[[:lua require 'telescope.builtin'.buffers(require 'telescope.themes'.get_ivy())<cr>]]
-- most recently used / MRU, bound to S since it is essentially a larger
-- go-back intention than just buffers
map.n.nore['<leader>S'] =
[[:lua require 'telescope.builtin'.oldfiles(require 'telescope.themes'.get_ivy())<cr>]]
-- fuzzy find files in cwd
map.n.nore['<leader>f'] = [[:lua require 'telescope.builtin'.find_files()<cr>]]
-- fuzzy find hidden files in cwd
map.n.nore['<leader><c-f>'] =
[[:lua require 'telescope.builtin'.find_files({hidden=true})<cr>]]
-- general full-text search in cwd with rg
map.n.nore['<leader>F'] = [[:lua require 'telescope.builtin'.live_grep()<cr>]]

-- git status
map.n.nore['<leader>gs'] = [[:lua require 'telescope.builtin'.git_status()<cr>]]
-- git buffercommits
map.n.nore['<leader>gb'] =
[[:lua require 'telescope.builtin'.git_bcommits()<cr>]]
-- git commitlog
map.n.nore['<leader>gl'] =
[[:lua require 'telescope.builtin'.git_commits()<cr>]]

-- helptags
map.n.nore['<leader><F1>'] =
[[:lua require 'telescope.builtin'.help_tags()<cr>]]
-- manpages
map.n.nore['<leader><F2>'] =
[[:lua require 'telescope.builtin'.man_pages()<cr>]]

-- colorschemes
map.n.nore['<leader><F8>'] =
[[:lua require 'telescope.builtin'.colorscheme(require 'telescope.themes'.get_ivy())<cr>]]

-- spell suggestions
map.n.nore['z='] =
[[:lua require 'telescope.builtin'.spell_suggest(require 'telescope.themes'.get_ivy())<cr>]]

-- PLUGIN: betterdigraphs
-- allow normal digraph insertion on c-k, telescope search on c-k c-k
map.i.nore['<C-k><C-k>'] = '<Cmd>lua require "betterdigraphs".digraphs("i")<CR>'

-- Note Searching
-- PLUGIN: Notational-FZF
-- set notational-fzf-vim keys for the NV window itself
vim.g.nv_fzf_binds = {
    'alt-a:select-all', 'alt-q:deselect-all', 'alt-p:toggle-preview',
    'alt-u:page-up', 'alt-d:page-down', 'ctrl-w:backward-kill-word'
}
-- FZF note full-text search with notational-velocity like functions (in wiki
-- directory)
map.n.nore['<leader>n'] = ':NV<cr>'
map.n.nore['<leader>N'] = ':NV!<cr>'

-- Mostly dealing with Prose writing from here on out
-- Format current Paragraph (esp useful in prose writing)
map.n.nore.silent['<localleader>q'] = 'gqap'
map.x.nore.silent['<localleader>q'] = 'gq'
map.n.nore.silent['<localleader>Q'] = 'vapJgqap'

-- FORMAT code with
-- PLUGIN: formatter.nvim
map.n.nore.silent['<localleader>f'] = ':FormatLock<cr>'
map.n.nore.silent['<localleader>F'] = ':FormatWriteLock<cr>'

-- Enter distraction free prose mode with F11
map.n.nore.silent['<F11>'] = ':ZenMode<cr>'

-- PLUGIN: fzf-bibtex
-- map @@ to automatically insert citation reference at cursor
map.i.nore.silent['@@'] = '<c-g>u<c-o>:CiteRef<cr>'
-- map <leader>cc to insert a complete citation at cursor

-- SPELL CHECKING
-- Spell check set to <leader>O, 'o' for 'orthography':
-- Move to the prev/next spelling error with [S ]S
-- Move to the prev/next spelling error or suggestion with [s ]s
map.n.nore['<leader>ZZ'] = ':setlocal spell! spelllang=en_us,de_de<cr>'
map.n.nore['<leader>ZE'] = ':setlocal spell! spelllang=en_us<cr>'
map.n.nore['<leader>ZG'] = ':setlocal spell! spelllang=en_us<cr>'
map.n.nore['<leader>zz'] = '1z='

-- pp to comPile a document (or file, works for some languages like go/python/c)
-- o to open the resulting document (mostly for pdfs)
-- po to comPile *and* open a doc
-- and all the same in uppercase for verbose output
map.n.nore['<leader>dp'] = ':DocCompile<cr>'
map.n.nore['<leader>dP'] = ':DocCompile!<cr>'
map.n.nore['<leader>do'] = ':DocOpen<cr>'
map.n.nore['<leader>dO'] = ':DocOpen!<cr>'

-- PLUGIN: easy-align
-- Start interactive EasyAlign in visual mode (e.g. vipga)
map.x['ga'] = '<Plug>(EasyAlign)'
-- Start interactive EasyAlign for a motion/text object (e.g. gaip)
map.n['ga'] = '<Plug>(EasyAlign)'

-- PLUGIN: Navigator.nvim
map.n.nore.silent['<c-w>h'] = "<CMD>lua require('Navigator').left()<CR>"
map.n.nore.silent['<c-w>k'] = "<CMD>lua require('Navigator').up()<CR>"
map.n.nore.silent['<c-w>l'] = "<CMD>lua require('Navigator').right()<CR>"
map.n.nore.silent['<c-w>j'] = "<CMD>lua require('Navigator').down()<CR>"
map.n.nore.silent['<c-w>p'] = "<CMD>lua require('Navigator').previous()<CR>"

-- PLUGIN: compe.nvim
-- lsp keymaps are set in lsp settings, only for lsp buffers
map.i.nore.expr.silent['<c-space>'] = 'compe#complete()'
map.i.expr['<Tab>'] =
[[vsnip#jumpable(1) ? '<Plug>(vsnip-jump-next)' : '<Tab>']]
map.i.expr['<S-Tab>'] =
[[vsnip#jumpable(-1) ? '<Plug>(vsnip-jump-next)' : '<S-Tab>']]

-- PLUGIN: symbols-outline.nvim
map.n.nore.silent['<leader>o'] = "<cmd>SymbolsOutline<cr>"

-- PLUGIN: dial-increment
map.n['<c-a>'] = '<Plug>(dial-increment)'
map.n['<c-x>'] = '<Plug>(dial-decrement)'
map.v['<c-a>'] = '<Plug>(dial-increment)'
map.v['<c-x>'] = '<Plug>(dial-decrement)'
map.v['g<c-a>'] = 'g<Plug>(dial-increment)'
map.v['g<c-x>'] = 'g<Plug>(dial-decrement)'

-- PLUGIN: zettelkasten.nvim
map.n.nore['<cr>'] = [[:silent lua require 'zettelkasten'.link_follow()<cr>]]
map.v.nore['<cr>'] = [[:lua require 'zettelkasten'.link_follow(true)<cr>]]
map.n.nore['<leader>ww'] = [[:lua require 'zettelkasten'.index_open()<cr> ]]

-- PLUGIN: toggleterm.nvim
-- create a lazygit window, set up in toggleterm settings
map.n.nore['<leader>G'] = ':Lazygit<cr>'

-- PLUGIN: slime and ipython-cell
-- send line / region, not adhering to cells
map.n['<leader>cs'] = '<Plug>SlimeLineSend'
map.x['<leader>cs'] = '<Plug>SlimeRegionSend'
-- send complete script to repl / benchmark execution
map.n.nore['<leader>cr'] = ':IPythonCellRun<cr>'
map.n.nore['<leader>cR'] = ':IPythonCellRunTime<cr>'
-- send current cell / send and go to next
map.n.nore['<leader>cc'] = ':IPythonCellExecuteCellVerbose<cr>'
map.n.nore['<leader>C'] = ':IPythonCellExecuteCellVerboseJump<cr>'
-- clear ipython repl
map.n.nore['<leader>cl'] = ':IPythonCellClear<cr>'
-- jump to previous/ next cell
map.n.nore[']c'] = ':IPythonCellNextCell<cr>'
map.n.nore['[c'] = ':IPythonCellPrevCell<cr>'
-- insert cell header above/below
map.n.nore['<leader>cO'] = ':IPythonCellInsertAbove<cr>a'
map.n.nore['<leader>co'] = ':IPythonCellInsertBelow<cr>a'
