#
#
# bash completion for archaea tools (hcp, hsync, ...)      -*- shell-script -*-
#
#Bytix Archaea OSS license
#(MIT license just filling 'year' and 'copyright holders')
#
#Copyright (c) 2023 CLEALINK TECHNOLOGY Co., Ltd.
#
#Permission is hereby granted, free of charge, to any person obtaining a copy
#of this software and associated documentation files (the "Software"), to deal
#in the Software without restriction, including without limitation the rights
#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
#copies of the Software, and to permit persons to whom the Software is
#furnished to do so, subject to the following conditions:
#
#The above copyright notice and this permission notice shall be included in all
#copies or substantial portions of the Software.
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
#SOFTWARE.
#

_HCP_HPFP_OPTIONS="--hpfp --hpfp-cong= --hpfp-mss= --hpfp-sndbuf= --hpfp-rcvbuf="
_HCP_WS_OPTIONS="--wss --ws --ws-proxy-direct --ws-proxy= --wss-no-check-certificate"
_HCP_FIO_OPTIONS="--fio-extension --fio-direct --fio-async-linux"
_HCP_FIO_OPTIONS="${_HCP_FIO_OPTIONS} --fio-direct-align= --fio-direct-align-local= --fio-direct-align-remote="
_HCP_FIO_OPTIONS="${_HCP_FIO_OPTIONS} --fio-direct-aligned-malloc= --fio-direct-reuse-aligned --fio-direct-threshold="
_HCP_FIO_OPTIONS="${_HCP_FIO_OPTIONS} --fio-async-max-events= --fio-async-max-get-events= --fio-async-get-events-timeo="
_HCP_FIO_OPTIONS="${_HCP_FIO_OPTIONS} --fio-fallocate= --fio-fallocate-unit="
_HCP_FIO_OPTIONS="${_HCP_FIO_OPTIONS} --fio-no-extension-local --fio-no-extension-remote --fio-extension-always"
_HCP_COMMON_OPTIONS="--version --help --user= --password= --tcp --no-agent --ident-select="
_HCP_COMMON_OPTIONS="${_HCP_COMMON_OPTIONS} --config-test --config-file= --config-option= --hcp-out="
_HCP_COMMON_OPTIONS="${_HCP_COMMON_OPTIONS} --multi-run= --include-conf-from-cwd --no-earlier-serv-compat"
_HCP_COMMON_OPTIONS="${_HCP_COMMON_OPTIONS} --system-info --run-host-benchmark --run-host-benchmark-categories= --show-config-options"
_HSYNC_OPTIONS="${_HCP_COMMON_OPTIONS} --hcp-log-file= --hcp-stat-log-file= ${_HCP_FIO_OPTIONS}" # hsync
_HSYNC_OPTIONS="${_HSYNC_OPTIONS} --no-ahead-listing --ahead-listing-depth= --progress-speed-allow-short-time=" # hsync
_HCP_COMMON_OPTIONS="${_HCP_COMMON_OPTIONS} --stat-log-file= --log-file="
_HPWD_OPTIONS="${_HCP_COMMON_OPTIONS}" # hpwd
_HCP_COMMON_OPTIONS="${_HCP_COMMON_OPTIONS} --port="
_HCP_OPTIONS="${_HCP_COMMON_OPTIONS} --no-skip-hcp-file --no-integrity-on-resume ${_HCP_FIO_OPTIONS}" # hcp
_HCP_OPTIONS="${_HCP_OPTIONS} --no-ahead-listing --ahead-listing-depth= --progress-speed-allow-short-time=" # hcp
_HCP_COMMON_OPTIONS="${_HCP_COMMON_OPTIONS} --host=" # other commands

