#!/usr/bin/env bash
. "${0%/*}"/../lib/common.bashlib || exit 1 #C#
init
depend portageq # emerge
esanitize
include atomf
usage <<-EOU
	Usage: ${0##*/} [2-9][-] <atom> [emerge option]...

	Helper for using \`qa-cmp\` which emerges the package defined by <atom> but
	by first emerging its previous (visible) version if not already installed.

	If [2-9] is provided as first argument, go back N versions.

	If \`-\` is specified (e.g. \`${0##*/} -\` or \`${0##*/} 2-\`), will only
	emerge the previous and not the newest.

	Any options after <atom> are passed to emerge as-is.

	Options:
	  -h, --help     Display usage information and exit
	      --version  Display version information and exit

	*Note*
	This exports IWDT_ALL=y (see help text of other @package@ commands)

	Environment:
	  EOLDNEW_EMERGE_CMD=emerge  If need to call something else than emerge(1)
	  EOLDNEW_EMERGE_ARGS=       Similar to EMERGE_DEFAULT_OPTS
	  EOLDNEW_EMERGE_ARGS_OLD=   Only used when emerging old
	  EOLDNEW_EMERGE_ARGS_NEW=   Only used when emerging new
	Note it is possible to set these in portage's make.conf as well, and _ARGS
	environment will replace instances of {} by the specified <atom>, e.g.
	  EOLDNEW_EMERGE_ARGS_NEW="--usepkg-exclude {}"
EOU

# do crude option parsing not to have to figure out emerge's options
# TODO?: this does not recognize --root/--eprefix unlike
# other scripts, albeit it is not very important here
skip_new=
skip_old=
declare -i old=1
if (( ${#} )); then
	if [[ ${1} == [1-9]* ]]; then
		old=${1%-}
		[[ ${1} == *- ]] && skip_new=y
		shift
	elif [[ ${1} == - ]]; then
		skip_new=y
		shift
	elif [[ ${1} == -h || ${1} == --help ]]; then
		usage
	elif [[ ${1} == --version ]]; then
		version
	fi
fi
(( ${#} >= 1 )) || die "no atom specified, see \`${0##*/} --help\`"

# reduce atom to category/pn (or just pn) so we can get all versions
atom=$(atomf -M '%p' "${1}") || die

# could use pkgcore's smarter version but portageq's is enough
portageq pquery "${atom}" | map vers || die "portageq pquery failed for '${atom}'"

# requested atom may not necessarily be latest, resolve it to know its position
atom=$(portageq best_visible "${EROOT:-/}" "${1}") \
	|| die "portageq best_visible failed for '${1}'"

usevers=()
for ver in "${vers[@]}"; do
	[[ ${ver} == "${atom}" ]] && break
	usevers+=("${ver}")
done

(( ${#usevers[@]} )) || die "failed to find an older version than '${atom}'"

(( old = ${#usevers[@]} - old ))
(( old < 0 )) && old=0 # use oldest

portageq has_version "${EROOT:-/}" "${usevers[old]}" && skip_old=y

[[ -v skip_old || -v skip_new ]] || die "nothing to do"

msg "old: ${usevers[old]}${skip_old/y/ (skipped)}"
msg "new: ${atom}${skip_new/y/ (skipped)}"

export IWDT_ALL=y

# ignore portageq errors as it return 1 if env is unset
portageq envvar EOLDNEW_EMERGE_CMD EOLDNEW_EMERGE_ARGS EOLDNEW_EMERGE_ARGS_OLD EOLDNEW_EMERGE_ARGS_NEW \
	| map env

: "${EOLDNEW_EMERGE_CMD:=${env[0]:-emerge}}"
: "${EOLDNEW_EMERGE_ARGS:=${env[1]:-}}"
: "${EOLDNEW_EMERGE_ARGS_OLD:=${env[2]:-}}"
: "${EOLDNEW_EMERGE_ARGS_NEW:=${env[3]:-}}"

# give a way to insert <atom> in environment options by replacing {}
EOLDNEW_EMERGE_ARGS=${EOLDNEW_EMERGE_ARGS//'{}'/${1}}
EOLDNEW_EMERGE_ARGS_OLD=${EOLDNEW_EMERGE_ARGS_OLD//'{}'/${1}}
EOLDNEW_EMERGE_ARGS_NEW=${EOLDNEW_EMERGE_ARGS_NEW//'{}'/${1}}

if [[ ! ${skip_old} ]]; then
	cmd=("${EOLDNEW_EMERGE_CMD}" "=${usevers[old]}" "${@:2}")
	split +cmd "${EOLDNEW_EMERGE_ARGS} ${EOLDNEW_EMERGE_ARGS_OLD}"
	msg "running: ${cmd[*]}"
	"${cmd[@]}" || exit $?
fi

if [[ ! ${skip_new} ]]; then
	cmd=("${EOLDNEW_EMERGE_CMD}" "${@}")
	split +cmd "${EOLDNEW_EMERGE_ARGS} ${EOLDNEW_EMERGE_ARGS_NEW}"
	msg "running: ${cmd[*]}"
	"${cmd[@]}"
fi

# vim: ts=4
