#!/bin/sh

VERSION="2.1"

export LSPKG=1

print_help()
{
    printf "%s\n" "
Usage:
lspkg [-f|-F|-s|-n|-p] [-d|-D|-i|-r] [--] PROFID PACKAGES [lsrdd options]
lspkg [-c|-t] PROFID PACKAGES [lsrdd options]
lspkg --help|--version

    Tool to output names of buildable or installable packages, available in current working directory of any-engine.
    See lspkg(1) man page for detailed description. See rdd(1) for generic package syntax 
    and lsrdd(1) for description of lsrdd utility.
    
    -f
        Print names of files instead of names for package database.
    -F
        Print verified full path names of packages instead of their names.
    -k
        Print key-value pairs: plain rdd name and verified relative path.
    -K
        Print key-value pairs: plain rdd name and verified full absolute path.
    -n
        Print full names for package database.
    -s
        Print base names without version.
    -p
        Print plain rdd names (default).
    -d
        Print dependency tree for given package set. CMD arguments included.
        Deployed packages are not printed.
    -D
        Print dependency tree for given package set. CMD arguments included.
        The output includes entire tree, whether the packages are currently deployed or not.
    -i
        Print names of packages, which are in direct dependencies of given package set.
        The output includes entire set, whether the packages are currently deployed or not.
    -m
        Print names of packages, which are in direct dependencies of given package set.
        Deployed packages are not printed.
    -r
        Print reverse dependencies of given package set.
        For given package a-1.2.3 lspkg will print all packages, which depend on a-1.2.3.
        Lists are supported as well.
    -c
        Check the correctness of list order for each given package.
        Correct order means all packages must be placed in list after their dependencies.
        If incorrect order is detected, return non-zero code.
        All other options are ignored in this mode.
        Option requires the usage of temporary file.
    -t
        Resolve dependencies for given set.
        Then print each dependency, followed by the packages from given set, that directly depend on it.
        Option requires the usage of temporary file.
    --status
        Print plain rdd name, build status and time.
    --
        Stop parsing lspkg options.
"
}

fatal_error()
{
    printf "%s\n" "$1" >& 2
    exit 1
}

lspkg_status()
{
    while read -r line_input <&0 ; do
        # must be synced with log_STATUS from corelib/api.sh
        status_file="${TMPDIR}/${line_input}/status"
        if test -f "${status_file}" ; then
            cat "${status_file}"
        else
            printf "%s None 0\n" "${line_input}"
        fi
    done
}

FILES=
FILENAMES=
SHORTNAMES=
FULLNAMES=
PLAINNAMES=1
KEYVALUES=
RELATIVEPATH=
MISSINGDEPS=
COMPLETEDEPS=
STRAIGHTDEPS=
STATUS=
CHECKORDER=
STRUCTURE=

