#!/bin/bash
# SPDX-Version: 3.0
# SPDX-CreationInfo: 2025-06-17; WEIDNER, Marc S.; <msw@coresecret.dev>
# SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.installer.git
# SPDX-FileContributor: WEIDNER, Marc S.; Centurion Intelligence Consulting Agency
# SPDX-FileCopyrightText: 2024-2025; WEIDNER, Marc S.; <msw@coresecret.dev>
# SPDX-FileType: SOURCE
# SPDX-License-Identifier: EUPL-1.2 OR LicenseRef-CCLA-1.0
# SPDX-LicenseComment: This file is part of the CISS.debian.installer.secure framework.
# SPDX-PackageName: CISS.debian.installer
# SPDX-Security-Contact: security@coresecret.eu

guard_sourcing

#######################################
# Log level values for comparison.
# Arguments:
#   1: LOG_LEVEL: "debug" | "info" | "notice" | "warn" | "error" | "critical" | "fatal" | "emergency"
#######################################
log_level_value() {
  case "${1,,}" in
    debug)     printf '%d' 7 ;;
    info)      printf '%d' 6 ;;
    notice)    printf '%d' 5 ;;
    warn)      printf '%d' 4 ;;
    error)     printf '%d' 3 ;;
    critical)  printf '%d' 2 ;;
    fatal)     printf '%d' 1 ;;
    emergency) printf '%d' 0 ;;
  esac
}

#######################################
# Filter and compare log levels.
# Globals:
#   VAR_DEFAULT_LOG_LEVEL
# Arguments:
#   1: LOG_LEVEL: "debug" | "info" | "notice" | "warn" | "error" | "critical" | "fatal" | "emergency"
#######################################
do_should_log() {
  # shellcheck disable=SC2155
  declare -i var_desired_log_value=$(log_level_value "$1")                   # Desired log level
  # shellcheck disable=SC2155
  declare -i var_default_log_value=$(log_level_value "${VAR_DEFAULT_LOG_LEVEL}") # Current threshold
  ###  Return true if a message should be logged.
  [[ ${var_desired_log_value} -le ${var_default_log_value} ]]
}

#######################################
# Log level color retriever.
# Globals:
#   BLU
#   GRE
#   MAG
#   RED
#   WHI
#   YEL
# Arguments:
#   1: LOG_LEVEL: "debug" | "info" | "notice" | "warn" | "error" | "critical" | "fatal" | "emergency"
#######################################
do_get_log_color() {
  case "${1,,}" in
    debug) echo "${WHI}" ;;
    info) echo "${GRE}" ;;
    notice) echo "${YEL}" ;;
    warn | error | critical) echo "${RED}" ;;
    fatal | emergency) echo "${MAG}" ;;
    *) echo "${BLU}" ;;
  esac
}

#######################################
# Main logger wrapper.
# Globals:
#   LOG_ERR
#   LOG_INS
# Arguments:
#   1: LOG_LEVEL: "debug" | "info" | "notice" | "warn" | "error" | "critical" | "fatal" | "emergency"
#   2: LOG_ONLY: "file_only" | "tty"
#   *: Arbitrary text string to log.
#######################################
do_log() {
  ### Reading arguments.
  declare var_log_level="$1"; shift
  declare var_log_only="$1"; shift
  declare var_msg_string="${*}"

  ### Declare variables.
  declare log_uniform=""
  declare var_color; var_color=$(do_get_log_color "${var_log_level}")
  declare var_ts; var_ts="$(date -u '+%Y-%m-%dT%H:%M:%S.%9N%z')"

  case "${var_log_level,,}" in
    debug)     log_uniform="[DEBUG]    ";;
    info)      log_uniform="[INFO]     ";;
    notice)    log_uniform="[NOTICE]   ";;
    warn)      log_uniform="[WARNING]  ";;
    error)     log_uniform="[ERROR]    ";;
    critical)  log_uniform="[CRITICAL] ";;
    fatal)     log_uniform="[FATAL]    ";;
    emergency) log_uniform="[EMERGENCY]";;
  esac

  declare var_log_entry=("${var_ts} ${log_uniform}: ${var_msg_string}")

  if do_should_log "${var_log_level}"; then
    if [[ "${var_log_only,,}" == "file_only" ]]; then
      case "${var_log_level,,}" in
        debug | info | notice)  do_print_log "${var_log_entry[*]}" >> "${LOG_INS}" ;;
        warn | error | critical | fatal | emergency ) do_print_log "${var_log_entry[*]}" >> "${LOG_ERR}" ;;
      esac
    elif [[ "${var_log_only,,}" == "tty" ]]; then
      case "${var_log_level,,}" in
        debug | info | notice)
          if [[ ${#var_msg_string} -le 76 ]]; then
            do_print_color "${var_color}" "${var_log_entry[*]}"
            do_print_log "${var_log_entry[*]}" >> "${LOG_INS}"
          else
            do_print_fold "${var_color}" "${var_log_entry[*]}"
            do_print_log "${var_log_entry[*]}" >> "${LOG_INS}"
          fi
          ;;
        warn | error | critical | fatal | emergency)
          if [[ ${#var_msg_string} -le 76 ]]; then
            do_print_color "${var_color}" "${var_log_entry[*]}"
            do_print_log "${var_log_entry[*]}" >> "${LOG_ERR}"
          else
            do_print_fold "${var_color}" "${var_log_entry[*]}"
            do_print_log "${var_log_entry[*]}" >> "${LOG_ERR}"
          fi
          ;;
        *)
          if [[ ${#var_msg_string} -le 76 ]]; then
            do_print_color "${var_color}" "${var_log_entry[*]}"
            do_print_log "${var_log_entry[*]}" >> "${LOG_INS}"
          else
            do_print_fold "${var_color}" "${var_log_entry[*]}"
            do_print_log "${var_log_entry[*]}" >> "${LOG_INS}"
          fi
          ;;
      esac
    fi
  fi
}
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh
