#compdef hsh hsh-install hsh-rebuild hsh-run hsh-shell hsh-copy mkaptbox
# vim: et tw=4 sw=4

local curcontext="$curcontext" packages ret=1
typeset -A opt_args
local -a help_opts common_opts aptbox_opts __repo builder_opts nonsh_opts
local mountpoints_opt
local workdir_arg

help_opts=(
'(-v --verbose -q --quiet)'{-q,--quiet}'[try to be more quiet]'
'(-v --verbose -q --quiet)'{-v,--verbose}'[print a message for each action]'
'(- :)'{-V,--version}'[print program version and exit]'
'(- :)'{-h,--help}'[show usage and exit]'
)

# options suitable for /hsh.*/
common_opts=(
'--hasher-priv-dir=[hasher-priv directory]:hasher-priv:_directories'
'--number=[subconfig identifier]:number'
'--workdir=[workdir]:hasher workdir:_directories'
'(--no-wait-lock)--wait-lock[wait for workdir and hasher-priv locks]'
'(--wait-lock)--no-wait-lock[do not wait for workdir and hasher-priv locks]'
)

__repo=(
'(--repo,--repo-bin,--repo-src)--repo=[destination repository directory]: :_directories'
'(--repo)--repo-bin=[binary packages destination directory]: :_directories'
'(--repo)--repo-src=[source packages destination directory]: :_directories'
)

# aptbox-exclusive
aptbox_opts=(
'--apt-config=[path to custom apt.conf file]:apt-config:_files'
'--apt-prefix=[path to apt directory prefix]:apt-prefix:_directories'
$__repo
'--target=[target architecture]:architecture'
)

mountpoints_opt='--mountpoints=[comma-separated list of known mount points]:mountpoints:'

# options for hsh, hsh-rebuild
builder_opts=(
'--build-srpm-only[do not build binary packages]'
'--images[image output directory]:_directories'
'--img-apt-config[custom apt.conf for image building]:_files'
'--repo-mountpoints=[comma-separated list of repo mountpoints]:repo mountpoints:'
'--rebuild-prog=[program to run to query for rebuild]:rebuild-prog:_files -g "*(-*)"'
'(--query-req-prog)--query-repackage[repackage the source before query for requirements]'
'(--query-repackage)--query-req-prog=[program to run to query for requirements]:query-req-prog:_files -g "*(-*)"'
$__repo
'--target=[target architecture]:architecture: '
)

# options for non-runners: hsh, -install, -rebuild
nonsh_opts=(
'--excludedocs[do not install documentation files]'

)

no_sis_check_opts=(
'(--no-sisyphus-check'{,-in,-out}')--no-sisyphus-check-in=[do not run sisyphus_check input tests]::sisyphus_check tests:_sisyphus_check_tests'
'(--no-sisyphus-check'{,-in,-out}')--no-sisyphus-check=[do not run sisyphus_check tests]::sisyphus_check tests:_sisyphus_check_tests'
'(--no-sisyphus-check'{,-in,-out}')--no-sisyphus-check-out=[do not run sisyphus_check output tests]::sisyphus_check tests:_sisyphus_check_tests'
)

srcrpm_or_pkgtar='"*.(src.rpm|tar)"'

# New tools do not support the positional workdir argument.
case "$service" in
    hsh-copy)
        workdir_arg='' ;;
    *)
        workdir_arg='::workdir:_directories'
        ;;
esac

