-- Basic settings
vim.g.loaded_matchparen = true
vim.g.netrw_liststyle = 3
vim.wo.number = true

local glob_opts = {
	background = 'dark',
	belloff = 'all',
	breakindent = true,
	hlsearch = false,
	laststatus = 0,
	lazyredraw = true,
	showcmd = true,
	synmaxcol = 800,
	syntax = 'on',
	termguicolors = true,
	titleold = vim.fn.getcwd(),
	title = true,
	wildmenu = true,
	wrap = true,
}

for option, value in pairs(glob_opts) do
	vim.go[option] = value
end


vim.cmd([[colorscheme gruvbox]])

require 'nvim-treesitter.configs'.setup {
	highlight = { enable = true, disable = {} },
	indent = { enable = false, disable = {} },
	rainbow = {
		enable = true,
		extended_mode = true, -- Highlight also non-parentheses delimiters, boolean or table: lang -> boolean
		max_file_lines = 1000, -- Do not enable for files with more than 1000 lines, int
		colors = {
			'#ff0000', '#ffa500', '#ffff00', '#008000', '#0051a0', '#8003f2'
		} -- table of hex strings
	}
}

-- Mappings.
-- See `:help vim.diagnostic.*` for documentation on any of the below functions
local opts = { noremap = true, silent = true }
vim.api.nvim_set_keymap('n', '<space>e',
	'<cmd>lua vim.diagnostic.open_float()<CR>', opts)
vim.api.nvim_set_keymap('n', '<space>q',
	'<cmd>lua vim.diagnostic.setloclist()<CR>', opts)
vim.api.nvim_set_keymap('n', 'Q', '<cmd>nohl<CR>', opts)
vim.api.nvim_set_keymap('n', 'j', 'gj', opts)
vim.api.nvim_set_keymap('n', 'k', 'gk', opts)
vim.api.nvim_set_keymap('v', 'j', 'gj', opts)
vim.api.nvim_set_keymap('v', 'k', 'gk', opts)
vim.api.nvim_set_keymap('n', '<C-J>', '<C-W><C-J>', opts)
vim.api.nvim_set_keymap('n', '<C-K>', '<C-W><C-K>', opts)
vim.api.nvim_set_keymap('n', '<C-L>', '<C-W><C-L>', opts)
vim.api.nvim_set_keymap('n', '<C-H>', '<C-W><C-H>', opts)
vim.api.nvim_set_keymap('n', "<C-P>", "<cmd>lua require('fzf-lua').files()<CR>", opts)

vim.api.nvim_create_autocmd('LspAttach', {
	desc = 'LSP actions',
	callback = function()
		local bufmap = function(mode, lhs, rhs)
			vim.keymap.set(mode, lhs, rhs, { buffer = true })
		end

		-- Displays hover information about the symbol under the cursor
		bufmap('n', 'K', '<cmd>lua vim.lsp.buf.hover()<cr>')

		-- Jump to the definition
		bufmap('n', 'gd', '<cmd>lua vim.lsp.buf.definition()<cr>')

		-- Jump to declaration
		bufmap('n', 'gD', '<cmd>lua vim.lsp.buf.declaration()<cr>')

		-- Lists all the implementations for the symbol under the cursor
		bufmap('n', 'gi', '<cmd>lua vim.lsp.buf.implementation()<cr>')

		-- Jumps to the definition of the type symbol
		bufmap('n', 'go', '<cmd>lua vim.lsp.buf.type_definition()<cr>')

		-- Lists all the references
		bufmap('n', 'gr', '<cmd>lua vim.lsp.buf.references()<cr>')

		-- Displays a function's signature information
		bufmap('n', '<C-k>', '<cmd>lua vim.lsp.buf.signature_help()<cr>')

		-- Renames all references to the symbol under the cursor
		bufmap('n', 'rn', '<cmd>lua vim.lsp.buf.rename()<cr>')

		-- Selects a code action available at the current cursor position
		bufmap('n', '<F4>', '<cmd>lua vim.lsp.buf.code_action()<cr>')
		bufmap('x', '<F4>', '<cmd>lua vim.lsp.buf.range_code_action()<cr>')

		-- Show diagnostics in a floating window
		bufmap('n', 'gl', '<cmd>lua vim.diagnostic.open_float()<cr>')

		-- Move to the previous diagnostic
		bufmap('n', '[d', '<cmd>lua vim.diagnostic.goto_prev()<cr>')

		-- Move to the next diagnostic
		bufmap('n', ']d', '<cmd>lua vim.diagnostic.goto_next()<cr>')

		-- Format current buffer
		bufmap('n', '<space>f', function() vim.lsp.buf.format { async = true } end)
	end
})

