#!/usr/bin/env bash
umask 0027

#------------------------------------------------------------------
# SAP HANA OS checks - Logging Functions
#------------------------------------------------------------------
# Script name: "saphana-logger"
#
#------------------------------------------------------------------

# return if saphana-logger already loaded
[[ -n "${HANA_LOGGER_PROGVERSION:-}" ]] && return 0

HANA_LOGGER_PROGVERSION='loaded'

#exec 3>&2 # logging stream (file descriptor 3) defaults to STDERR

# notify/silent=0 (always), error=1, warn=2, info=3, CHK_verbose=4, debug=5, trace=6
logNotify() { logger 0 '[N]'    "$1"; } # Always prints
logError()  { logger 1 '[E]'    "$1"; }
logWarn()   { logger 2 '[W]'    "$1"; }
logInfo()   { logger 3 '[I]'    "$1"; }
logDebug()  { logger 5 '[D]'    "$1"; }
logTrace()  { logger 6 '[T]'    "$1"; }

function logNewLine {

    if  ! ${LOG_lastLineWasNewLine}; then
        logger 0 '' '';
        LOG_lastLineWasNewLine=true
    fi
}

function logger {

    local loglevel="$1"
    shift 1

    [[ ${loglevel} -gt ${LOG_VERBOSE_LVL} ]] && return

    local logleveltag="$1"
    shift 1

    local datestring
    local -i prefix_length=0
    local -i content_width

    if show_timestamp; then                 #debug/trace or option timestamp set

        datestring=$(date +'%H:%M:%S.%3N ')
        prefix_length=13                    #len("00:04:32.001")+1space

    fi

    if [[ -n $* ]]; then

        (( prefix_length += 17 ))            #len("[C] Lxxxx <ERROR>")
        LOG_lastLineWasNewLine=false

    fi

    if [[ ${prefix_length} -eq 0 ]]; then
        # empty line
        printf '%-*b\n' ${prefix_length} "${datestring:-}${logleveltag}"

    else
        content_width=$((COLUMNS-prefix_length-1))

        # Expand escaped characters, wrap at COLUMNS chars, indent wrapped lines
        # use %b instead of %s for colors
        #printf "%-30b %s\n" "${datestring} ${logleveltag}" "$*" | fold -w ${COLUMNS} | sed '2~1s/^/                        /' #>&3
        if [[ -t 1 ]]; then #FD1 = stdout
            local line
            printf '%s\n' "$*" | fold -w ${content_width} | { read -r line ; printf '%-*b %s\n' ${prefix_length} "${datestring:-}${logleveltag}" "${line}" ; while read -r line ; do printf '%-*s %s\n' ${prefix_length} " " "${line}" ; done }
        else
            printf '%-*b %s\n' ${prefix_length} "${datestring:-}${logleveltag}" "$*"
        fi
    fi
}

function use_colored_output {
    return "${LOG_COLOR_CHECK}"
}

function show_timestamp {
    return "${LOG_TIMESTAMP}"
}

function logCheckError {

    [[ ${LOG_VERBOSE_LVL} -lt 1 ]] && return 1

    local CallerCheck
    printf -v CallerCheck 'L%-4.4s' "${FUNCNAME[1]:6:4}"

    if use_colored_output; then
        logger 1 "[C] ${fmt_error}${CallerCheck} <ERROR>${fmt_reset}"   "$@"
    else
        logger 1 "[C] ${CallerCheck} <ERROR>" "$@"
    fi
}

function logCheckWarning {

    [[ ${LOG_VERBOSE_LVL} -lt 2 ]] && return 1

    local CallerCheck
    printf -v CallerCheck 'L%-4.4s' "${FUNCNAME[1]:6:4}"

    if use_colored_output; then
        #we need the trailing space after fmt_reset, because color formatting prevents padding
        logger 2 "[C] ${fmt_warn}${fmt_blbackgr}${CallerCheck} <WARN>${fmt_reset} " "$@"
    else
        logger 2 "[C] ${CallerCheck} <WARN>" "$@"
    fi
}

function logCheckOk {

    [[ ${LOG_VERBOSE_LVL} -lt 3 ]] && return 1

    local CallerCheck
    printf -v CallerCheck 'L%-4.4s' "${FUNCNAME[1]:6:4}"

    if use_colored_output; then
        #we need the trailing spaces after fmt_reset, because color formatting prevents padding
        logger 3 "[C] ${fmt_ok}${CallerCheck} <OK>${fmt_reset}   "  "$@"
    else
        logger 3 "[C] ${CallerCheck} <OK>" "$@"
    fi
}

function logCheckInfo {

    [[ ${LOG_VERBOSE_LVL} -lt 4 ]] && return 1

    local CallerCheck
    printf -v CallerCheck 'L%-4.4s' "${FUNCNAME[1]:6:4}"

    if use_colored_output; then
        #we need the trailing space after fmt_reset, because color formatting prevents padding
        logger 4 "[C] ${fmt_info}${CallerCheck} <INFO>${fmt_reset} " "$@"
    else
        logger 4 "[C] ${CallerCheck} <INFO>" "$@"
    fi
}

function logCheckSkipped {

    [[ ${LOG_VERBOSE_LVL} -lt 4 ]] && return 1

    local CallerCheck
    printf -v CallerCheck 'L%-4.4s' "${FUNCNAME[1]:6:4}"

    if use_colored_output; then
        #we need the trailing space after fmt_reset, because color formatting prevents padding
        logger 4 "[C] ${fmt_skip}${CallerCheck} <SKIP>${fmt_reset} "    "$@"
    else
        logger 4 "[C] ${CallerCheck} <SKIP>" "$@"
    fi
}


#============================================================
# LIB MAIN - initialization
#============================================================
function _lib_logger_main {

    COLUMNS=80 # required before 1st logger usage

    logTrace "<${BASH_SOURCE[0]}:${FUNCNAME[*]}>"

    # ToDo: -t 1 stdout?
    #  if [[ -t 1 && -n "$TERM" && "$TERM" != "dumb" ]]; then
    if [[ -n "${TERM}" && "${TERM}" != "dumb" ]]; then
        COLUMNS=$(tput cols)
    fi

    fmt_ok='\033[0;32m' # 1=Bold; 32m=Green
    fmt_error='\033[1;31m' # Red
    fmt_warn='\033[0;33m' # Yellow
    fmt_info='\033[1;37m' # Bold gray
    fmt_skip='\033[0;37m' # Light gray
    fmt_blbackgr='\033[40m'    # Black background
    fmt_reset='\033[0m'   #'\033[m\017'
}

# LIB local
declare LOG_lastLineWasNewLine=false

# Variables to be used by other
declare -i LOG_VERBOSE_LVL=3 #notify/silent=0 (always), error=1, warn=2, info=3, CHK_verbose=4, debug=5, trace=6
declare -i LOG_COLOR_CHECK=1 #1=off, 0=on
declare -i LOG_TIMESTAMP=1 #1=off, 0=on

# ToDo: declare -ix ?? - logging should also work for pipes (grep or less)
declare -i COLUMNS
_lib_logger_main
