--------------------------------------------------------------------------------
-- Toggles
--------------------------------------------------------------------------------
-- Clear highlighted searched on pressing <Esc> in normal mode
vim.keymap.set('n', '<Esc>', '<cmd>nohlsearch<CR>', { desc = 'Hide search results' })

vim.keymap.set('n', '<leader>tn', '<cmd> set nu! <cr>', { desc = '[T]oggle line [N]umbers' })
vim.keymap.set('n', '<leader>trn', '<cmd> set rnu! <cr>', { desc = '[T]oggle [R]elative line [N]umbers' })
vim.keymap.set('n', '<leader>tw', '<cmd> set wrap! <cr>', { desc = '[T]oggle [W]rap' })
vim.keymap.set('n', '<leader>ts', '<cmd> set spell! <cr>', { desc = '[T]oggle [S]pellcheck' })
vim.keymap.set('n', '<C-s>', '<cmd>wa!<cr><cmd>wa!<cr><cmd>wa!<cr><cmd>wa!<cr>', { desc = 'Speichern um jeden Preis' })

--------------------------------------------------------------------------------
-- Movements
--------------------------------------------------------------------------------
-- make big movements up and down
vim.keymap.set({ 't', 'i', 'v', 'n' }, '<A-j>', '<C-d>', { desc = 'move a many lines up' })
vim.keymap.set({ 't', 'i', 'v', 'n' }, '<A-k>', '<C-u>', { desc = 'move a many lines down' })

-- move to end and start of lines with H and L
vim.keymap.set({ 'v', 'n' }, 'H', '<Home>', { desc = 'move to start of line' })
vim.keymap.set({ 'v', 'n' }, 'L', '<End>', { desc = 'move to end of line' })

-- make j and k move by visual lines, not actual lines
vim.keymap.set({ 'v', 'n' }, 'j', 'gj', { desc = 'move up' })
vim.keymap.set({ 'v', 'n' }, 'k', 'gk', { desc = 'move down' })

-- move+scroll
vim.keymap.set({ 'v', 'n' }, 'zk', '<C-e>', { desc = 'move and scroll up' })
vim.keymap.set({ 'v', 'n' }, 'zj', '<C-y>', { desc = 'move and scroll down' })

-- go to  beginning and end in insert mode
vim.keymap.set('i', '<C-S-h>', '<esc>^i', { desc = 'Go to the start of the line' })
vim.keymap.set('i', '<C-S-l>', '<End>', { desc = 'Go to the end of the line' })
vim.keymap.set('i', '<C-w>', '<esc>lwi', { desc = 'Go a word further' })
vim.keymap.set('i', '<C-b>', '<esc>lbi', { desc = 'Go a word backward' })
vim.keymap.set('i', '<C-e>', '<esc>lea', { desc = 'Go a to next word end' })

-- navigate hjkl in insert mode
vim.keymap.set('i', '<C-h>', '<Left>', { desc = 'Move left' })
vim.keymap.set('i', '<C-j>', '<Down>', { desc = 'Move down' })
vim.keymap.set('i', '<C-k>', '<Up>', { desc = 'Move up' })
vim.keymap.set('i', '<C-l>', '<Right>', { desc = 'Move right' })

-- move to window
--  See `:help wincmd` for a list of all window commands
vim.keymap.set('n', '<C-h>', '<C-w><C-h>', { desc = 'Move focus to the left window' })
vim.keymap.set('n', '<C-l>', '<C-w><C-l>', { desc = 'Move focus to the right window' })
vim.keymap.set('n', '<C-j>', '<C-w><C-j>', { desc = 'Move focus to the lower window' })
vim.keymap.set('n', '<C-k>', '<C-w><C-k>', { desc = 'Move focus to the upper window' })

-- diagnostics
vim.keymap.set('n', '[d', vim.diagnostic.goto_prev, { desc = 'Go to previous [D]iagnostic message' })
vim.keymap.set('n', ']d', vim.diagnostic.goto_next, { desc = 'Go to next [D]iagnostic message' })

