#
# Variables to hold exit status semantic
#
TF_ES_OK=0
TF_ES_FAIL=1
TF_ES_BAILOUT=2
TF_ES_ERROR=3
TF_ES_PANIC=4

#
# Color definition variables
#
TF_COLOR_BLACK="\033[0;30m"
TF_COLOR_RED="\033[0;31m"
TF_COLOR_GREEN="\033[0;32m"
TF_COLOR_YELLOW="\033[0;33m"
TF_COLOR_BLUE="\033[0;34m"
TF_COLOR_MAGENTA="\033[0;35m"
TF_COLOR_CYAN="\033[0;36m"
TF_COLOR_WHITE="\033[0;37m"
TF_COLOR_LBLACK="\033[1;30m"
TF_COLOR_LRED="\033[1;31m"
TF_COLOR_LGREEN="\033[1;32m"
TF_COLOR_LYELLOW="\033[1;33m"
TF_COLOR_LBLUE="\033[1;34m"
TF_COLOR_LMAGENTA="\033[1;35m"
TF_COLOR_LCYAN="\033[1;36m"
TF_COLOR_LWHITE="\033[1;37m"
TF_COLOR_NONE="\033[1;0m"


_tf__is_word() {
    #
    # Check if $1 contains only alphanumeric chars or _
    #
    local tainted=$1    # "dirty" version
    local clean         # clean version
    clean=$(tr -c -d '_[:alnum:]' <<< "$tainted")
    test "$tainted" = "$clean"
}

tf_exit_ok() {
    #
    # Exit with OK status
    #
    exit $TF_ES_OK
}

tf_exit_fail() {
    #
    # Warn $1 and exit with status FAIL
    #
    tf_warn "$@"
    exit $TF_ES_FAIL
}

tf_exit_bailout() {
    #
    # Warn $1 and exit with status FAIL
    #
    tf_warn "$@"
    exit $TF_ES_BAILOUT
}

tf_exit_error() {
    #
    # Warn $1 and exit with status FAIL
    #
    tf_warn "$@"
    exit $TF_ES_ERROR
}

tf_exit_panic() {
    #
    # Warn $1 and exit with status FAIL
    #
    tf_warn "$@"
    exit $TF_ES_PANIC
}

tf_debug() {
    #
    # Emit debug message
    #
    $TF_DEBUG || return 0
    local msg
    for msg in "$@";
    do
        $TF_COLOR && echo -ne "$TF_COLOR_CYAN" >&2
        echo "||| $msg" >&2;
        $TF_COLOR && echo -ne "$TF_COLOR_NONE" >&2
    done
}

tf_debugv() {
    #
    # Emit debug message showing value of each named variable
    #
    local varname
    local declare_str
    for varname in "$@";
    do
        if ! _tf__is_word "$varname";
        then
            tf_warn "tf_debugv: unsafe value skipped: $varname";
            continue
        fi
        if declare_str=$(declare -p "$varname" 2>/dev/null);
        then
            tf_debug "${declare_str#declare ?? }"
        else
            tf_debug "$varname #Unset"
        fi
    done
}

tf_think() {
    #
    # Emit status/progress message
    #
    $TF_VERBOSE || return 0
    local msg
    for msg in "$@";
    do
        $TF_COLOR && echo -ne "$TF_COLOR_LBLACK" >&2
        echo "$pfx$msg$sfx" >&2;
        $TF_COLOR && echo -ne "$TF_COLOR_NONE" >&2
    done
}

tf_warn() {
    #
    # Emit warning
    #
    local msg
    for msg in "$@";
    do
        $TF_COLOR && echo -ne "$TF_COLOR_LRED" >&2
        echo "$msg" >&2;
        $TF_COLOR && echo -ne "$TF_COLOR_NONE" >&2
    done
}