while test -n "$1" ; do
    case "$1" in
        --help)
                print_help
                exit 0
            ;;
        --version)
                printf "%s\n" "${VERSION}"
                exit 0
            ;;
        --status)
            STATUS=1
            shift
            ;;
        -f)
            FILES=
            FILENAMES=1
            BASENAMES=
            FULLNAMES=
            PLAINNAMES=
            KEYVALUES=
            RELATIVEPATH=
            shift
            ;;
        -F)
            FILES=1
            FILENAMES=
            BASENAMES=
            FULLNAMES=
            PLAINNAMES=
            KEYVALUES=
            RELATIVEPATH=
            shift
            ;;
        -k)
            FILES=1
            FILENAMES=
            BASENAMES=
            FULLNAMES=
            PLAINNAMES=1
            KEYVALUES=1
            RELATIVEPATH=1
            shift
            ;;
        -K)
            FILES=1
            FILENAMES=
            BASENAMES=
            FULLNAMES=
            PLAINNAMES=1
            KEYVALUES=1
            RELATIVEPATH=
            shift
            ;;
        -s)
            FILES=
            FILENAMES=
            SHORTNAMES=1
            FULLNAMES=
            PLAINNAMES=
            KEYVALUES=
            RELATIVEPATH=
            shift
            ;;
        -n)
            FILES=
            FILENAMES=
            SHORTNAMES=
            FULLNAMES=1
            PLAINNAMES=
            KEYVALUES=
            RELATIVEPATH=
            shift
            ;;
        -p)
            FILES=
            FILENAMES=
            SHORTNAMES=
            FULLNAMES=
            PLAINNAMES=1
            KEYVALUES=
            RELATIVEPATH=
            shift
            ;;
        -d)
            MISSINGDEPS=1
            COMPLETEDEPS=
            STRAIGHTDEPS=
            STRAIGHTMISSINGDEPS=
            REVERSEDEPS=
            shift
            ;;
        -D)
            COMPLETEDEPS=1
            MISSINGDEPS=
            STRAIGHTDEPS=
            STRAIGHTMISSINGDEPS=
            REVERSEDEPS=
            shift
            ;;
        -i)
            STRAIGHTDEPS=1
            STRAIGHTMISSINGDEPS=
            COMPLETEDEPS=
            MISSINGDEPS=
            REVERSEDEPS=
            shift
            ;;
        -m)
            STRAIGHTDEPS=
            STRAIGHTMISSINGDEPS=1
            COMPLETEDEPS=
            MISSINGDEPS=
            REVERSEDEPS=
            shift
            ;;
        -r)
            REVERSEDEPS=1
            STRAIGHTDEPS=
            STRAIGHTMISSINGDEPS=
            COMPLETEDEPS=
            MISSINGDEPS=
            shift
            ;;
        -c)
            CHECKORDER=1
            shift
            ;;
        -t)
            STRUCTURE=1
            shift
            ;;
        --)
            shift
            break
            ;;
        *)
            break
            ;;
    esac
done

time_warning=
if test -n "${COMPLETEDEPS}" ; then
    depend_filter="resolve_rebuild complete"
    time_warning=1
elif test -n "${STRAIGHTDEPS}" ; then
    depend_filter="resolve_atom complete"
elif test -n "${STRAIGHTMISSINGDEPS}" ; then
    depend_filter="resolve_atom"
elif test -n "${MISSINGDEPS}" ; then
    depend_filter="resolve_rebuild"
elif test -n "${REVERSEDEPS}" ; then
    depend_filter="resolve_reverse"
    time_warning=1
else
    depend_filter=
fi
if test -n "${CHECKORDER}" ; then
    time_warning=
    depend_filter="resolve_atom checklistorder"
fi
if test -n "${STRUCTURE}" ; then
    time_warning=
    depend_filter="resolve_atom structure"
fi

if test -n "${KEYVALUES}" ; then
    if test -n "${FILES}" && test -n "${PLAINNAMES}"; then
        if test -n "${RELATIVEPATH}" ; then
            pack_filter="pack_filter_pkgbinfiles_pairs_relative"
        else
            pack_filter="pack_filter_pkgbinfiles_pairs"
        fi
    fi
elif test -n "${FILENAMES}" ; then
    pack_filter="pack_filter_pkgbin"
elif test -n "${FILES}" ; then
    pack_filter="pack_filter_pkgbinfiles"
elif test -n "${SHORTNAMES}" ; then
    pack_filter="pack_filter_pkgbase"
elif test -n "${FULLNAMES}" ; then
    pack_filter="pack_filter_pkgname"
elif test -n "${STATUS}" ; then
    pack_filter="lspkg_status"
elif test -n "${PLAINNAMES}" ; then
    pack_filter=
fi

if test -z "${depend_filter}" -a -z "${pack_filter}" ; then
    lsrdd "${@}"
    exit $?
fi

if test -n "${time_warning}" ; then
    printf "%s\n" "Warning: the request may be time-consuming." >&2
fi

eval "$( dumprdd -g "${@}" )"
if test -z "${ANYAPI}" ; then
    fatal_error 'dumprdd failed. Check your rdd tools.'
fi

if test -n "${depend_filter}" ; then
    # handle possible errors here without single pipeline
    # depend filters wait inside full time anyways before any output, so it's no big deal
    results="$( list_parse "${rdd_list_entry}" | ${depend_filter} )"
    code=$?
    if test -z "${results}" ; then
        exit "${code}"
    fi
    if test -z "${pack_filter}" ; then
        pack_filter="cat"
    fi
    printf "%s\n" "${results}" | "${pack_filter}"
else
    list_parse "${rdd_list_entry}" | "${pack_filter}"
fi