_hcp_known_hosts_real() {
    local flag ifs=$IFS
    local suffix=""
    local -a kh=() tmpkh=()

    local OPTIND=1
    while getopts "c" flag "$@"
    do
        case $flag in
            c) suffix=':' ;;
            *) return 1 ;;
        esac
    done
    # TODO check $# and OPTIND ?
    
    if [ ! -e ~/.hcp/known_hosts ] ; then
    	return 1
    fi

    kh[0]=~/.hcp/known_hosts
    
    # https://man.openbsd.org/sshd.8#SSH_KNOWN_HOSTS_FILE_FORMAT
    for i in "${kh[@]}"; do
        while read -ra tmpkh; do
            ((${#tmpkh[@]} == 0)) && continue
            set -- "${tmpkh[@]}"
            # Skip entries starting with | (hashed) and # (comment)
            [[ $1 == [\|\#]* ]] && continue
            # Ignore leading @foo (markers)
            [[ $1 == @* ]] && shift
            # Split entry on commas
            local IFS=,
            for host in $1; do
                # Skip hosts containing wildcards
                [[ $host == *[*?]* ]] && continue
                # Remove leading [
                host="${host#[}"
                # Remove trailing ] + optional :port
                host="${host%]?(:+([0-9]))}"
                # Checking duplication from _known_hosts_real (reading ~/.ssh/known_hosts)
                local found=0
                for ehost in ${COMPREPLY[@]}; do
                    [[ "$ehost" = "$host$suffix" ]] && found=1
                done
                # Add host to candidates if the host not already found.
                [[ $found -eq 0 ]] && COMPREPLY+=($host$suffix)
            done
            IFS=$ifs
        done <"$i"
    done
    COMPREPLY=($(compgen -W '${COMPREPLY[@]}' -- "$cur"))
}

_hcp_common_opt_val_reply()
{
    case $prev in
        --config-file | --log-file | --hcp-out)
            compopt +o nospace
            _filedir
            return
            ;;
        --multi-run)
            compopt +o nospace
            _filedir -d
            return
            ;;
        --hpfp-cong)
            compopt +o nospace
            COMPREPLY=($(compgen -W 'FAIR FAIR_FAST_START MODEST AGGRESSIVE DEFAULT' -- "$cur"))
            return
            ;;
        --run-host-benchmark-categories)
            compopt +o nospace
            COMPREPLY=($(compgen -W 'secure integrity disk memory all' -- "$cur"))
            return
            ;;
    esac
}

_hcp()
{
    local cur prev words cword split
    _init_completion -s -n : || return

    _hcp_common_opt_val_reply || return

    case $prev in
        --source-file | --resume)
            compopt +o nospace
            _filedir
            return
            ;;
        --copy-mode | -m)
            compopt +o nospace
            COMPREPLY=($(compgen -W 'ALLCOPY UPDATE DIFF DIFF_STRICT SYNC' -- "$cur"))
            return
            ;;
        --overwrite | -o)
            compopt +o nospace
            COMPREPLY=($(compgen -W 'FORCE RENAME BACKUP SYNC' -- "$cur"))
            return
            ;;
        --fail-action | -a)
            compopt +o nospace
            COMPREPLY=($(compgen -W 'HALT SKIP' -- "$cur"))
            return
            ;;
        --fio-fallocate)
            compopt +o nospace
            COMPREPLY=($(compgen -W 'native standard none' -- "$cur"))
            return
            ;;
        --fio-direct-aligned-malloc)
            compopt +o nospace
            COMPREPLY=($(compgen -W 'posix malloc_h malloc_f' -- "$cur"))
            return
            ;;
        --ahead-listing-depth)
            compopt +o nospace
            COMPREPLY=($(compgen -W '1000 512MB 25GB 500Mbit 200Gbit max' -- "$cur"))
            return
            ;;
        --progress-speed-allow-short-time)
            compopt +o nospace
            COMPREPLY=($(compgen -W '100 100usec 100us 1msec 1ms' -- "$cur"))
            return
            ;;
    esac


    $split && return

    _expand || return

    case $cur in
        -*)
            COMPREPLY=($(compgen -W '--permission --recursive --anydirs --regex --verify
                --compress --copy-linkfile --follow-linkdir --dereference-src --no-emptyfile
                --no-emptydir --no-dotfile --no-dotdir --copy-mode= --overwrite= --fail-action=
                --source-file= --source-file-host= --resume= --auto-resume --no-send 
                --no-diskio= --no-diskio-keep-read --no-diskio-keep-write --no-diskio-keep-memalign
                --mcd= --quiet
                ${_HCP_HPFP_OPTIONS} ${_HCP_WS_OPTIONS} ${_HCP_OPTIONS}' -- $cur))
            [[ ${COMPREPLY-} == *= ]] || compopt +o nospace
            ;;
        *)
            _known_hosts_real -c -a -- "$cur"
            _hcp_known_hosts_real -c -- "$cur"
            _filedir
            ;;
    esac
} &&
    complete -F _hcp -o nospace hcp 

