-- Set <space> as the leader key
-- See `:help mapleader`
-- NOTE: Must happen before plugins are loaded (otherwise wrong leader will be used)
vim.g.mapleader = " "
vim.g.maplocalleader = " "

-- Disable mouse input
vim.o.mouse = ""

-- Minimal number of screen lines to keep above and below the cursor.
vim.o.scrolloff = 10

-- Highlight the line where the cursor is on
vim.o.cursorline = true

-- Column at 80 characters
vim.o.colorcolumn = "80"

-- Set default tabstop and shiftwidth
vim.o.tabstop = 4
vim.o.shiftwidth = 4
vim.o.expandtab = true

-- Show <tab> and trailing spaces
vim.o.list = true
vim.opt.listchars = { tab = "» ", trail = "·", nbsp = "␣" }

-- Configure line wrap
vim.o.linebreak = true
vim.o.breakindent = true
vim.o.showbreak = "↪ "

-- Case-insensitive searching UNLESS \C or one or more capital letters in the search term
vim.o.ignorecase = true
vim.o.smartcase = true

-- Use undofile to preserve actions over restarts
vim.o.undofile = true

-- if performing an operation that would fail due to unsaved changes in the buffer (like `:q`),
-- instead raise a dialog asking if you wish to save the current file(s) See `:help 'confirm'`
vim.o.confirm = true

-- local toggle_background = function (obj)
-- 	print(string.find(obj.stdout, "prefer-light"))
-- 	if string.find(obj.stdout, "prefer-light") then
-- 		print('light')
-- 	else
-- 		print('dark')
-- 	end
-- end
--
-- vim.o.background = 'light'
-- vim.system({"dconf", "read", "/org/gnome/desktop/interface/color-scheme"}, toggle_background)

vim.cmd.colorscheme("gruvbox")

-- [[ Set up keymaps ]] See `:h vim.keymap.set()`, `:h mapping`, `:h keycodes`

-- Use <Esc> to exit terminal mode
vim.keymap.set("t", "<A-Esc>", "<C-\\><C-n>")

-- Map <A-j>, <A-k>, <A-h>, <A-l> to navigate between windows in any modes
vim.keymap.set({ "t", "i" }, "<A-h>", "<C-\\><C-n><C-w>h")
vim.keymap.set({ "t", "i" }, "<A-j>", "<C-\\><C-n><C-w>j")
vim.keymap.set({ "t", "i" }, "<A-k>", "<C-\\><C-n><C-w>k")
vim.keymap.set({ "t", "i" }, "<A-l>", "<C-\\><C-n><C-w>l")
vim.keymap.set({ "n" }, "<A-h>", "<C-w>h")
vim.keymap.set({ "n" }, "<A-j>", "<C-w>j")
vim.keymap.set({ "n" }, "<A-k>", "<C-w>k")
vim.keymap.set({ "n" }, "<A-l>", "<C-w>l")

-- [[ Basic Autocommands ]].
-- See `:h lua-guide-autocommands`, `:h autocmd`, `:h nvim_create_autocmd()`
-- Highlight when yanking (copying) text.
-- Try it with `yap` in normal mode. See `:h vim.hl.on_yank()`
vim.api.nvim_create_autocmd("TextYankPost", {
	desc = "Highlight when yanking (copying) text",
	callback = function()
		vim.hl.on_yank()
	end,
})

-- Sync clipboard between OS and Neovim. Schedule the setting after `UiEnter` because it can
-- increase startup-time. Remove this option if you want your OS clipboard to remain independent.
-- See `:help 'clipboard'`
vim.api.nvim_create_autocmd("UIEnter", {
	callback = function()
		vim.o.clipboard = "unnamedplus"
	end,
})

-- Print the line number in front of each line
vim.o.number = true
vim.o.relativenumber = true

-- [[ Create user commands ]]
-- See `:h nvim_create_user_command()` and `:h user-commands`

-- Create a command `:GitBlameLine` that print the git blame for the current line
vim.api.nvim_create_user_command("GitBlameLine", function()
	local line_number = vim.fn.line(".") -- Get the current line number. See `:h line()`
	local filename = vim.api.nvim_buf_get_name(0)
	print(vim.fn.system({ "git", "blame", "-L", line_number .. ",+1", filename }))
end, { desc = "Print the git blame for the current line" })

