#!/usr/bin/lua5.3
-- Generate bash completion for apk(8) from scdoc manpages

local template_main = [==[
# apk(8) completion                                         *- shell-script -*-
# Automatically generated by apk-tools (src/genbash.lua). Do not modify.

# Helpers
__apk_installed_pkgs() { apk query --summarize name --installed "$1*" 2>/dev/null; }
__apk_available_pkgs() { apk query --summarize name --available "$1*" 2>/dev/null; }

_comp_cmd_apk() {
	local cur="${COMP_WORDS[COMP_CWORD]}"
	local applet=""

	# Find the applet (first non-option argument)
	for ((i=1; i < COMP_CWORD; i++)); do
		if [[ ${COMP_WORDS[i]} != -* ]]; then
			applet="${COMP_WORDS[i]}"
			break
		fi
	done

	# Applet specific completion
	case "$applet" in
%s	*)
		if [[ ${cur} == -* ]]; then
			# No applet or unknown applet, complete with global options
			COMPREPLY=($(compgen -W "%s" -- ${cur}))
		elif [[ -z "$applet" ]]; then
			# No applet, complete with applet list
			COMPREPLY=($(compgen -W "%s" -- ${cur}))
		else
			COMPREPLY=()
		fi
		;;
	esac
}

complete -F _comp_cmd_apk apk
]==]

local template_applet = [==[
	%s)
		if [[ ${cur} == -* ]]; then
			COMPREPLY=($(compgen -W "%s" -- ${cur}))
		else
			%s
		fi
		;;
]==]

local M = {}

local function collect_flags(doc)
	local opts = {}
	-- Collect every --flag/-f we can find
	for _, group in ipairs(doc.optgroup or {}) do
		for _, opt in ipairs(group) do
			for flag in opt[1]:gmatch("(%-%-?[^ ,]+)") do
				local opt, val = flag:match("(.*)%[=(%w+)%]")
				if val == "BOOL" then
					local no_opt =  opt:gsub("^%-%-", "--no-")
					table.insert(opts, opt)
					table.insert(opts, no_opt)
				else
					table.insert(opts, flag)
				end
			end
		end
	end
	--table.sort(opts)
	return opts
end

local wildcard_installed = 'COMPREPLY=($(compgen -W "$(__apk_installed_pkgs "${cur}")" -- ${cur}))'
local wildcard_available = 'COMPREPLY=($(compgen -W "$(__apk_available_pkgs "${cur}")" -- ${cur}))'

-- Applets needing package name completion
local applet_wildcard = {
	add=wildcard_available,
	del=wildcard_installed,
	dot=wildcard_available,
	fetch=wildcard_available,
	fix=wildcard_installed,
	index=wildcard_available,
	info=wildcard_available,
	list=wildcard_available,
	manifest=wildcard_available,
	mkndx=wildcard_available,
	policy=wildcard_available,
	query=wildcard_available,
	search=wildcard_available,
	upgrade=wildcard_installed,
}

function M:generate(app, docs)
	local applets, options, goptions = {}, {}, {}
	for _, doc in ipairs(docs) do
		-- only process section 8
		if doc.mansection == "8" then
			local opts = collect_flags(doc)
			if doc.applet == "APK" then
				table.sort(opts)
				goptions = opts
			else
				table.insert(applets, doc.applet)
				options[doc.applet] = opts
			end
		end
	end

	local t_applet = {}
	for _, name in ipairs(applets) do
		local o = table.concat(options[name], " ")
		local wildcard = applet_wildcard[name] or "COMPREPLY=()"
		table.insert(t_applet, template_applet:format(name, o, wildcard))
	end

	local s_root   = table.concat(applets, " ")
	local s_global = table.concat(goptions, " ")
	local s_applet = table.concat(t_applet, "")
	return string.format(template_main, s_applet, s_global, s_root)
end

return M
