#! /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
    --multi-arch
    --sign-by
    --sign-passphrase-file
    --sign-identity
    --src-creds --screds
    --src-cert-dir
    --src-tls-verify
    --dest-creds --dcreds
    --dest-cert-dir
    --dest-tls-verify
    --src-daemon-host
    --dest-daemon-host
    --src-registry-token
    --dest-registry-token
    --src-username
    --src-password
    --dest-username
    --dest-password
    "

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

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

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

_skopeo_sync() {
    local options_with_args="
    --authfile
    --dest
    --dest-authfile
    --dest-cert-
    --dest-creds
    --dest-registry-token string
    --format
    --retry-times
    --sign-by
    --sign-passphrase-file
    --src
    --src-authfile
    --src-cert-dir
    --src-creds
    --src-registry-token
    --src-username
    --src-password
    --dest-username
    --dest-password
    "

    local boolean_options="
    --all
    --dest-no-creds
    --dest-tls-verify
    --dry-run
    --remove-signatures
    --scoped
    --src-no-creds
    --src-tls-verify
    --keep-going
    --preserve-digests
    "

    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
     --format
     --retry-times
     --registry-token
    --username
    --password
     "
     local boolean_options="
     --config
     --raw
     --tls-verify
     --no-creds
     --no-tags -n
    "

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

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

_skopeo_standalone_sign() {
     local options_with_args="
       -o --output
       --passphrase-file
     "
     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
     --registry-token
    --username
    --password
     "
     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="
       --authfile
       --creds
       --cert-dir
       --registry-token
      --username
      --password
     "
     local boolean_options="
       --tls-verify
       --no-creds
     "
    _complete_ "$options_with_args" "$boolean_options"
}

_skopeo_list_repository_tags() {
     local options_with_args="
     --authfile
     --creds
     --cert-dir
     --registry-token
    --username
    --password
     "

     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 reflected 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 reflected 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|sync|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