_hsync()
{
    local cur prev words cword split
    _init_completion -s -n : || return

    case $prev in
        --include-from | --exclude-from | --files-from | --log-file | --hcp-log-file)
            compopt +o nospace
            _filedir
            return
            ;;
        --temp-dir | --backup-dir | --partial-dir)
            compopt +o nospace
            _filedir -d
            return
            ;;
        --compress-level)
            compopt +o nospace
            COMPREPLY=($(compgen -W '{1..9}' -- "$cur"))
            return
            ;;
        --fio-fallocate)
            compopt +o nospace
            COMPREPLY=($(compgen -W 'native standard none' -- "$cur"))
            return
            ;;
        --fio-direct-aligned-malloc)
            compopt +o nospace
            COMPREPLY=($(compgen -W 'posix malloc_h malloc_f' -- "$cur"))
            return
            ;;
        --ahead-listing-depth)
            compopt +o nospace
            COMPREPLY=($(compgen -W '1000 512MB 25GB 500Mbit 200Gbit max' -- "$cur"))
            return
            ;;
        --progress-speed-allow-short-time)
            compopt +o nospace
            COMPREPLY=($(compgen -W '100 100usec 100us 1msec 1ms' -- "$cur"))
            return
            ;;
    esac

    $split && return

    _expand || return

    case $cur in
        -*)
            COMPREPLY=($(compgen -W '--verbose --quiet --checksum --archive
                --recursive --relative --no-implied-dirs --backup --backup-dir=
                --suffix= --update --inplace --dirs --links --copy-links
                --copy-unsafe-links --safe-links --copy-dirlinks --keep-dirlinks
                --perms --executability --chmod= --owner --group --devices
                --specials --times --omit-dir-times --super
                --dry-run --dry-run-keep-read --dry-run-keep-write --dry-run-keep-memalign
                --whole-file --one-file-system --existing --ignore-existing
                --delete --delete-before --delete-during --delete-delay
                --delete-after --delete-excluded --max-delete --max-size=
                --min-size= --partial --partial-dir= --delay-updates
                --prune-empty-dirs --numeric-ids --ignore-times --size-only
                --modify-window= --temp-dir= --compress --compress-level
                --filter= --exclude= --exclude-from= --include= --include-from=
                --files-from= --stats --human-readable --progress --itemize-changes
                --out-format= --log-file= --bwlimit= --mcd=
                ${_HCP_HPFP_OPTIONS} ${_HCP_WS_OPTIONS} ${_HSYNC_OPTIONS}' -- $cur))
            [[ ${COMPREPLY-} == *= ]] || compopt +o nospace
            ;;
        *)
            _known_hosts_real -c -a -- "$cur"
            _hcp_known_hosts_real -c -- "$cur"
            _filedir
            ;;
    esac
} &&
    complete -F _hsync -o nospace hsync

_hrm()
{
    local cur prev words cword split
    _init_completion -s -n : || return

    _hcp_common_opt_val_reply || return

    $split && return

    _expand || return

    case $cur in
        -*)
            COMPREPLY=($(compgen -W '--force --recursive --dir --no-diskio=
                ${_HCP_HPFP_OPTIONS} ${_HCP_WS_OPTIONS} ${_HCP_COMMON_OPTIONS}' -- $cur))
            [[ ${COMPREPLY-} == *= ]] || compopt +o nospace
            ;;
        *)
            _known_hosts_real -c -a -- "$cur"
            _filedir
            ;;
    esac
} &&
    complete -F _hrm -o nospace hrm 

_hcp_ls()
{
    local cur prev words cword split
    _init_completion -s -n : || return

    _hcp_common_opt_val_reply || return

    $split && return

    _expand || return

    case $cur in
        -*)
            COMPREPLY=($(compgen -W '--query-cmdname --cmd-options=
                ${_HCP_HPFP_OPTIONS} ${_HCP_WS_OPTIONS} ${_HCP_COMMON_OPTIONS}' -- $cur))
            [[ ${COMPREPLY-} == *= ]] || compopt +o nospace
            ;;
        *)
            _known_hosts_real -c -a -- "$cur"
            _hcp_known_hosts_real -c -- "$cur"
            _filedir
            ;;
    esac
} &&
    complete -F _hcp_ls -o nospace hcp-ls

