#! /bin/bash

_complete_() {
    local options_with_args=$1
    local boolean_options="$2 -h --help"
    local transports=$3

    local option_with_args
    for option_with_args in $options_with_args $transports
    do
        if [ "$option_with_args" == "$prev" ] || [ "$option_with_args" == "$cur" ]
        then
            return
        fi
    done

    case "$cur" in
        -*)
            while IFS='' read -r line; do COMPREPLY+=("$line"); done < <(compgen -W "$boolean_options $options_with_args" -- "$cur")
            ;;
        *)
            if [ -n "$transports" ]
            then
                compopt -o nospace
                while IFS='' read -r line; do COMPREPLY+=("$line"); done < <(compgen -W "$transports" -- "$cur")
            fi
            ;;
    esac
}

_skopeo_supported_transports() {
    local subcommand=$1

    skopeo "$subcommand" --help | grep "Supported transports" -A 1 | tail -n 1 | sed -e 's/,/:/g' -e 's/$/:/'
}

_skopeo_copy() {
    local options_with_args="
    --authfile
    --src-authfile
    --dest-authfile
    --format -f
    --sign-by
    --src-creds --screds
    --src-cert-dir
    --src-tls-verify
    --dest-creds --dcreds
    --dest-cert-dir
    --dest-tls-verify
    --src-daemon-host
    --dest-daemon-host
    "

    local boolean_options="
    --all
    --dest-compress
    --remove-signatures
    --src-no-creds
    --dest-no-creds
    --dest-oci-accept-uncompressed-layers
    "

    local transports
    transports="
    $(_skopeo_supported_transports "${FUNCNAME//"_skopeo_"/}")
    "

    _complete_ "$options_with_args" "$boolean_options" "$transports"
}

_skopeo_inspect() {
     local options_with_args="
     --authfile
     --creds
     --cert-dir
     "
     local boolean_options="
     --config
     --raw
     --tls-verify
     --no-creds
    "

    local transports
    transports="
    $(_skopeo_supported_transports "${FUNCNAME//"_skopeo_"/}")
    "

    _complete_ "$options_with_args" "$boolean_options" "$transports"
}

_skopeo_standalone_sign() {
     local options_with_args="
       -o --output
     "
     local boolean_options="
     "
    _complete_ "$options_with_args" "$boolean_options"
}

_skopeo_standalone_verify() {
     local options_with_args="
     "
     local boolean_options="
     "
    _complete_ "$options_with_args" "$boolean_options"
}

_skopeo_manifest_digest() {
     local options_with_args="
     "
     local boolean_options="
     "
    _complete_ "$options_with_args" "$boolean_options"
}

_skopeo_delete() {
     local options_with_args="
     --authfile
     --creds
     --cert-dir
     "
     local boolean_options="
     --tls-verify
     --no-creds
     "

    local transports
    transports="
    $(_skopeo_supported_transports "${FUNCNAME//"_skopeo_"/}")
    "

    _complete_ "$options_with_args" "$boolean_options" "$transports"
}

_skopeo_layers() {
     local options_with_args="
       --creds
       --cert-dir
     "
     local boolean_options="
       --tls-verify
     "
    _complete_ "$options_with_args" "$boolean_options"
}

_skopeo_list_repository_tags() {
     local options_with_args="
     --authfile
     --creds
     --cert-dir
     "

     local boolean_options="
     --tls-verify
     --no-creds
     "
    _complete_ "$options_with_args" "$boolean_options"
}

_skopeo_login() {
    local options_with_args="
    --authfile
    --cert-dir
    --password -p
    --username -u
    "

    local boolean_options="
    --get-login
    --tls-verify
    --password-stdin
    "
    _complete_ "$options_with_args" "$boolean_options"
}

_skopeo_logout() {
    local options_with_args="
    --authfile
    "

    local boolean_options="
    --all -a
    "
    _complete_ "$options_with_args" "$boolean_options"
}

_skopeo_skopeo() {
     # XXX: Changes here need to be refleceted in the manually expanded
     # string in the `case` statement below as well.
     local options_with_args="
       --policy
       --registries.d
       --override-arch
       --override-os
       --override-variant
       --command-timeout
       --tmpdir
     "
     local boolean_options="
       --insecure-policy
       --debug
       --version -v
       --help -h
     "

     local commands=(
       copy
       delete
       inspect
       list-tags
       login
       logout
       manifest-digest
       standalone-sign
       standalone-verify
       sync
       help
       h
     )

     case "$prev" in
         # XXX: Changes here need to be refleceted in $options_with_args as well.
         --policy|--registries.d|--override-arch|--override-os|--override-variant|--command-timeout)
             return
             ;;
     esac

     case "$cur" in
         -*)
             while IFS='' read -r line; do COMPREPLY+=("$line"); done < <(compgen -W "$boolean_options $options_with_args" -- "$cur")
             ;;
         *)
             while IFS='' read -r line; do COMPREPLY+=("$line"); done < <(compgen -W "${commands[*]} help" -- "$cur")
             ;;
     esac
}

_cli_bash_autocomplete() {
     local cur

     COMPREPLY=()
     cur="${COMP_WORDS[COMP_CWORD]}"
     COMPREPLY=()
     local cur prev words cword

     _get_comp_words_by_ref -n : cur prev words cword

     local command="skopeo" cpos=0
     local counter=1
     while [ $counter -lt "$cword" ]; do
         case "${words[$counter]}" in
             skopeo|copy|inspect|delete|manifest-digest|standalone-sign|standalone-verify|help|h|list-repository-tags)
                 command="${words[$counter]//-/_}"
                 cpos=$counter
                 (( cpos++ ))
                 break
                 ;;
         esac
         (( counter++ ))
     done

     local completions_func=_skopeo_${command}
     declare -F "$completions_func" >/dev/null && $completions_func

     return 0
}

 complete -F _cli_bash_autocomplete skopeo
