local default_config = {
	delve = {
		path = "dlv",
		initialize_timeout_sec = 20,
		port = "${port}",
		args = {},
		build_flags = "",
		-- Automatically handle the issue on delve Windows versions < 1.24.0
		-- where delve needs to be run in attched mode or it will fail (actually crashes).
		detached = vim.fn.has("win32") == 0,
		output_mode = "remote",
		cwd = nil,
	},
	tests = {
		verbose = false,
	},
}

local function setup_go_configuration(dap, configs)
	local common_debug_configs = {
		{
			type = "go",
			name = "Debug",
			request = "launch",
			program = "${workspaceFolder}",
			outputMode = "remote",
		},

	}

	if dap.configurations.go == nil then
		dap.configurations.go = {}
	end

	for _, config in ipairs(common_debug_configs) do
		table.insert(dap.configurations.go, config)
	end

	if configs == nil or configs.dap_configurations == nil then
		return
	end

	for _, config in ipairs(configs.dap_configurations) do
		if config.type == "go" then
			table.insert(dap.configurations.go, config)
		end
	end
end

return {
	"leoluz/nvim-dap-go",
	dependencies = { "mfussenegger/nvim-dap" },
	opts = true,
	config = function()
		local dap, dapui = require("dap"), require("dapui")

		dap.adapters.go = {
			type = "server",
			port = "${port}",
			executable = {
				command = "dlv",
				args = { "dap", "-l", "127.0.0.1:${port}" },
			},
		}

		setup_go_configuration(dap, default_config)

		dap.defaults.fallback.terminal_win_cmd = "enew | set filetype=dap-terminal"
		dap.listeners.before.attach.dapui_config = function()
			dapui.open()
		end
		dap.listeners.before.launch.dapui_config = function()
			dapui.open()
		end
		dap.listeners.before.event_terminated.dapui_config = function()
			dapui.close()
		end
		dap.listeners.before.event_exited.dapui_config = function()
			dapui.close()
		end

		vim.api.nvim_set_hl(0, "DapBreakpoint", { ctermbg = 0, fg = "#993939", bg = "#31353f" })
		vim.api.nvim_set_hl(0, "DapLogPoint", { ctermbg = 0, fg = "#61afef", bg = "#31353f" })
		vim.api.nvim_set_hl(0, "DapStopped", { ctermbg = 0, fg = "#98c379", bg = "#31353f" })

		vim.fn.sign_define(
			"DapBreakpoint",
			{ text = "!", texthl = "DapBreakpoint", linehl = "DapBreakpoint", numhl = "DapBreakpoint" }
		)
		vim.fn.sign_define(
			"DapBreakpointCondition",
			{ text = "?", texthl = "DapBreakpoint", linehl = "DapBreakpoint", numhl = "DapBreakpoint" }
		)
		vim.fn.sign_define(
			"DapBreakpointRejected",
			{ text = "RJ", texthl = "DapBreakpoint", linehl = "DapBreakpoint", numhl = "DapBreakpoint" }
		)
		vim.fn.sign_define(
			"DapLogPoint",
			{ text = "i", texthl = "DapLogPoint", linehl = "DapLogPoint", numhl = "DapLogPoint" }
		)
		vim.fn.sign_define(
			"DapStopped",
			{ text = "→", texthl = "DapStopped", linehl = "DapStopped", numhl = "DapStopped" }
		)
	end,
	keys = {
		{
			"<F5>",
			function()
				require("dap").continue()
			end,
			silent = true,
		},
		{
			"<F17>", -- S-F5
			function()
				require("dap").restart()
			end,
			silent = true,
		},
		{
			"<F29>", -- C-F5
			function()
				require("dap").terminate()
			end,
			silent = true,
		},
		{
			"<F8>",
			function()
				require("dap").step_over()
			end,
			silent = true,
		},
		{
			"<F7>",
			function()
				require("dap").step_into()
			end,
			silent = true,
		},
		{
			"<F19>", -- S-F7
			function()
				require("dap").step_out()
			end,
			silent = true,
		},
		{
			"<A-b>",
			function()
				require("dap").toggle_breakpoint()
			end,
			silent = true,
		},
	},
}