case "$service" in
    hsh)
        if (( $words[(I)--(initroot|cleanup)-only] )); then
            packages=
        else
            packages='*:source package:_files -g '"$srcrpm_or_pkgtar"
        fi
        # TODO: replace --args and --build-args with --rpmbuild-args on completion attempt,
        #       possibly -M 'm:--build-args=--rpmbuild-args r:|[_-]=* r:|=*'
        _arguments -S \
            $help_opts \
            $common_opts \
            $builder_opts \
            $nonsh_opts \
            $aptbox_opts \
            '--'{rpm,}'build-args=[extra arguments for rpmbuild]:rpmbuild args:' \
            '--cache-compress[specify executable to compress cache with]:_normal -e' \
            '--cache-dir[specify alternative cache directory]:_directories' \
            '(--initroot-only)--cleanup-only[do not build at all, just cleanup workdir]' \
            '--eager-cleanup[cleanup build environment after each successful build]' \
            '--lazy-cleanup[cleanup build environment before each new build]' \
            '(--cleanup-only)--initroot-only[do not build, stop after initroot stage]' \
            '--install-langs=[colon-separated list of languages to install]:languages' \
            $mountpoints_opt \
            '--no-cache[do not use initroot cache]' \
            '--no-contents-indices[do not use content indices]' \
            '(--repackage-source)--no-repackage-source[do not repackage source along with binaries]' \
            $no_sis_check_opts \
            '--nprocs=[number of CPUs to use]:number' \
            '--packager=[override default RPM packager tag]:packager:' \
            '--predb-prog=[program to run before rpmi --justdb]:predb-prog:_files -g "*(-*)"' \
            '--printenv[show configuration environment variables]' \
            '--pkg-build-list=[override default build package file list]:packages' \
            '--pkg-init-list=[override default initial package file list]:packages' \
            '(--no-repackage-source)--repackage-source[repackage source along with binaries]' \
            '--save-fakeroot[save fakeroot state]' \
            '(--with-stuff)--without-stuff[do not use built packages]' \
            '(--without-stuff)--with-stuff[allow use of built packages]' \
            "$workdir_arg" \
            $packages && ret=0
        ;;
    hsh-install)
        _arguments -S \
            $help_opts \
            $common_opts \
            $nonsh_opts \
            $mountpoints_opt \
            "$workdir_arg" \
            '*:package name' && ret=0
        ;;
    hsh-rebuild)
        _arguments -S \
            $help_opts \
            $common_opts \
            $builder_opts \
            $nonsh_opts \
            '--'{rpmbuild-,}'args=[extra arguments for rpmbuild]: : ' \
            '--install-only[do not build, stop after installing build dependencies]' \
            $mountpoints_opt \
            '--nodeps[ignore package dependencies (dangerous)]' \
            $no_sis_check_opts \
            '--source-only[do not build, stop after installing source package]' \
            '(--with-stuff)--without-stuff[do not generate apt index files]' \
            '(--without-stuff)--with-stuff[generate apt index files]' \
            "$workdir_arg" \
            ':source package:_files -g '"$srcrpm_or_pkgtar" && ret=0
        ;;
    hsh-run|hsh-shell)
        _arguments -S \
            $help_opts \
            $common_opts \
            '(--rooter)--builder[run program as builder]' \
            '--execute=[copy given script to workdir and execute it]:script:_files' \
            $mountpoints_opt \
            '--pty[redirect standard descriptors to controlling pty]' \
            '(--builder)--rooter[run program as pseudoroot]' \
            '--shell=[run a custom interactive shell]::shell:_files -g "*(-*)"' \
            '--x11-timeout=[how long X11 authorization will be valid]:seconds' \
            '(-x -X -Y)-x[disable X11 forwarding]' \
            '(-x -X -Y)-X[enable X11 forwarding]' \
            '(-x -X -Y)-Y[enable trusted X11 forwarding]' \
            "$workdir_arg" \
            '*::command:= _normal -e' && ret=0
        ;;
    hsh-copy)
        _arguments -C -S \
            $help_opts \
            $common_opts \
            '(--rooter)--builder[assume builder]' \
            '(--builder)--rooter[assume pseudoroot]' \
            ':source:_files' \
            '*: :->dest-or-sources' && ret=0

        case $state in
        dest-or-sources)
            local -a specs=(
                'files:source:_files'
            )

            local def_dest_prefix
            local workdir=${~opt_args[--workdir]}
            if [[ -z "$workdir" ]]; then
                # The hasher project CLI assumes ~/hasher as the default workdir.
                workdir="$HOME/hasher"
            fi
            def_dest_prefix="$(realpath -q -e -- $workdir/chroot)"
            if [[ -d "$def_dest_prefix" ]]; then
                local home="/usr/src"
                [[ "${words[(I)--builder]}" -ge "${words[(I)--rooter]}" ]] || home="/root"
                def_dest_prefix="$def_dest_prefix$home"
                local def_dest_action="_files -W ${(q)def_dest_prefix}"
                specs+=( 'destination-files:destination:'"$def_dest_action" )
            else
                _message 'no valid destinations in workdir'
            fi
            _alternative "${(@)specs}"
            ;;
        esac
        ;;
    mkaptbox)
        _arguments -S \
            $help_opts \
            $aptbox_opts \
            '(-f --force)'{-f,--force}'[force aptbox creation]' \
            '(-u --update)--no-update[do not run "apt-get update" after creation]' \
            '(-u --update --no-update)'{-u,--update}'[run "apt-get update" after creation]' \
            '(--with-stuff)--without-stuff[do not configure sources.list for the work repository]' \
            '(--without-stuff)--with-stuff[configure sources.list for the work repository]' \
            ':workdir:_directories' && ret=0
        ;;

    esac

    return $ret