-- [[ Add optional packages ]]
-- Nvim comes bundled with a set of packages that are not enabled by
-- default. You can enable any of them by using the `:packadd` command.

-- For example, to add the "nohlsearch" package to automatically turn off search highlighting after
-- 'updatetime' and when going to insert mode
vim.cmd("packadd! nohlsearch")

-- [[ Language Setup ]]

-- Treat Ipe stylesheets as xml code
vim.filetype.add({
	extension = {
		isy = "xml",
	},
})

-- Install nvim-treesitter
vim.pack.add({ "https://github.com/nvim-treesitter/nvim-treesitter" })
require("nvim-treesitter").install({ 'fish', 'java', 'latex', 'make' })

vim.api.nvim_create_autocmd('FileType', {
	pattern = { '<filetype>' },
	callback = function()
		vim.treesitter.start()
		vim.wo[0][0].foldexpr = 'v:lua.vim.treesitter.foldexpr()'
		vim.wo[0][0].foldmethod = 'expr'
	end,
})


vim.pack.add({ "https://github.com/mason-org/mason.nvim" })
local mason = require("mason").setup()

vim.lsp.enable({ 'lua_ls', 'texlab', 'clangd', 'jdtls', 'fish_lsp', 'html', 'cssls', 'lemminx' })


vim.keymap.set('n', '<leader>lf', vim.lsp.buf.format,
	{ desc = 'Formats a buffer using the attached language server clients' })
vim.keymap.set('n', '<leader>lh', vim.lsp.buf.hover,
	{ desc = 'Displays hover information about the symbol' })
vim.keymap.set('n', '<leader>lr', vim.lsp.buf.rename,
	{ desc = 'Renames all references to the symbol' })
vim.keymap.set('n', '<leader>ld', vim.lsp.buf.definition,
	{ desc = 'Jumps to the definition of the symbol' })

vim.diagnostic.config({
	signs = {
		text = {
			[vim.diagnostic.severity.ERROR] = "W ",
			[vim.diagnostic.severity.WARN] = "w ",
			[vim.diagnostic.severity.INFO] = "I ",
			[vim.diagnostic.severity.HINT] = "H ",
		},
	},
	virtual_text = true, -- Show inline diagnostics
})

vim.keymap.set("n", "<leader>dn", "]d", { desc = "Jump to next diagnostic" })
vim.keymap.set("n", "<leader>dp", "[d", { desc = "Jump to previous diagnostic" })
vim.keymap.set("n", "<leader>dN", "]D", { desc = "Jump to last diagnostic" })
vim.keymap.set("n", "<leader>dP", "[D", { desc = "Jump to first diagnostic" })
vim.keymap.set("n", "<leader>ds", "<C-w>d", { desc = "Display diagnostic on current line" })

vim.api.nvim_create_autocmd('FileType', {
	pattern = { 'c', 'cpp', 'rust' },
	callback = function()
		vim.pack.add({ "https://github.com/mfussenegger/nvim-dap", "https://github.com/theHamsta/nvim-dap-virtual-text" })
		local dap = require("dap")
		local dap_widgets = require("dap.ui.widgets")
		local dap_sidebar_s = dap_widgets.sidebar(dap_widgets.scopes)
		local dap_sidebar_f = dap_widgets.sidebar(dap_widgets.frames)

		vim.keymap.set("n", "<leader>bb", dap.toggle_breakpoint, { desc = "Toggle breakpoint" })
		vim.keymap.set("n", "<leader>bc", dap.continue, { desc = "Continue execution" })
		dap.listeners.on_session["debug"] = function()
			vim.keymap.set("n", "<leader>bs", dap_sidebar_s.toggle, { desc = "Toggle scopes" })
			vim.keymap.set("n", "<leader>bf", dap_sidebar_f.toggle, { desc = "Toggle frames" })
			vim.keymap.set("n", "<leader>br", dap.repl.toggle, { desc = "Toggle REPL" })

			vim.keymap.set("n", "<Left>", dap.step_out, { desc = "Step out" })
			vim.keymap.set("n", "<Right>", dap.step_into, { desc = "Step into" })
			vim.keymap.set("n", "<Down>", dap.step_over, { desc = "Step over" })
			vim.keymap.set("n", "<Up>", dap.restart_frame, { desc = "Restart frame" })
		end

		dap.adapters.gdb = {
			type = "executable",
			command = "gdb",
			args = { "--interpreter=dap", "--eval-command", "set print pretty on" }
		}

		dap.configurations.c = {
			{
				name = "Launch",
				type = "gdb",
				request = "launch",
				program = function()
					return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/', 'file')
				end,
				args = {}, -- provide arguments if needed
				cwd = "${workspaceFolder}",
				stopAtBeginningOfMainSubprogram = false,
			},
			{
				name = "Select and attach to process",
				type = "gdb",
				request = "attach",
				program = function()
					return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/', 'file')
				end,
				pid = function()
					local name = vim.fn.input('Executable name (filter): ')
					return require("dap.utils").pick_process({ filter = name })
				end,
				cwd = '${workspaceFolder}'
			},
			{
				name = 'Attach to gdbserver :1234',
				type = 'gdb',
				request = 'attach',
				target = 'localhost:1234',
				program = function()
					return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/', 'file')
				end,
				cwd = '${workspaceFolder}'
			}
		}

		dap.configurations.cpp = dap.configurations.c
		dap.configurations.rust = dap.configurations.c
	end,
})
--
-- [[ UI Configuration ]]
vim.pack.add({ "https://github.com/nvim-mini/mini.nvim" })