-- let me out!!!
vim.keymap.set({ 'n', 'v' }, 'qqq', '<cmd>bnext<cr><cmd>bd #<cr>', { desc = '[Q]uit the current window' })
vim.keymap.set({ 'n', 'v' }, '<A-c>', '<cmd>bnext<cr><cmd>bd #<cr>', { desc = '[C]lose the current buffer' })

vim.keymap.set({ 'n' }, '#', "'", { desc = '[Q]uit the current window' })

--------------------------------------------------------------------------------
-- Workspace, buffer and window manipulation
--------------------------------------------------------------------------------
-- split windows
vim.keymap.set('n', '<leader>"', '<cmd>vsplit<cr>', { desc = 'Split the window vertically' })
vim.keymap.set('n', '<leader>%', '<cmd>split<cr>', { desc = 'Split the window horizontally' })
vim.keymap.set('n', '<leader>w"', '<cmd>vnew<cr>', { desc = 'Split the window vertically (new buffer)' })
vim.keymap.set('n', '<leader>w%', '<cmd>new<cr>', { desc = 'Split the window horizontally (new buffer)' })

-- window actions
vim.keymap.set('n', '<leader>wbn', '<cmd>enew<cr>', { desc = 'Open a [N]ew buffer' })
vim.keymap.set('n', '<leader>wbc', '<cmd>bw<cr>', { desc = '[C]lose current buffer' }) -- :bd would keep in background
vim.keymap.set('n', '<C-Up>', '<cmd>resize +1<cr>', { desc = 'Resize window' })
vim.keymap.set('n', '<C-Down>', '<cmd>resize -1<cr>', { desc = 'Resize window' })
vim.keymap.set('n', '<C-Left>', '<cmd>vertical resize +1<cr>', { desc = 'Resize window vertically' })
vim.keymap.set('n', '<C-Right>', '<cmd>vertical resize -1<cr>', { desc = 'Resize window vertically' })

-- tabs/workspaces
vim.keymap.set('n', '<Tab>', '<cmd>bnext<cr>', { desc = 'Next Buffer' })
vim.keymap.set('n', '<S-Tab>', '<cmd>bprev<cr>', { desc = 'Last Buffer' })
vim.keymap.set('n', '<leader>wn', '<cmd>tabnew<cr>', { desc = 'Open a [N]ew [W]orkspace/Tab' })
vim.keymap.set('n', '<leader>wc', '<cmd>tabclose<cr>', { desc = '[C]lose a [W]orkspace/Tab' })
vim.keymap.set('n', '<leader>wk', '<cmd>tabnext<cr>', { desc = 'Next [W]orkspace/Tab' })
vim.keymap.set('n', '<leader>wj', '<cmd>tabprevious<cr>', { desc = 'Last [W]orkspace/Tab' })
vim.keymap.set('n', '<leader>n', '<cmd>enew<cr>', { desc = '[N]ew Buffer' })

vim.keymap.set('t', '<C-w>', vim.api.nvim_replace_termcodes('<C-\\><C-N>', true, true, true),
	{ desc = 'Leave terminal mode' })

--------------------------------------------------------------------------------
-- Editing
--------------------------------------------------------------------------------
-- copy to system clipboard
vim.keymap.set({ 'n', 'v' }, '<leader>y', '"+y', { desc = '[Y]ank to system' })
vim.keymap.set({ 'n', 'v' }, '<leader>Y', '"+Y', { desc = '[Y]ank to system' })
vim.keymap.set({ 'n', 'v' }, '<leader>yy', '"+yy', { desc = '[Y]ank to system' })

-- paste from system clipboard
vim.keymap.set({ 'n', 'v' }, '<leader>p', '"+p', { desc = '[P]aste from system' })
vim.keymap.set({ 't', 'n', 'v' }, '<C-S-v>', '<C-w>"+pi', { desc = 'Paste the system clipboard' })