vim.diagnostic.config({ virtual_text = false}) -- Turn off inline diagnostics 

-- Show all diagnostics on current line in floating window
vim.api.nvim_set_keymap( 'n', '<Leader>d', ':lua vim.diagnostic.open_float()<CR>', opts)

-- Go to next diagnostic (if there are multiple on the same line, only shows
-- one at a time in the floating window)
vim.api.nvim_set_keymap( 'n', '<Leader>n', ':lua vim.diagnostic.goto_next()<CR>', opts)

-- Go to prev diagnostic (if there are multiple on the same line, only shows
-- one at a time in the floating window)
vim.api.nvim_set_keymap( 'n', '<Leader>p', ':lua vim.diagnostic.goto_prev()<CR>', opts)

-- Use a loop to conveniently call 'setup' on multiple servers and
-- map buffer local keybindings when the language server attaches
local cmp = require 'cmp'
cmp.setup({
	snippet = {
		expand = function(args)
			vim.fn["UltiSnips#Anon"](args.body)
		end,
	},
	sources = cmp.config.sources({
		{ name = 'nvim_lsp' },
		{ name = 'buffer' },
		{ name = 'path' },
		{ name = 'ultisnips' },
	}),
	mapping = {
		["<Tab>"] = cmp.mapping({
			i = function(fallback)
				if cmp.visible() then
					cmp.select_next_item({ behavior = cmp.SelectBehavior.Insert })
				else
					fallback()
				end
			end,
		}),
		["<S-Tab>"] = cmp.mapping({
			i = function(fallback)
				if cmp.visible() then
					cmp.select_prev_item({ behavior = cmp.SelectBehavimr.Insert })
				else
					fallback()
				end
			end,
		}),
		['<Down>'] = cmp.mapping(cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Select }), { 'i' }),
		['<Up>'] = cmp.mapping(cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Select }), { 'i' }),
		['<C-n>'] = cmp.mapping({
			i = function(fallback)
				if cmp.visible() then
					cmp.select_next_item({ behavior = cmp.SelectBehavior.Select })
				else
					fallback()
				end
			end
		}),
		['<C-p>'] = cmp.mapping({
			i = function(fallback)
				if cmp.visible() then
					cmp.select_prev_item({ behavior = cmp.SelectBehavior.Select })
				else
					fallback()
				end
			end
		}),
		['<C-b>'] = cmp.mapping(cmp.mapping.scroll_docs(-4), { 'i', 'c' }),
		['<C-f>'] = cmp.mapping(cmp.mapping.scroll_docs(4), { 'i', 'c' }),
		['<C-Space>'] = cmp.mapping(cmp.mapping.complete(), { 'i', 'c' }),
		['<C-e>'] = cmp.mapping({ i = cmp.mapping.close(), c = cmp.mapping.close() }),
		['<CR>'] = cmp.mapping({
			i = cmp.mapping.confirm({ behavior = cmp.ConfirmBehavior.Replace, select = false }),
		}),
	}
})

local servers = { 'pyright', 'rust_analyzer', 'ccls', 'nixd', 'texlab', 'zls' }
local capabilities = require('cmp_nvim_lsp').default_capabilities()
for _, lsp in pairs(servers) do
	require('lspconfig')[lsp].setup {
		capabilities = capabilities
	}
end

require('lspconfig').lua_ls.setup({
	capabilities = capabilities,
	single_file_support = true,
	settings = {
		Lua = {
			diagnostics = {
				globals = { 'vim' },
			},
			runtime = {
				version = 'LuaJIT',
				path = vim.split(package.path, ';'),
			},
			workspace = {
				library = {
					[vim.fn.expand('$VIMRUNTIME/lua')] = true,
					[vim.fn.expand('$VIMRUNTIME/lua/vim/lsp')] = true,
				},
			},
			telemetry = {
				enable = false,
			},
		},
	},
})

require('lspconfig').verible.setup({
	capabilities = capabilities,
	root_dir = function() return vim.loop.cwd() end
})

if vim.fn.exists('+undofile') ~= 0 then
	local undo_dir = vim.env.HOME .. '/.config/nvim/undo'
	if vim.fn.isdirectory(undo_dir) == 0 then vim.fn.mkdir(undo_dir, 'p') end
	vim.o.undodir = undo_dir
	vim.o.undofile = true
end

vim.cmd([[syntax sync minlines=100]])
vim.cmd([[syntax sync maxlines=140]])