# Bash completion function for cave
# Written by Mike Kelly
# vim: set et sw=4 sts=4 ts=4 ft=sh :

# Based in part upon 'git' bash completion from git-1.6.4.2
# Based in part upon a cave bash completion script by Ɓukasz Michalik

__cave_find_cmd() {
    local w c cmd

    for (( c=1; c < COMP_CWORD; c++ )) ; do
        w="${COMP_WORDS[c]}"
        case "${w}" in
            --*) ;;
            --help|-h) cmd="help"; break ;;
            config|@(display|execute)-resolution|help|import|perform|print-@(categories|commands|environment-metadata|id-@(contents|executables|metadata)|ids|owners|packages|repositor@(ies|y-formats)|sets|sync-protocols)|resolve|show|sync|update-world) cmd="${w}"; break ;;
        esac
    done

    echo "${cmd}"
}

__cave_enum_value() {
    local w c v enum="${1}"
    for (( c=COMP_CWORD; c > 1; c-- )) ; do
        w="${COMP_WORDS[c]}"
        if [[ "${w}" =~ ^${enum}$ ]] ; then
            v="${COMP_WORDS[c+1]}"
            break;
        fi
    done

    echo "${v}"
}

__cave_compgen() {
    COMPREPLY=( $(compgen -W "$*" -- "${cur}") )
}

__cave_global() {
    case "${prev}" in
        --log-level)
            __cave_compgen "debug qa warning silent"
            ;;
        --environment|-E)
            __cave_compgen "paludis: portage:"
            ;;
        *)
            __cave_compgen "$(cave print-commands -a) -E --environment --log-level"
            ;;
    esac
}

__cave_help() {
    # only complete once
    if [[ "${prev}" == "help" ]] ; then
        __cave_compgen "$(cave print-commands -a) -a --all -h --help"
    fi
}

__cave_sync() {
    __cave_compgen "$(cave print-repositories) --sequential -h --help"
}

__cave_show() {
    local type="$(__cave_enum_value '--type|-t')"
    case "${prev}" in
        --type|-t)
            __cave_compgen "auto repository set wildcard package"
            ;;
        *)
            case "${cur}" in
                -*)
                    __cave_compgen "--type -t --complex-keys -c --internal-keys -i --flat -f --raw-names -r --help"
                    ;;
                *)
                    case "${type}" in
                        repository)
                            __cave_compgen "$(cave print-repositories)"
                            ;;
                        set)
                            __cave_compgen "$(cave print-sets)"
                            ;;
                        package)
                            __cave_compgen "$(cave print-packages)"
                            ;;
                        auto|wildcard|*)
                            # TODO: provide reasonable completions for 'spec' here
                            COMPREPLY=()
                            ;;
                    esac
                    ;;
            esac
            ;;
    esac
}

__cave_resolve_options="-h --help
        -x --execute --no-execute
        -z --lazy --no-lazy
        -c --complete --no-complete
        -e --everything --no-everything
        -U --permit-uninstall
        -d --permit-downgrade
        -o --permit-old-version
        -K --keep-targets
        -k --keep
        -R --reinstall-scm
        -w --with
        -W --without
        -S --target-slots
        -s --slots
        -D --follow-installed-build-dependencies --no-follow-installed-build-dependencies
        -n --no-follow-installed-dependencies --no-no-follow-installed-dependencies
        -0 --no-dependencies-from
        -! --no-blockers-from
        --suggestions
        --recommendations
        -t --take
        -T --take-from
        -i --ignore
        -I --ignore-from
        -F --favour
        -A --avoid
        -p --preset
        -b --create-binaries
        -B --no-binaries-for
        -/ --install-to-root --no-install-to-root
        -2 --chroot-path
        --dump --no-dump
        --dump-restarts --no-dump-restarts
        -1 --preserve-world --no-preserve-world
        -C --continue-on-failure
        --skip-phase
        --abort-at-phase
        --skip-until-phase
        --change-phases-for
        --show-option-descriptions
        --show-descriptions
        -X --explain
        --show-all-jobs --no-show-all-jobs
        --display-resolution-program
        --execute-resolution-program
        --perform-program
        --update-world-program"

__cave_resolve() {
    case "${prev}" in
        -K|--keep-targets)
            __cave_compgen "auto never if-transient if-same if-same-version if-possible"
            ;;
        -k|--keep)
            __cave_compgen "never if-transient if-same if-same-version if-possible"
            ;;
        -R|--reinstall-scm)
            __cave_compgen "always daily weekly never"
            ;;
        -w|--with|-W|--without)
            __cave_compgen "$(cave print-packages)"
            ;;
        -S|--target-slots|-s|--slots)
            __cave_compgen "best-or-installed installed-or-best all best"
            ;;
        --suggestions|--recommendations)
            __cave_compgen "ignore display take"
            ;;
        -C|--continue-on-failure)
            __cave_compgen "never if-satisfied if-independent always"
            ;;
        --change-phases-for)
            __cave_compgen "all first last"
            ;;
        --show-option-descriptions)
            __cave_compgen "none new changed all"
            ;;
        --show-descriptions)
            __cave_compgen "none new all"
            ;;
        --skip-phase|--abort-at-phase|--skip-until-phase)
            __cave_compgen "fetch_extra killold init setup unpack prepare configure compile test test_expensive install strip preinst merge prerm postrm postinst tidyup"
            ;;
        -[UdawW0!tTiIFApBX]|--@(permit-@(uninstall|downgrade|any-version)|with?(out)|no-@(dependencies|blockers)-from|@(take|ignore)?(-from)|favor|avoid|preset|no-binaries-for|explain))
            # TODO: better completion here
            COMPREPLY=()
            ;;
        --@(@(display|execute)-resolution|perform|update-world)-program)
            _filedir
            ;;
        *)
            case "${cur}" in
                -*)
                    __cave_compgen "${__cave_resolve_options}"
                    ;;
                *)
                    __cave_compgen "${__cave_resolve_options}
                        $(cave print-packages)
                        $(cave print-sets)"
                    ;;
            esac
            ;;
    esac
}

__cave_import_options="${__cave_resolve_options}
    -l --location
    -u --install-under
    -r --rewrite-uids-over-to-root
    -D --description
    -B --build-dependency
    -R --run-dependency
    -P --preserve-metadata"

__cave_import() {
    case "${prev}" in
        -l|--location|-u|--install-under)
            _filedir
            ;;
        -r|--rewrite-uids-over-to-root)
            _uids
            ;;
        -D|--description)
            COMPREPLY=()
            ;;
        -B|--build-dependency|-R|--run-dependency|-P|--preserve-metadata)
            __cave_compgen "$(cave print-packages)"
            ;;
        -*)
            # all the other options are the same as with __cave_resolve
            __cave_resolve
            ;;
        *)
            case "${cur}" in
                -*)
                    __cave_compgen "${__cave_import_options}"
                    ;;
                *)
                    # TODO: make this more correct (only one package
                    # name, then version, then slot)
                    __cave_compgen "${__cave_import_options}
                        $(cave print-packages)"
                    ;;
            esac
            ;;
    esac
}

_cave() {
    local cmd=`__cave_find_cmd` prev=`_get_pword 2>/dev/null || echo ${COMP_WORDS[COMP_CWORD-1]}` cur=`_get_cword`

    COMPREPLY=()

    if [[ -z "${cmd}" ]] ; then
        __cave_global
    else
        if [[ "$(type -t "__cave_${cmd}")" == "function" ]] ; then
            "__cave_${cmd}"
        fi
    fi
}
complete -F _cave cave