-- do not overwrite the register when pasting (kept defaults)
vim.keymap.set({ 'v' }, 'P', 'P', { desc = '[P]aste to selected' })
vim.keymap.set({ 'v' }, 'p', 'p', { desc = '[p]aste to selected and copy to register' })

-- add lines from normal and visual, without insert mode
vim.keymap.set({ 'n', 'v' }, 'OO', 'O<Esc>', { desc = 'Insert a line above' })
vim.keymap.set({ 'n', 'v' }, 'oo', 'o<Esc>', { desc = 'Insert a line below' })

-- add lines from normal and visual, with insert mode
vim.keymap.set({ 'n', 'v' }, 'O', 'O', { desc = 'Insert a line above and insert' })
vim.keymap.set({ 'n', 'v' }, 'o', 'o', { desc = 'Insert a line below and insert' })
vim.keymap.set({ 'n', 'v' }, 'Oi', 'O', { desc = 'Insert a line above and insert' })
vim.keymap.set({ 'n', 'v' }, 'oi', 'o', { desc = 'Insert a line below and insert' })

-- make current line a blank line
vim.keymap.set({ 'n', 'v' }, 'do', 'Vc<Esc>', { desc = '[D]o [O]ver / Rewrite line' })

-- substitute, normally on 's', but the leap plugin is more useful on 's'
vim.keymap.set({ 'n' }, '<leader>s', 's', { desc = '[S]ubstitute hovered text' })

-- do something useful with the arrow keys:
-- move lines up/down and change indentation
vim.keymap.set({ 'n', 'v' }, '<Up>', '<cmd> move-2<cr>', { desc = 'Move line up' })
vim.keymap.set({ 'n', 'v' }, '<Down>', '<cmd> move+1<cr>', { desc = 'Move line down' })
vim.keymap.set({ 'n', 'v' }, '<Left>', '<<', { desc = 'Less indentation' })
vim.keymap.set({ 'n', 'v' }, '<Right>', '>>', { desc = 'More indentation' })

-- format a long line into multiple with length 80
vim.keymap.set({ 'v' }, '<leader>fl', ':!fmt -w80<CR>', { desc = '[F]ormat long [L]ines into smaller ones' })

--------------------------------------------------------------------------------
-- Formating
--------------------------------------------------------------------------------
-- format the current buffer
vim.keymap.set('n', '<leader>ff', function()
	require('conform').format()
end, { desc = '[F]ormat buffer' })
vim.keymap.set('n', '<leader>fF', function()
	vim.lsp.buf.format()
end, { desc = '[F]ormat buffer (no plugin)' })
vim.keymap.set('n', '<leader>fw', function()
	require('mini.trailspace').trim()
end, { desc = '[F]ormat remove [W]hitespace' })

--------------------------------------------------------------------------------
-- Diagnostics
--------------------------------------------------------------------------------
vim.keymap.set({ 'i', 'n', 'v' }, '<S-A-k>', function()
	vim.diagnostic.open_float()
end)

--------------------------------------------------------------------------------
-- Ignore
--------------------------------------------------------------------------------
-- discard F15
vim.keymap.set({ 'i', 't', 'x', 'n', 'v' }, '<F15>', '<Nop>')
vim.keymap.set({ 'i', 't', 'x', 'n', 'v' }, '<S-F15>', '<Nop>')
vim.keymap.set({ 'i', 't', 'x', 'n', 'v' }, '<A-F15>', '<Nop>')
vim.keymap.set({ 'i', 't', 'x', 'n', 'v' }, '<C-F15>', '<Nop>')
vim.keymap.set({ 'i', 't', 'x', 'n', 'v' }, '<C-S-F15>', '<Nop>')
vim.keymap.set({ 'i', 't', 'x', 'n', 'v' }, '<C-A-F15>', '<Nop>')
vim.keymap.set({ 'i', 't', 'x', 'n', 'v' }, '<A-S-F15>', '<Nop>')
vim.keymap.set({ 'i', 't', 'x', 'n', 'v' }, '<C-A-S-F15>', '<Nop>')
