# Logging output

log_GETOPTS="qvDV"

LOG=y
LOG_ERROR=y
LOG_WARN=y
LOG_FORCE=y
LOG_APPLY=y
LOG_CHECK=
LOG_CHANGED=
LOG_NOOP=y
LOG_SKIP=
LOG_DEBUG=
LOG_CMD=
LOG_DIFF=y

# use color output?
IS_TTY=

function log_help {
    cat <<END
Logging:    
    -q      quiet
    -v      verbose
    -D      debug
    -V      debug commands
END
}

function log_opt {
    local opt=$1
    local optarg="$2"

    case $opt in
        q)  
            LOG= 
            LOG_WARN=
            LOG_APPLY=
            LOG_FORCE=
            LOG_NOOP=
            LOG_DIFF=
            ;;
        v)  
            LOG_CHANGED=y
            LOG_CHECK=y
            LOG_SKIP=y
            ;;
        D)  
            LOG_DEBUG=y
            LOG_INFO=y
            ;;
        V)  LOG_CMD=y ;;

        n)  LOG_NOOP=y ;;
        *)  return 1
    esac
}

function log_init {
    if [ -t 1 ]; then
        IS_TTY=y
    fi
}

# Output message to stderr.
function log_msg {
    echo "$*" >&2
}

# Output message to stderr, optionally with given color, if TTY.
function log_color {
    local code=$1; shift

    if [ $IS_TTY ]; then
        echo $'\e['${code}'m'"$*"$'\e[00m' >&2
    else
        echo "$*" >&2
    fi
}

## Log at various log-levels
# plain
function log {
    [ $LOG          ] && log_msg            "$*"            || true
}

function log_error {
    [ $LOG_ERROR    ] && log_color '31'     "$*"            || true
}

function log_warn {
    [ $LOG_WARN     ] && log_color '33'     "$*"            || true
}

function log_force {
    [ $LOG_FORCE    ] && log_color '2;33'   "  $*"          || true
}

function log_apply {
    [ $LOG_APPLY    ] && log_color '36'     "  $*"          || true
}

function log_check {
    [ $LOG_CHECK    ] && log_color '32'     "  $*"          || true
}

function log_changed {
    [ $LOG_CHANGED  ] && log_color '1;32'   "  $*"          || true
}

function log_noop {
    [ $LOG_NOOP     ] && log_color '2;34'   "  $*"          || true
}

function log_skip {
    [ $LOG_SKIP     ] && log_color '1;34'   "  $*"          || true
}

function log_debug {
    [ $LOG_DEBUG    ] && log_color '34'     "    $*"        || true
}

function log_cmd {
    [ $LOG_CMD      ] && log_color '35'     "        \$ $*" || true
}

# Output stacktrace, broken.
function log_stack {
    local level=1

    while info=$(caller $level); do
        echo $info | read line sub file

        log_msg "$file:$lineno $sub()"

        level=$(($level + 1))
    done
}

### High-level logging output
# Log with func_caller at log_debug
function debug {
    printf -v prefix "%s" $(func_caller)

    log_debug "$prefix: $*"
}

function warn {
    log_warn "$(func_caller): $*"
}

function error {
    log_error "$(func_caller): $*"
}

# Log with func_caller at log_error and exit, intended for internal errors...
function fail {
    log_error "$(func_caller): $*"

    exit 2
}

# Log at log_error and exit
function die {
    log_error "$*"
    exit 1
}
