local utils = require("utils")
local opts = utils.opts

local keymap = vim.keymap

keymap.set({ 'n', 'i', 'v' }, "<C-S-A-i>", function ()
    vim.show_pos()
end, opts("Show inspect"))

-- Scroll more
keymap.set({ "n", "v" }, "<C-S-e>", "4<C-e>", opts("Scroll four lines up"))
keymap.set({ "n", "v" }, "<C-S-y>", "4<C-y>", opts("Scroll four lines down"))

-- write to file (sudo if readonly)
if vim.g.vscode then
    keymap.set("n", "W", ":Write<CR>", opts("write file (vscode)"))
else
    keymap.set("n", "W", ":w!<CR>", opts("write file"))
    keymap.set("n", "<leader>W", ":lua require('utils').sudo_write()<CR>", opts("sudo write file"))
end

-- Keep selection in visual mode when indenting
keymap.set("v", "<", "<gv", opts())
keymap.set("v", ">", ">gv", opts())

-- Tabs
keymap.set("n", "<C-t>n", ":tabnew<CR>", opts("open new tab"))
keymap.set("n", "<C-t>j", ":-tabnext<CR>", opts("Go to previous tab"))
keymap.set("n", "<C-t>k", ":+tabnext<CR>", opts("Go to next tab"))
keymap.set("n", "<C-t>l", ":+tabnext<CR>", opts("Go to next tab"))
keymap.set("n", "<C-t>h", ":-tabnext<CR>", opts("Go to previous tab"))
keymap.set("n", "<C-t>0", ":1tabnext<CR>", opts("Go to previous tab"))
keymap.set("n", "<C-t>$", ":$tabnext<CR>", opts("Go to previous tab"))

-- Quit file
keymap.set("n", "Q", ":q!<CR>", opts("quit file"))

-- Duplicate line
keymap.set("n", "<leader>dd", ":t.<CR>", opts("Duplicate line"))

-- LaTeX mappings
keymap.set("n", "<leader>lc", utils.run_vim_cmd("VimtexCompile"), opts("Compile latex document")) -- Compile LaTeX file
keymap.set("n", "<leader>lv", utils.run_vim_cmd("VimtexView"), opts("View compiled latex pdf"))   -- View compiled PDF
keymap.set("n", "<leader>lq", utils.run_vim_cmd("VimtexStop"), opts("Stop Compiling document"))   -- Stop compilation

-- window navigation
keymap.set("n", "<A-h>", "<C-w>h", opts())
keymap.set("n", "<A-j>", "<C-w>j", opts())
keymap.set("n", "<A-k>", "<C-w>k", opts())
keymap.set("n", "<A-l>", "<C-w>l", opts())
keymap.set("n", "<C-S-w>", "<C-w>w", opts())

-- window resize
keymap.set("n", "<A-C-h>", ":vertical resize +2<CR>", opts("Resize horizontally right"))
keymap.set("n", "<A-C-j>", ":resize -2<CR>", opts("Resize horizontally down"))
keymap.set("n", "<A-C-k>", ":resize +2<CR>", opts("Resize horizontally up"))
keymap.set("n", "<A-C-l>", ":vertical resize -2<CR>", opts("Resize Vertically to left"))
keymap.set("n", "<leader><leader>e", ":vertical resize 40<CR>", opts("Reset sizing to default"))

-- nohlsearch
keymap.set("n", "<leader>h", ":nohlsearch<CR>", opts("remove search highlighting"))

-- run file
keymap.set("n", "<leader>r", ":!%:p<CR>", opts("run current file"))
keymap.set("n", "<leader><leader>r", ":!%:p", opts("run current file with arguments"))

-- chmod +x
keymap.set("n", "<leader><leader>x", ":!chmod +x %:p<CR>", opts("make current file executable"))

-- script setup
keymap.set(
    "n",
    "<leader>#",
    ":w<CR>:!chmod +x %:p<CR>ggO#!/bin/sh<CR><CR><Esc>:setfiletype bash<CR>",
    opts("setup sh script")
)
keymap.set(
    "n",
    "<leader><leader>#",
    ":set syntax=python<CR>:w<CR>:!chmod +x %:p<CR>ggO#!/usr/bin/env python3<CR><CR>",
    opts("setup python script")
)

-- Migrate from function to const-arrow function (js)
keymap.set("n", "<leader><leader>fs", ":%s/\\v(async )@<!function (.*) \\((.*)\\)(.*) \\{/const \\2 = (\\3)\\4 => {/g<CR>", opts("Migrate to const-arrow func (sync)"))
keymap.set("n", "<leader><leader>fa", ":%s/\\vasync function (.*) \\((.*)\\)(.*) \\{/const \\1 = async (\\2)\\3 => {/g<CR>", opts("Migrate to const-arrow func (async)"))


-- select all
keymap.set("n", "<leader>a", "ggVG", opts("select all"))

-- move cursor in insert mode
keymap.set("i", "<C-h>", "<Left>", opts())
keymap.set("i", "<C-j>", "<Down>", opts())
keymap.set("i", "<C-k>", "<Up>", opts())
keymap.set("i", "<C-l>", "<Right>", opts())
keymap.set("i", "<C-b>", "<C-Left>", opts("Jump back by word"))
keymap.set("i", "<C-e>", "<C-Right>", opts("Jump back by word"))
keymap.set("i", "<C-$>", "<End>", opts("Jump to EOL"))
keymap.set("i", "<C-0>", "<Home>", opts("Jump to beginning of line"))

-- Spell checking
keymap.set("n", "<leader>ss", ":set spell<CR>", opts("Start built-in spell checker"))
keymap.set("n", "<leader>sn", ":set nospell<CR>", opts("Stop spell checker"))
keymap.set("n", "<leader>slu", ":set spelllang=en_us<CR>", opts("Set spell checker lang to en_US"))
keymap.set("n", "<leader>sle", ":set spelllang=en_gb<CR>", opts("Set spell checker lang to en_GB"))
keymap.set("n", "<leader>slc", ":set spelllang=de_ch<CR>", opts("Set spell checker lang to de_CH"))

-- deleting doesn't yank except when used with <leader>
keymap.set({ "n", "v" }, "d", '"_d', opts())
keymap.set({ "n", "v" }, "D", '"_D', opts())
keymap.set({ "n", "v" }, "x", '"_x', opts())
keymap.set({ "n", "v" }, "X", '"_X', opts())
keymap.set({ "n", "v" }, "c", '"_c', opts())
keymap.set({ "n", "v" }, "C", '"_C', opts())
keymap.set({ "n", "v" }, "<leader>d", "d", opts("yank and delete"))
keymap.set({ "n", "v" }, "<leader>D", "D", opts("YANK and DELETE to end"))

-- <leader> + yank/paste/delete with system clipboard
keymap.set({ "n", "v" }, "<leader>y", '"+y', opts("yank to system clipboard"))
keymap.set({ "n", "v" }, "<leader>Y", '"+y$', opts("YANK to system clipboard"))
keymap.set({ "n", "v" }, "<leader>p", '"+p', opts("paste from system clipboard"))
keymap.set({ "n", "v" }, "<leader>P", '"+P', opts("PASTE from system clipboard"))
keymap.set({ "n", "v" }, "<leader><leader>d", '"+d', opts("yank to system clipboard and delete"))
keymap.set({ "n", "v" }, "<leader><leader>D", '"+D', opts("YANK to system clipboard and DELETE"))

-- Toggle relative line numbers
keymap.set(
    "n",
    "<leader>.",
    ":lua vim.wo.relativenumber = not vim.wo.relativenumber<CR>",
    opts("Toggle relative line numbers")
)
