vim.g.mapleader = " "
vim.g.localleader = "\\"


-- Install Lazy
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not (vim.uv or vim.loop).fs_stat(lazypath) then
	local lazyrepo = "https://github.com/folke/lazy.nvim.git"
	local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath })
	if vim.v.shell_error ~= 0 then
		vim.api.nvim_echo({
			{ "Failed to clone lazy.nvim:\n", "ErrorMsg" },
			{ out,                            "WarningMsg" },
			{ "\nPress any key to exit..." },
		}, true, {})
		vim.fn.getchar()
		os.exit(1)
	end
end
vim.opt.rtp:prepend(lazypath)

-- TODO: get colored renders working
vim.g.rustaceanvim = {
	-- Plugin configuration
	tools = {
		float_win_config = { border = 'rounded' },
	},

	-- LSP configuration
	server = {
		on_attach = function(client, bufnr)
			vim.keymap.set('n', '<leader>lg', pick_rust_target,
				{ desc = "Pick Target (Rust)", buffer = bufnr })
			vim.keymap.set('n', "<leader>a", function() vim.cmd.RustLsp('codeAction') end,
				{ desc = "Code Action (Rust)", buffer = bufnr })
			vim.keymap.set('n', "<leader>e", function() vim.cmd.RustLsp('renderDiagnostic', 'current') end,
				{ desc = "Render Diagnostic", buffer = bufnr })
		end,
		default_settings = {
			['rust-analyzer'] = {
				checkOnSave = true,
				check = {
					overrideCommand = {
						"cargo", "check", "--message-format=json-diagnostic-rendered-ansi",
					}
				},
			},
		},
		settings = function(project_root)
			local ra = require('rustaceanvim.config.server')
			local settings = ra.load_rust_analyzer_settings(project_root, {
				settings_file_pattern = 'rust-analyzer.json'
			})

			-- override default target (if `set_rust_target` has been called)
			local rust_target = vim.g["rust-analyzer-target"]
			if rust_target then
				settings["rust-analyzer"]["cargo"] = { target = rust_target }
			end

			vim.g["rust-analyzer-target-test"] = settings

			return settings
		end,
	},

	-- DAP configuration
	dap = {},
}


require('plugins')
require('vars')
require('opts')
require('fns')
require('keys')
require('theme')
require('statusline')
--require('debugger') -- TODO:

-- Mason Setup
local language_servers = {
	"pylsp",
	"eslint",
	"cssls",
	"jsonls",
	"ts_ls",
	"gopls",
	"wgsl_analyzer",
}
require("mason").setup({
	ui = {
		icons = {
			package_installed = "",
			package_pending = "",
			package_uninstalled = "",
		},
	},
	ensure_installed = language_servers,
})
require("mason-lspconfig").setup {
	automatic_enable = {
		exclude = {
			-- rust_analyzer is managed by rustaceanvim
			"rust_analyzer",
		}
	}
}

local lspconfig = require("lspconfig")
for _, l in pairs(language_servers) do
	lspconfig[l].setup {}
end

require('dapui').setup();

local compare = require "cmp.config.compare"
require('cmp').setup.filetype({ "rust" }, {
	sorting = {
		priority_weight = 2,
		comparators = {
			-- deprioritize `.box`, `.mut`, etc.
			require("cmp-rust").deprioritize_postfix,
			-- deprioritize `Borrow::borrow` and `BorrowMut::borrow_mut`
			require("cmp-rust").deprioritize_borrow,
			-- deprioritize `Deref::deref` and `DerefMut::deref_mut`
			require("cmp-rust").deprioritize_deref,
			-- deprioritize `Into::into`, `Clone::clone`, etc.
			require("cmp-rust").deprioritize_common_traits,
			compare.offset,
			compare.exact,
			compare.score,
			--compare.recently_used,
			compare.locality,
			compare.sort_text,
			compare.length,
			compare.order,
		},
	},
})

-- Format file on save
vim.cmd [[autocmd BufWritePre * lua vim.lsp.buf.format()]]

-- Completion Plugin Setup
local cmp = require 'cmp'
cmp.setup({
	-- Enable LSP snippets
	snippet = {
		expand = function(args)
			vim.fn["vsnip#anonymous"](args.body)
		end,
	},
	mapping = {
		['<C-p>'] = cmp.mapping.select_prev_item(),
		['<C-n>'] = cmp.mapping.select_next_item(),
		-- Add tab support
		['<S-Tab>'] = cmp.mapping.select_prev_item(),
		['<Tab>'] = cmp.mapping.select_next_item(),
		['<C-S-f>'] = cmp.mapping.scroll_docs(-4),
		['<C-f>'] = cmp.mapping.scroll_docs(4),
		['<C-Space>'] = cmp.mapping.complete(),
		['<C-e>'] = cmp.mapping.close(),
		['<CR>'] = cmp.mapping.confirm({
			behavior = cmp.ConfirmBehavior.Insert,
			select = true,
		})
	},
	-- Installed sources:
	sources = {
		{ name = 'path' },                                 -- file paths
		{ name = 'nvim_lsp',               keyword_length = 3 }, -- from language server
		{ name = 'nvim_lsp_signature_help' },              -- display function signatures with current parameter emphasized
		{ name = 'nvim_lua',               keyword_length = 2 }, -- complete neovim's Lua runtime API such vim.lsp.*
		{ name = 'buffer',                 keyword_length = 2 }, -- source current buffer
		{ name = 'vsnip',                  keyword_length = 2 }, -- nvim-cmp source for vim-vsnip
		{ name = 'calc' },                                 -- source for math calculation
	},
	window = {
		completion = cmp.config.window.bordered(),
		documentation = cmp.config.window.bordered(),
	},
	formatting = {
		fields = { 'menu', 'abbr', 'kind' },
		format = function(entry, item)
			local menu_icon = {
				nvim_lsp = 'λ',
				vsnip = '⋗',
				buffer = 'Ω',
				path = '🖫',
			}
			item.menu = menu_icon[entry.source.name]
			return item
		end,
	},
})


-- Treesitter Plugin Setup
require('nvim-treesitter.configs').setup {
	ensure_installed = { "lua", "rust", "toml" },
	auto_install = true,
	highlight = {
		enable = true,
		additional_vim_regex_highlighting = false,
	},
	ident = { enable = true },
	rainbow = {
		enable = true,
		extended_mode = true,
		max_file_lines = nil,
	}
}