_hpwd()
{
    local cur prev words cword split
    _init_completion -s -n : || return

    _hcp_common_opt_val_reply || return

    $split && return

    _expand || return

    case $cur in
        -*)
            COMPREPLY=($(compgen -W '--logical --physical
                ${_HCP_HPFP_OPTIONS} ${_HCP_WS_OPTIONS} ${_HPWD_OPTIONS}' -- $cur))
            [[ ${COMPREPLY-} == *= ]] || compopt +o nospace
            ;;
        *)
            _known_hosts_real -c -a -- "$cur"
            _hcp_known_hosts_real -c -- "$cur"
            _filedir
            ;;
    esac
} &&
    complete -F _hpwd -o nospace hpwd

_hmkdir()
{
    local cur prev words cword split
    _init_completion -s -n : || return

    _hcp_common_opt_val_reply || return

    $split && return

    _expand || return

    case $cur in
        -*)
            COMPREPLY=($(compgen -W '--parents
                ${_HCP_HPFP_OPTIONS} ${_HCP_WS_OPTIONS} ${_HCP_COMMON_OPTIONS}' -- $cur))
            [[ ${COMPREPLY-} == *= ]] || compopt +o nospace
            ;;
        *)
            _known_hosts_real -c -a -- "$cur"
            _hcp_known_hosts_real -c -- "$cur"
            _filedir
            ;;
    esac
} &&
    complete -F _hmkdir -o nospace hmkdir

_hmv()
{
    local cur prev words cword split
    _init_completion -s -n : || return

    _hcp_common_opt_val_reply || return

    $split && return

    _expand || return

    case $cur in
        -*)
            COMPREPLY=($(compgen -W '--force --interactive --no-overwrite
                ${_HCP_HPFP_OPTIONS} ${_HCP_WS_OPTIONS} ${_HCP_COMMON_OPTIONS}' -- $cur))
            [[ ${COMPREPLY-} == *= ]] || compopt +o nospace
            ;;
        *)
            _known_hosts_real -c -a -- "$cur"
            _hcp_known_hosts_real -c -- "$cur"
            _filedir
            ;;
    esac
} &&
    complete -F _hmv -o nospace hmv

_hln()
{
    local cur prev words cword split
    _init_completion -s -n : || return

    _hcp_common_opt_val_reply || return

    $split && return

    _expand || return

    case $cur in
        -*)
            COMPREPLY=($(compgen -W '--force --interactive --no-dereference --symbolic
                --logical --physical
                ${_HCP_HPFP_OPTIONS} ${_HCP_WS_OPTIONS} ${_HCP_COMMON_OPTIONS}' -- $cur))
            [[ ${COMPREPLY-} == *= ]] || compopt +o nospace
            ;;
        *)
            _known_hosts_real -c -a -- "$cur"
            _hcp_known_hosts_real -c -- "$cur"
            _filedir
            ;;
    esac
} &&
    complete -F _hln -o nospace hln

_hchmod()
{
    local cur prev words cword split
    _init_completion -s -n : || return

    _hcp_common_opt_val_reply || return

    $split && return

    _expand || return

    case $cur in
        -*)
            COMPREPLY=($(compgen -W '--recursive
                ${_HCP_HPFP_OPTIONS} ${_HCP_WS_OPTIONS} ${_HCP_COMMON_OPTIONS}' -- $cur))
            [[ ${COMPREPLY-} == *= ]] || compopt +o nospace
            ;;
        *)
            _known_hosts_real -c -a -- "$cur"
            _hcp_known_hosts_real -c -- "$cur"
            _filedir
            ;;
    esac
} &&
    complete -F _hchmod -o nospace hchmod

_hchown()
{
    local cur prev words cword split
    _init_completion -s -n : || return

    _hcp_common_opt_val_reply || return

    $split && return

    _expand || return

    case $cur in
        -*)
            COMPREPLY=($(compgen -W '--no-dereference --recursive --follow-cmd-link-dir
                --follow-all --no-follow
                ${_HCP_HPFP_OPTIONS} ${_HCP_WS_OPTIONS} ${_HCP_COMMON_OPTIONS}' -- $cur))
            [[ ${COMPREPLY-} == *= ]] || compopt +o nospace
            ;;
        *)
            _known_hosts_real -c -a -- "$cur"
            _hcp_known_hosts_real -c -- "$cur"
            _filedir
            ;;
    esac
} &&
    complete -F _hchown -o nospace hchown

