# -*- mode: sh -*-
#
# Provides bash programmable completion for rtg commands and flags.
# To use this, you need to source the file. e.g.:
#
# . /path/to/rtg/scripts/rtg-bash-completion
#
# To enable permanently, put that command into your $HOME/.bashrc
#


# NOTE: Some distro bash-completion systems install a _minimal
# completion function that is hooked up dynamically when you try
# completing a command that has no completion function defined yet. On
# these systems, if you've already accidentally attempted to
# tab-complete rtg *before* sourcing this file, it can block us from
# working now. It's easiest to just start a new shell with this file
# sourced before you do any tab completion.
if complete | grep "rtg$" | grep -q -v _complete_rtg; then
    echo "WARNING: It looks like some other form of completion has been registered for rtg commands in this shell. It may be best to start a new shell to avoid unpredictable behaviour."
fi


# Main bash completion function
function _complete_rtg() {
    local rtg=$1
    local cur prev opts cmd flagtype enumvar enumval
    local IFS=$'\n'
    local cmdi=0
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    if [ "$COMP_CWORD" -gt 1 ]; then
        # Scan to look for a subcommand name, skipping RTG_MEM/RTG_JAVA_OPTS being split on = by bash
        # This is not perfect, as it looks like COMP_CWORD doesn't treat quotes in any sane manner.
        for ((cmdi=1, cmdl=0; cmdi < "$COMP_CWORD"; cmdi++, cmdl++)); do
            cmd="${COMP_WORDS[$cmdi]}"
            if [ "${cmd:0:4}" == "RTG_" ]; then
                continue;
            elif [ "${cmd}" == "=" ]; then
                continue;
            elif [ "${COMP_WORDS[$cmdl]}" == "=" ]; then
                continue;
            fi
            break;
        done
    fi
    if [[ "${prev}" == "$rtg" ]] || [[ "$cmdi" -ge "$COMP_CWORD" ]]; then
        _complete_rtgcommands "$rtg"
        COMPREPLY=($(compgen -W "${_rtg_cmds// /$'\n'}" -- "${cur}"))
        return 0
    elif [ "$COMP_CWORD" -gt 1 ]; then
        case "${cur}" in
            --XX*)
                _complete_rtghelp "$rtg" "$cmd" --XXhelp
                opts="$(echo "$_rtg_help" | sed -n '/^  *-/s/^ *\(-., \)\{0,1\}\(--XX[^= ][^= ]*\)[= ].*/\2/p')"
                COMPREPLY=($(compgen -W "${opts}" -- "${cur}"))
                return 0
                ;;
            --X*)
                _complete_rtghelp "$rtg" "$cmd" --Xhelp
                opts="$(echo "$_rtg_help" | sed -n '/^  *-/s/^ *\(-., \)\{0,1\}\(--X[^= ][^= ]*\)[= ].*/\2/p')"
                COMPREPLY=($(compgen -W "${opts}" -- "${cur}"))
                return 0
                ;;
            -*)
                _complete_rtghelp "$rtg" "$cmd" --help
                opts="$(echo "$_rtg_help" | sed -n '/^  *-/s/^ *\(-., \)\{0,1\}\(--[^= ][^= ]*\)[= ].*/\2/p')"
                COMPREPLY=($(compgen -W "${opts}" -- "${cur}"))
                return 0
                ;;
            *)
                _complete_rtghelp "$rtg" "$cmd" --help
                if [ "${prev:0:1}" == "-" ]; then
                    flagtype="$(echo "$_rtg_help" | sed -E -n -e "/  *${prev}.*=[A-Z][A-Z]*/s/.*=([A-Z][A-Z]*)[[:blank:]].*/\1/p")"
                else   # Completion for anonymous flags
                    flagtype="$(echo "$_rtg_help" | sed -E -n -e "/^    *[A-Z][A-Z]*\+?  */s/^  *([A-Z][A-Z]*).*/\1/p")"
                fi
                case ${flagtype} in
                    FILE)
                        COMPREPLY=( $(compgen -o dirnames -f "${cur}") )
                        return 0
                        ;;
	            DIR|SDF)
                        COMPREPLY=( $(compgen -o dirnames -d "${cur}") )
                        return 0
                        ;;
                    *)
                        enumvar="_rtg_${cmd}_${prev//-/_}"
                        enumval="${!enumvar}"
                        if [ "$enumval" ]; then
                            COMPREPLY=( $(compgen -W "${enumval// /$'\n'}" -- "${cur}") )
                        else
                            oifs="$IFS"
                            IFS=$'\n' 
                            COMPREPLY=( $(compgen -f -- "${cur}") )
                            IFS="$oifs"
                        fi
                        return 0
                        ;;
                esac
                ;;
        esac
    fi
}

# Helper for completion that caches list of RTG subcommands. Use cache
# whenever it exists and we are running the same rtg as last time.
function _complete_rtgcommands () {
    local rtg=$1
    if [ -z "$_rtg_cmds" ] || [ -z "$_rtg_lastrtg" ] || [ "$_rtg_lastrtg" != "$rtg" ]; then
        _rtg_lastrtg="$rtg"
        _rtg_cmds="$("$rtg" --Xhelp 2>&1 | sed -E -n '/^'$'\t''[a-z]/s/^[[:blank:]][[:blank:]]*([[:graph:]][[:graph:]]*).*/\1/p') RTG_MEM RTG_JAVA_OPTS"
    fi
}

# Helper for completion that caches help output per command. Use cache
# whenever it exists and we are running the same command as last time.
# Also automatically works out options for enums (e.g. --sex, --format
# --machine) and stashes for later enum expansion into variables named
# e.g. _rtg_format___quality_format="illumina solexa sanger"
function _complete_rtghelp () {
    local rtg=$1
    local cmd=$2
    local help=$3
    local enumvar
    if [ -z "$_rtg_help" ] || [ -z "$_rtg_lastcmd" ] || [ "$_rtg_lastrtg" != "$rtg" ] || [ "$_rtg_lastcmd" != "$cmd$help" ]; then
        _rtg_lastrtg="$rtg"
        _rtg_lastcmd="$cmd$help"
        _rtg_help="$("$rtg" "$cmd" "$help" 2>/dev/null | tr '\n' '\a' | sed -e "s/"$'\a'"            */ /g" | tr '\a' '\n' | sed -n "/^  *[-A-Z]/p")"
        while IFS=' ' read flag rest; do
            enumvar="_rtg_${cmd}___${flag//-/_}"
            # Kind of yuk setting of dynamic variables. Can't use declare -g with bash <4.2
            eval "${enumvar}=\"${rest}\""
        done < <(echo "$_rtg_help" | sed -n -e "s/,//g" -e "/.*--[^=]*=.*Allowed values are/s/.*--\([^=]*\)=.*Allowed values are \[\([^]]*\)\].*/\1 \2/p")
    fi
}

_rtg_lastrtg=
_rtg_cmds=
_rtg_help=
_rtg_lastcmd=

# Main completion hook for default executable name
complete -o filenames -F _complete_rtg rtg

# Let completion also work in the case where people have separate
# executable names for RTG Tools and RTG Core.
complete -o filenames -F _complete_rtg rtg-tools
complete -o filenames -F _complete_rtg rtg-core
