#-*-shell-script-*-

# Extract from bash_completion
declare -F __reassemble_comp_words_by_ref >/dev/null ||
__reassemble_comp_words_by_ref() {
    local exclude i j line ref
    if [[ $1 ]]; then
        exclude="[${1//[^$COMP_WORDBREAKS]/}]"
    fi

    printf -v "$3" %s "$COMP_CWORD"
    if [[ -v exclude ]]; then
        line=$COMP_LINE
        for ((i = 0, j = 0; i < ${#COMP_WORDS[@]}; i++, j++)); do
            while [[ $i -gt 0 && ${COMP_WORDS[i]} == +($exclude) ]]; do
                [[ $line != [[:blank:]]* ]] && ((j >= 2)) && ((j--))
                ref="$2[$j]"
                printf -v "$ref" %s "${!ref-}${COMP_WORDS[i]}"
                ((i == COMP_CWORD)) && printf -v "$3" %s "$j"
                line=${line#*"${COMP_WORDS[i]}"}
                [[ $line == [[:blank:]]* ]] && ((j++))
                ((i < ${#COMP_WORDS[@]} - 1)) && ((i++)) || break 2
            done
            ref="$2[$j]"
            printf -v "$ref" %s "${!ref-}${COMP_WORDS[i]}"
            line=${line#*"${COMP_WORDS[i]}"}
            ((i == COMP_CWORD)) && printf -v "$3" %s "$j"
        done
        ((i == COMP_CWORD)) && printf -v "$3" %s "$j"
    else
        for i in "${!COMP_WORDS[@]}"; do
            printf -v "$2[i]" %s "${COMP_WORDS[i]}"
        done
    fi
}

__apply_alt_cwd() {
    # Applies alt current working directory to COMPREPLY. See applied
    # rules below.
    for i in "${!COMPREPLY[@]}"; do
        # If item is a directory, append '/' and nospace.
        if [[ -d $1/${COMPREPLY[i]} ]]; then
            COMPREPLY[i]+=/
            compopt -o nospace
        fi
    done
}

__strip_click_directive() {
    # Strips click directive from the variable specified by $1.
    #
    # Click uses their own directive style with `plain,`, `file,`, and
    # `dir,` preceding the list of completions. As we munge together
    # both plain entries and directives, we ignore their directive by
    # stripping it off.
    local name=$1
    local val=${!name}
    if [ "${val:0:6}" = "plain," ]; then
        declare -ag $name="${val:6}"
    elif [ "${val:0:4}" = "dir," ]; then
        declare -ag $name="${val:4}"
    elif [ "${1:0:5}" = "file," ]; then
        declare -ag $name="${val:5}"
    fi
}

_guild_completion() {
    local cword words
    __reassemble_comp_words_by_ref "=:" words cword

    # Use guild to generate comp reply - includes possible directives
    # that are processed later.
    local IFS=$'\n'
    local reply=($(COMP_WORDS="${words[*]}" \
                   COMP_CWORD=$cword \
                   _GUILD_COMPLETE=bash_complete $1))

    COMP_WORDBREAKS='"'"'"'><=;|&(: '  # Reset as can be modified below.
    COMPREPLY=()
    local item alt_cwd
    for item in "${reply[@]}"; do
        __strip_click_directive item
        if [ "${item:0:7}" = '!!file:' ]; then
            COMPREPLY+=($(compgen -f -X '!'"${item:7}" -o plusdirs -- $2 | sort))
            compopt -o filenames
        elif [ "${item:0:7}" = '!!dir' ]; then
            COMPREPLY+=($(compgen -d -- $2 | sort))
            compopt -o filenames
        elif [ "${item:0:12}" = '!!batchfile:' ]; then
            COMPREPLY+=($(compgen -f -X '!'"${item:12}" -P @ -o plusdirs -- ${2:1} | sort))
            compopt -o filenames
        elif [ "${item:0:10}" = '!!rundirs:' ]; then
            alt_cwd="${item:10}"
            COMPREPLY+=($(cd "$alt_cwd" && compgen -d -X .guild -- $2 | sort))
            __apply_alt_cwd "$alt_cwd"
        elif [ "${item:0:13}" = '!!allrundirs:' ]; then
            alt_cwd="${item:13}"
            COMPREPLY+=($(cd "$alt_cwd" && compgen -d -- $2 | sort))
            __apply_alt_cwd "$alt_cwd"
        elif [ "${item:0:11}" = '!!runfiles:' ]; then
            alt_cwd="${item:11}"
            COMPREPLY+=($(cd "$alt_cwd" && compgen -f -X .guild -- $2 | sort))
            __apply_alt_cwd "$alt_cwd"
        elif [ "$item" = "!!nospace" ]; then
            compopt -o nospace
        elif [ "${item:0:10}" = "!!command:" ]; then
            COMPREPLY+=($(compgen -c -X '!'"${item:10}" -- $2 | sort))
        elif [ "$item" = "!!command" ]; then
            COMPREPLY+=($(compgen -c -- $2 | sort))
        elif [ "$item" = "!!no-colon-wordbreak" ]; then
            # Dangerous as this effects other completions. The damage
            # is mitigated by resetting COMP_WORDBREAKS above but this
            # is still not ideal.
            COMP_WORDBREAKS='"'"'"'><=;|&( '
            continue
        else
            COMPREPLY+=($item)
        fi
    done

} && complete -o nosort -F _guild_completion guild 2> /dev/null \
  || complete -F _guild_completion guild
