local function async_cmd(cmd)
	local job_id = vim.fn.jobstart(cmd, {
		on_stdout = function(_, data)
			for _, line in pairs(data or {}) do
				print(line)
			end
		end,
		on_stderr = function(_, data)
			for _, line in pairs(data or {}) do
				print(line)
			end
		end,
		on_exit = function(_, code)
			if code ~= 0 then
				vim.notify(
					string.format("Команда завершилась с ошибкой (%d)", code),
					vim.log.levels.ERROR
				)
			else
				vim.notify("OK", vim.log.levels.INFO)
			end
		end,
	})

	return job_id
end

vim.api.nvim_create_autocmd({ "BufWritePre" }, {
	pattern = "*.go",
	callback = function()
		local params = vim.lsp.util.make_range_params(nil, vim.lsp.util._get_offset_encoding())
		params.context = { only = { "source.organizeImports" } }
		local result = vim.lsp.buf_request_sync(0, "textDocument/codeAction", params, 3000)
		for _, res in pairs(result or {}) do
			for _, r in pairs(res.result or {}) do
				if r.edit then
					vim.lsp.util.apply_workspace_edit(r.edit, vim.lsp.util._get_offset_encoding())
				else
					vim.lsp.buf.execute_command(r.command)
				end
			end
		end
	end,
})

vim.api.nvim_create_autocmd({ "BufWritePre" }, {
	pattern = "*.go",
	callback = function()
		vim.lsp.buf.format(nil, 3000)
	end,
})

local TrimWhiteSpaceGrp = vim.api.nvim_create_augroup("TrimWhiteSpaceGrp", {})
vim.api.nvim_create_autocmd("BufWritePre", {
	group = TrimWhiteSpaceGrp,
	pattern = "*",
	command = "%s/\\s\\+$//e",
})

local YankHighlightGrp = vim.api.nvim_create_augroup("YankHighlightGrp", {})
vim.api.nvim_create_autocmd("TextYankPost", {
	group = YankHighlightGrp,
	pattern = "*",
	callback = function()
		vim.highlight.on_yank({
			higroup = "IncSearch",
			timeout = 40,
		})
	end,
})

vim.api.nvim_create_autocmd("BufEnter", {
	callback = function()
		if vim.bo.filetype == "NvimTree" or vim.fn.expand("%") == "" then
			return
		end
		vim.schedule(function()
			vim.cmd("nohlsearch")
			local treeapi = require("nvim-tree.api")
			treeapi.tree.find_file({
				update_root = false,
				focus = false,
			})
		end)
	end,
})

vim.api.nvim_create_autocmd("FileType", {
	pattern = "*",
	callback = function(args)
		local buf = args.buf
		local ft = vim.bo[buf].filetype

		if ft and ft ~= "" then
			local has_parser, _ = pcall(vim.treesitter.language.get_lang, ft)
			if has_parser then
				pcall(vim.treesitter.start, buf, ft)
			end
		end
	end,
})
vim.api.nvim_create_autocmd("User", {
	pattern = "TSUpdate",
	callback = function()
		vim.cmd([[TSEnable highlight]])
	end,
})
vim.api.nvim_create_autocmd({ "BufWritePost" }, {
	pattern = "*.templ",
	callback = function()
		local cmd = "templ generate"
		async_cmd(cmd)
	end,
})

vim.api.nvim_create_autocmd({ "VimEnter" }, {
	callback = function(data)
		local directory = vim.fn.isdirectory(data.file) == 1
		if not directory then
			return
		end
		vim.cmd.cd(data.file)
		require("nvim-tree.api").tree.open()
	end,
})

vim.api.nvim_create_autocmd("FileType", {
	pattern = "go",
	callback = function()
		vim.opt_local.expandtab = false
		vim.opt_local.tabstop = 4
		vim.opt_local.shiftwidth = 4
		vim.opt_local.autoindent = true
		vim.opt_local.smartindent = true
		vim.opt_local.cindent = false
	end,
})

vim.filetype.add({
	extension = {
		hjson = "hjson",
	},
})

vim.api.nvim_create_autocmd("InsertEnter", {
	pattern = "*",
	command = "set norelativenumber",
})

vim.api.nvim_create_autocmd("InsertLeave", {
	pattern = "*",
	command = "set relativenumber",
})
