#!/usr/bin/env bash

_check_ssl_cert() {

    local cur prev opts

    COMPREPLY=()

    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD - 1]}"

    #
    # list of command line options
    #   only the autocompletion with long options is implemented: long options are more readable and quick to enter since we are
    #   using autocompletion.
    #
    opts="--file --host --noauth --all --all-local --allow-empty-san --clientcert --configuration --critical --check-chain --check-ciphers --check-ciphers-warnings --check-http-headers --check-ssl-labs --check-ssl-labs-warn --clientpass --crl --curl-bin --user-agent --custom-http-header --dane --date --debug-cert --debug-file --debug-headers --debug-time --default-format --dig-bin --dtls --dtls1 --dtls1_2 --ecdsa --element --file-bin --fingerprint --first-element-only --force-dconv-date --force-perl-date --format --grep-bin --http-headers-path --http-use-get --ignore-altnames --jks-alias --ignore-connection-problems --ignore-exp --ignore-http-headers --ignore-host-cn --ignore-incomplete-chain --ignore-maximum-validity --ignore-ocsp --ignore-ocsp-errors --ignore-ocsp-timeout --ignore-sct --ignore-sig-alg --ignore-ssl-labs-cache --ignore-tls-renegotiation --inetproto protocol --info --init-host-cache --issuer-cert-cache --long-output --match --maximum-validity --nmap-bin --no-perf --no-proxy --no-proxy-curl --no-proxy-s_client --no-ssl2 --no-ssl3 --no-tls1 --no-tls1_1 --no-tls1_2 --no-tls1_3 --not-issued-by --not-valid-longer-than --ocsp-critical --ocsp-warning --openssl --password --path --precision --prometheus --proxy --require-client-cert --require-dnssec --require-http-header --require-no-http-header --require-no-ssl2 --require-no-ssl3 --require-no-tls1 --require-no-tls1_1 --require-ocsp-stapling --require-purpose --require-purpose-critical --resolve  --rootcert-dir --rootcert-file --rsa --serial --security-level --skip-element --sni --ssl2 --ssl3 --temp --terse --tls1 --tls1_1 --tls1_2 --tls1_3 --xmpphost -4 -6 --clientkey --protocol --version --debug --email --help --issuer --cn --org  --port port --rootcert --quiet --selfsigned --timeout --url --verbose --warning --python-bin"

    if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]]; then
        # shellcheck disable=2207
        COMPREPLY=($(compgen -W "${opts}" -- "${cur}"))
        return 0
    fi

    #
    # options with arguments: if the option requires an argument we try to autocomplete it if possible
    #
    case "${prev}" in

    # options with files or directories as argument
    -f | --file | -C | --clientcert | --configuration | --curl-bin | --date | --debug-file | --dig-bin | --file-bin | --grep-bin | --issuer-cert-cache | --nmap-bin | --openssl | --rootcert-dir | --rootcert-file | --temp | -K | --clientkey | -r | --rootcert | --python-bin)
        _filedir
        ;;

    # options with hosts as argument
    -H | --host | --resolve)
        _known_hosts_real "${cur}"
        if [[ -r ~/.check_ssl_cert-cache ]]; then
            # concatenate the array with the cached hosts: https://stackoverflow.com/questions/31143874/how-to-concatenate-arrays-in-bash
            # shellcheck disable=2207
            COMPREPLY+=($(compgen -W "$(tr <~/.check_ssl_cert-cache "\n" ' ')" -- "${cur}"))
        fi
        ;;

    # grades
    --check-ciphers | --check-ssl-labs-warn | --check-ssl-labs)
        # shellcheck disable=2207
        COMPREPLY=($(compgen -W "A B C D E F" -- "${cur}"))
        ;;

    --dane)
        # shellcheck disable=2207
        COMPREPLY=($(compgen -W "211 301 302 311 312" -- "${cur}"))
        ;;

    --maximum-validity)
        # shellcheck disable=2207
        COMPREPLY=($(compgen -W "397" -- "${cur}"))
        ;;

    --require-purpose)

        # the argument have spaces: see https://stackoverflow.com/questions/1146098/properly-handling-spaces-and-quotes-in-bash-completion

        # Get the currently completing word
        local CWORD=${COMP_WORDS[COMP_CWORD]}

        # This is our word list (in a bash array for convenience)
        local WORD_LIST=('Digital Signature' 'Key Encipherment' 'Key Agreement' 'Certificate Sign' 'Certificate Revocation List (CRL) Sign' 'CRL Sign')

        # Commands below depend on this IFS
        local IFS=$'\n'

        # Filter our candidates
        # shellcheck disable=2207
        CANDIDATES=($(compgen -W "${WORD_LIST[*]}" -- "$CWORD"))

        # Correctly set our candidates to COMPREPLY
        if [[ ${#CANDIDATES[*]} -eq 0 ]]; then
            COMPREPLY=()
        else
            # shellcheck disable=2207
            COMPREPLY=($(printf '%q\n' "${CANDIDATES[@]}"))
        fi
        ;;

    --require-http-header)

        # shellcheck disable=2207
        COMPREPLY=($(compgen -W "strict-transport-security X-Frame-Options Content-Security-Policy X-Content-Type-Options Referrer-Policy Permissions-Policy X-Permitted-Cross-Domain-Policies" -- "${cur}"))
        ;;

    --require-no-http-header)

        # shellcheck disable=2207
        COMPREPLY=($(compgen -W "X-Powered-By X-Aspnet-Version X-XSS-Protection Server X-AspNetMvc-Version" -- "${cur}"))
        ;;

    --security-level)

        # shellcheck disable=2207
        COMPREPLY=($(compgen -W "0 1 2 3 4 5" -- "${cur}"))
        ;;

    --port | -p)
        # shellcheck disable=2207
        COMPREPLY=($(compgen -W "21 22 80 443 143 993 194 994 389 587 636 3306 3391 110 995 5432 4190 25 465 5222 5269" -- "${cur}"))
        ;;

    --protocol | -P)
        # shellcheck disable=2207
        COMPREPLY=($(compgen -W "dns ftp ftps http https h2 imap imaps irc ircs ldap ldaps mysql pop3 pop3s postgres sieve smtp smtps xmpp xmpp-server tds" -- "${cur}"))
        ;;

    *) ;;

    esac

}

complete -F _check_ssl_cert check_ssl_cert