vim.o.winborder = "none"

-- Use mini.completion
require("mini.completion").setup()

local imap_expr = function(lhs, rhs)
	vim.keymap.set('i', lhs, rhs, { expr = true })
end
imap_expr('<Tab>', [[pumvisible() ? "\<C-n>" : "\<Tab>"]])
imap_expr('<S-Tab>', [[pumvisible() ? "\<C-p>" : "\<S-Tab>"]])

-- Snippet integration for mini.completion
-- require("mini.snippets").setup()

-- Icons for statusline and completion
require("mini.icons").setup()

-- Use mini.statusline instead of native showmode
require("mini.statusline").setup()
vim.o.showmode = false

-- Git integration for statusline and Command mode
require("mini.git").setup()

-- Show git diff in linenumbers
require("mini.diff").setup()

-- Use mini.notify
-- require("mini.notify").setup()

-- Use and configure mini.clue
local clue = require("mini.clue")
clue.setup({
	triggers = {
		-- Leader triggers
		{ mode = { "n", "x" }, keys = "<Leader>" },

		-- `[` and `]` keys
		{ mode = "n",          keys = "[" },
		{ mode = "n",          keys = "]" },

		-- Built-in completion
		{ mode = "i",          keys = "<C-x>" },

		-- `g` key
		{ mode = { "n", "x" }, keys = "g" },

		-- Marks
		{ mode = { "n", "x" }, keys = "'" },
		{ mode = { "n", "x" }, keys = "`" },

		-- Registers
		{ mode = { "n", "x" }, keys = '"' },
		{ mode = { "i", "c" }, keys = "<C-r>" },

		-- Window commands
		{ mode = "n",          keys = "<C-w>" },

		-- `z` key
		{ mode = { "n", "x" }, keys = "z" },

		-- `i/a` key
		{ mode = { "n", "x" }, keys = "i" },
	},

	clues = {
		-- Enhance this by adding descriptions for <Leader> mapping groups
		clue.gen_clues.square_brackets(),
		clue.gen_clues.builtin_completion(),
		clue.gen_clues.g(),
		clue.gen_clues.marks(),
		clue.gen_clues.registers(),
		clue.gen_clues.windows(),
		clue.gen_clues.z(),
	},

	window = {
		delay = 200,
		config = {
			width = 'auto',
		}
	}
})


-- Use and configure mini.hipatterns
-- local hipatterns = require('mini.hipatterns')
-- hipatterns.setup({
-- 	highlighters = {
-- 		-- Highlight standalone 'FIXME', 'HACK', 'TODO', 'NOTE'
-- 		fixme     = { pattern = '%f[%w]()FIXME()%f[%W]', group = 'MiniHipatternsFixme' },
-- 		hack      = { pattern = '%f[%w]()HACK()%f[%W]', group = 'MiniHipatternsHack' },
-- 		todo      = { pattern = '%f[%w]()TODO()%f[%W]', group = 'MiniHipatternsTodo' },
-- 		note      = { pattern = '%f[%w]()NOTE()%f[%W]', group = 'MiniHipatternsNote' },
--
-- 		-- Highlight hex color strings (`#rrggbb`) using that color
-- 		hex_color = hipatterns.gen_highlighter.hex_color(),
-- 	},
-- })
