#!/bin/sh -efu

. shell-args
. girar-sh-functions
PROG='task ls'

valid_repo_list="$(tr -s '\n' ' '<"$GIRAR_REPO_LIST" | sed 's/ $//')"
valid_state_list='awaiting building committing done eperm failed new pending postponed tested'
notdone_state_list='awaiting building committing eperm failed new pending postponed tested'
queue_state_list='awaiting building committing pending postponed'

show_help()
{
	cat <<EOF
$PROG - list tasks

Usage: $PROG [options]

Options:
  --repo=LIST   comma-separated list of repositories to display;
  --state=LIST  comma-separated list of task states to display;
  --user=NAME   user name whose tasks to display;
  -h, --help    show this text and exit.

Valid repository names are:
  $valid_repo_list, or ALL.
Default list of repositories is ALL.

Valid task state names are:
  $valid_state_list, or ALL.
Default list of task states is:
  for single user: $notdone_state_list;
  for --user=ALL: $queue_state_list.

Valid user name is
  any ${USER_PREFIX}* account name with "$USER_PREFIX" prefix stripped, or ALL.
Default user name is $GIRAR_USER.

EOF
	exit
}

TEMP="$(getopt -n "$PROG" -o h -l all,brief,done,repo:,state:,user:,help -- "$@")" ||
	show_usage
eval set -- "$TEMP"

repo=
brief=
state=
user=
while :; do
	case "$1" in
		--) shift; break ;;
		--all) user=all ;;
		--brief) brief=1 ;;
		--done) state=done ;;
		--repo) shift; repo="$1" ;;
		--state) shift; state="$1" ;;
		--user) shift; user="$1" ;;
		-h|--help) show_help ;;
		*) fatal "unrecognized option: $1" ;;
	esac
	shift
done

[ "$#" -eq 0 ] || show_usage 'too many arguments.'

user="$(printf %s "$user" |tr '[:upper:]' '[:lower:]')"

repo="$(printf %s "$repo" |tr -s , ' ' |tr '[:upper:]' '[:lower:]')"
[ -z "$(printf %s "$repo" |tr -d '[:alnum:]. ')" ] ||
	show_usage 'invalid repository name'

case "$repo" in
	''|all) repo="$valid_repo_list"
		;;
	*)	for r in $repo; do
			for v in $valid_repo_list; do
				[ "$v" = "$r" ] && break || continue
			done
			[ "$v" = "$r" ] ||
				show_usage 'invalid repository name'
		done
		;;
esac

state="$(printf %s "$state" |tr -s , ' ' |tr '[:upper:]' '[:lower:]')"
[ -z "$(printf %s "$state" |tr -d '[:alpha:] ')" ] ||
	show_usage 'invalid task state name'

case "$state" in
	'')	if [ "$user" = all ]; then
			state="$queue_state_list"
		else
			state="$notdone_state_list"
		fi
		;;
	all)	if [ "$user" = all ]; then
			state="$notdone_state_list"
		else
			state="$valid_state_list"
		fi
		;;
	*)	for s in $state; do
			for v in $valid_state_list; do
				[ "$v" = "$s" ] && break || continue
			done
			[ "$v" = "$s" ] ||
				show_usage 'invalid task state name'
		done
		;;
esac

[ -n "$user" ] ||
	user="$GIRAR_USER"
printf %s "$user" |grep -qs '^[a-z][a-z_0-9]\+$' ||
	show_usage 'invalid user name'

case "$user" in
	all)	ls_user=
		;;
	*)	[ -d "$GIRAR_PEOPLE_QUEUE/$user" ] ||
			fatal "user \"$user\" not found"
		ls_user="-user $USER_PREFIX$user"
		;;
esac

enable -f /usr/lib/bash/lockf lockf

show_status()
{
	local state try iter
	state="$(cat task/state)"
	printf ' %s' "$state"
	try="$(cat task/try 2>/dev/null ||:)"
	iter="$(cat task/iter 2>/dev/null ||:)"
	[ -z "$try$iter" ] ||
	[ "$try.$iter" = 1.1 ] ||
		[ "$iter" = 1 ] &&
			printf ' #%s' "$try" ||
			printf ' #%s' "$try.$iter"
}

ls1()
{
	local id="$1"; shift
	cd "$id" || return
	id="${id##*/}"
	printf '#%d' "$id"
	show_status
	if ! (builtin lockf -n . ); then
		printf ' [locked]'
	fi
	find gears -maxdepth 0 -path gears -type d -perm -g=w -printf ' [shared]' 2>/dev/null ||:
	if [ -f task/test-only ]; then
		printf ' [test-only]'
	fi
	[ -s "task/pocket" ] &&
		printf ' %s/%s' "$(cat task/pocket)" "$(cat task/repo)" ||
			printf ' %s' "$(cat task/repo)"
	if [ -f task/swift ]; then
		printf ' [swift]'
	fi
	[ -n "$ls_user" ] ||
		printf '/%s' "$(cat task/owner)"
	if [ -n "$brief" ]; then
		echo ' ...'
		return
	fi
	local i
	for i in $(gear_nums); do
		if [ -s "gears/$i/dir" ]; then
			local dir tag_name
			dir="$(cat "gears/$i/dir")"
			tag_name="$(cat "gears/$i/tag_name")"
			printf ' %s=%s' "${dir##*/}" "$tag_name"
		elif [ -s "gears/$i/srpm" ]; then
			printf ' srpm=%s' "$(cat "gears/$i/srpm")"
		elif [ -s "gears/$i/package" ]; then
			local action package
			[ -s "gears/$i/copy_repo" ] &&
				action=copy ||
				action=del
			package="$(cat "gears/$i/package")"
			printf ' %s=%s' "$action" "$package"
		fi
	done
	printf '\n'
}

cd "$GB_TASKS"

ids="$(
	for r in $repo; do
		for s in $state; do
			[ -d index/$r/$s ] || continue
			find -L index/$r/$s -mindepth 1 -maxdepth 1 -name '[1-9]*' -type d $ls_user
		done
	done |
		sort -t/ -nr -k4,4)"

if [ -z "$ids" ]; then
	message 'no tasks found for the given criteria'
	exit
fi

for id in $ids; do
	(ls1 "$id")
done
