-- All fields defined in one/init.lua
local One = {}

-- Clear all plugins and cached files.
-- It will ask to confirm before deleting files.
function One.reset()
	local util = One.util
	local config = One.CM.config
	local PATH_SEPARATOR = One.consts.PATH_SEPARATOR

	local pmUse = config.pluginManager.use
	local pmConf = config.pluginManager[pmUse]

	local files = { --
	}

	if pmUse == 'lazy' then
		files[#files + 1] = pmConf.dist
		files[#files + 1] = pmConf.config.root
	elseif pmUse == 'vim-plug' then
		files[#files + 1] = pmConf.dist
		files[#files + 1] = pmConf.pluginDir
	elseif pmUse == 'packer' then
		files[#files + 1] = pmConf.packerFolder
		files[#files + 1] = pmConf.config.snapshot_path
		files[#files + 1] = pmConf.config.compile_path
		files[#files + 1] = pmConf.config.package_root .. PATH_SEPARATOR .. pmConf.config.plugin_package
	else
		error('Invalid config.pluginManager.use=' .. pmUse)
	end

	for _, path in pairs(files) do print(path) end

	local isDir = vim.fn.isdirectory
	local choice = vim.fn.confirm('Confirm to delete above files', '&Yes\n&No', 2)

	if choice == 1 then
		print('Yes')

		local ok, msg
		for _, path in pairs(files) do
			if isDir(path) == 1 then
				print('Deleting directory: ' .. path)
				ok, msg = pcall(util.rm, path)
				if not ok then
					print('Failed to delete directory. Reason: ' .. msg)
					break
				end
			else
				print('Deleting file: ' .. path)
				ok, msg = os.remove(path)
				if not ok then
					print('Failed to delete file. Reason: ' .. msg)
					break
				end
			end
		end

		if ok then
			print(
				'Success. Please restart nvim and reinitialize it. See https://github.com/adoyle-h/one.nvim#initialization')
		else
			print(
				'Please delete above files manually.\nAnd then restart nvim and reinitialize it. See https://github.com/adoyle-h/one.nvim#initialization')
		end
	else
		print('No')
	end
end

function One.showConfig(opts)
	opts = vim.tbl_deep_extend('keep', opts, {
		fargs = {},
	})
	local util = One.util

	local title = '[one.nvim config]'
	local w = util.newWindow({ title = title, ft = 'lua' })
	local write = w.write
	write({ '-- The content generated by :OneShowConfig ' .. opts.args, '-- config --' })

	local config = One.CM.config

	if (#opts.fargs > 0) then
		config = vim.tbl_get(One.CM.config, table.unpack(opts.fargs))
	end

	write(util.dump2Lines(config))
	w.resetCursor()
end

function One.showPlugins()
	local util = One.util
	local title = '[one.nvim plugins]'
	local w = util.newWindow({ title = title, ft = 'lua' })
	local write = w.write

	write('-- The content generated by :OneShowPlugins')

	local disabledPlugs = {}
	local enabledPlugs = {}
	for _, p in pairs(One.PM.plugs) do
		if p.disable then
			disabledPlugs[#disabledPlugs + 1] = p
		else
			enabledPlugs[#enabledPlugs + 1] = p
		end
	end

	local omitFields = { 'config', 'defaultConfig', 'id' }
	local writePlug = function(p)
		write({ '', '-- id: ' .. p.id })

		local result = {}
		for key, val in pairs(p) do
			if not vim.tbl_contains(omitFields, key) then
				if type(val) == 'function' then val = val(One.CM.config) end
				result[key] = val
			end
		end

		write(util.dump2Lines(result))
	end

	write({ '', '-- Disabled plugins --' })
	for _, p in pairs(disabledPlugs) do writePlug(p) end

	write({ '', '-- Enabled plugins --' })
	for _, p in pairs(enabledPlugs) do writePlug(p) end

	w.resetCursor()
end

local updateMap = {
	one = function(config, run)
		run(string.format('git -C %s pull --progress --depth 1', config.ONE_DIR))
	end,

	pm = function(config, run)
		local pmConf = config.pluginManager
		local pmUse = pmConf.use

		if pmUse == 'lazy' then
			run(string.format('git -C %s pull --progress --depth 1', pmConf['lazy'].dist))
		elseif pmUse == 'packer' then
			run(string.format('git -C %s pull --progress --depth 1', pmConf['packer'].packerFolder))
		elseif pmUse == 'vim-plug' then
			local url = One.util.proxyGithub(pmConf['vim-plug'].src)
			local cmd = string.format('curl --create-dirs -Lo "%s" "%s"', pmConf['vim-plug'].dist, url)
			run(cmd)
		end
	end,
}

One.updateMap = updateMap

function One.update(name)
	local config = One.CM.config
	local util = One.util

	local run = function(cmd)
		local _, buf = util.floatWindow { height = 0.4 }

		cmd = cmd .. ' 2>&1'
		vim.cmd.terminal(cmd)

		vim.api.nvim_buf_set_keymap(buf, 'n', 'q', ':q<CR>', { silent = true })
		vim.api.nvim_buf_call(buf, function()
			vim.api.nvim_put({ 'To run: ' .. cmd, '' }, 'l', false, true)
		end)
	end

	if name == nil or name == 'all' then
		for _, fn in pairs(updateMap) do fn(config, run) end
	else
		local fn = updateMap[name]
		if not fn then error('Invalid name: ' .. name) end
		fn(config, run)
	end
end

return One
