#!/bin/bash

# Flag to disable/enable log into error.log
IS_ERROR_LOG_ENABLE=0
# List of patterns to ignore in error.log
ignore_patterns=()

error_log_ignore_pattern_reset() {
    # Reset pattern to ignore
    ignore_patterns=()

    # Set stderr filtering, if stderr log is enabled
    local error_log_was_enable=$IS_ERROR_LOG_ENABLE
    error_log_disable
    if [[ $error_log_was_enable -eq 1 ]]; then
        error_log_enable
    fi
}

# Add a new pattern to ignore into error.log
error_log_ignore_pattern_add() {
    # Add new pattern to ignore
    local new_pattern="$1"
    ignore_patterns+=("$new_pattern")

    # Set stderr filtering, if stderr log is enabled
    local error_log_was_enable=$IS_ERROR_LOG_ENABLE
    error_log_disable
    if [[ $error_log_was_enable -eq 1 ]]; then
        error_log_enable
    fi
}

# Redirection of stdout and sterr to fd3 et fd4
error_log_enable()
{
    if [[ $IS_ERROR_LOG_ENABLE -eq 0 ]]; then
        # Set flag
        IS_ERROR_LOG_ENABLE=1
        # Sauvegarder stdout (1) et stderr (2). Redirect file descriptor 3 to stdout and file descriptor 4 to stderr
        exec 3>&1 4>&2

        # Create error.log
        touch "$LOG_PATH/error.log"
        # Create user.log
        touch "$LOG_PATH/user.log"

        # Rediriger stderr vers un fichier d'erreurs
        exec 2> >(while read -r line; do
            # Check if we must ignore the message
            local should_ignore=false
            for pattern in "${ignore_patterns[@]}"; do
                if [[ "$line" =~ $pattern ]]; then
                    should_ignore=true
                    break
                fi
            done
            
            if $should_ignore; then
                # Print the message to stdout
                echo -e "\e[33m⚠️  $(basename "$0") The following stderr message is ignored and placed into user.log : \e[0m"
                echo -e "\e[33m$line \e[0m"
                # Log into user.log in yellow
                echo -e "\e[33m$line \e[0m" >> "$LOG_PATH/user.log"
            else
                # Log error messages into error.log
                echo $line >> "$LOG_PATH/error.log"
            fi
        done)
    else
        # Info
        info_print "Error log was already enabled"
    fi
}

# Restore redirection of stdout and sterr to fd3 et fd4
error_log_disable()
{
    if [[ $IS_ERROR_LOG_ENABLE -eq 1 ]]; then
        # Clear flag
        IS_ERROR_LOG_ENABLE=0
        # Restaurer stdout et stderr
        exec 1>&3 2>&4
        # Fermer les descripteurs de sauvegarde
        exec 3>&- 4>&-
    else
        # Info
        info_print "Error log was already disabled"
    fi
}

# Function to print custom error into stderr
error_log_print()
{
    if [[ $IS_ERROR_LOG_ENABLE -eq 0 ]]; then
        # Enable log into file
        error_log_enable
        # Print in red
        echo -e "\e[91m$1\e[0m" 1>&2
        # Disable log into file
        error_log_disable
    else
        # Print in red
        echo -e "\e[91m$1\e[0m" 1>&2
    fi
}

# Function to print custom warning into user.log
user_log_print()
{
    # Print
    echo -e "$1" >> "$LOG_PATH/user.log"
}

on_error_print()
{
    # Save line error
    local line="$1"
    # Save error code
    local error_code="$2"
    local command="${BASH_COMMAND}"

    # Print error message in red
    echo -e "\e[91m$(basename "$0") script error code $error_code occured at line $line : \e[0m"
    echo -e "\e[91m$command \e[0m"
}

on_exit()
{
    if [[ $? -eq 0 ]]; then
        # Print in green
        echo -e "\e[32m✔️  $(basename "$0") script exit with 0 ! \e[0m"
    else
        echo -e "\e[91m❌ $(basename "$0") script exit with error ! \e[0m" # 1>&2   # 1>&2 : redirect stdout to stderr.
    fi
    # Disable log into file
    error_log_disable

    info_print "Exit by trapping the exit signal"
}

trap_signal_disable()
{
    info_print "Disable trap signal"

    trap - ERR
    trap - EXIT
}

info_print()
{
    echo -e "\e[34mℹ️ $(basename "$0") $1 \e[0m"
}

init()
{
    error_log_enable
    trap 'on_error_print $LINENO $?' ERR
    trap "on_exit" EXIT

    set -e
}

init