# shellcheck shell=dash

___X_CMD_LOG_OTHER_LOADED=1

___x_cmd_log____other(){
    case "$1" in
        -h|--help)                  shift;      ___x_cmd help -m log  1>&2; return 1 ;;

        init1)      shift;      ___x_cmd_log_init1          "$@" ;;

        run)                        shift;      ___x_cmd_log_run            "$@" ;;
        default)                    shift;      ___x_cmd_log_level_default  "$@" ;;

        vis)                        shift;      ___x_cmd logvis             "$@" ;;
        uirotate|exec|sub|store|view|timestamp|redirect)
                                    local op="$1";
                                    xrc:mod:lib log     "$op"
                                    shift;      ___x_cmd_log_"$op"          "$@" ;;

        init0|init01|init02)
                                    local op="$1";
                                    xrc:mod:lib log     "init0"
                                    shift;      ___x_cmd_log_"$op"          "$@" ;;

        trace|trace_evex|trace_time|trace_log|trace_start|trace_exit)
                                    local op="$1";
                                    xrc:mod:lib log     "trace"
                                    shift;      ___x_cmd_log_"$op"          "$@" ;;

        ""|recent)                  xrc:mod:lib log     "recent"
                                    shift;      ___x_cmd_log_recent         "$@" ;;

        *)                                      ___x_cmd_log_default        "$@" ;;
    esac
}

___x_cmd_log_init1(){
    ___x_cmd_log_init_inner "$@" 1
}

___x_cmd_log_run(){
    while [ "$#" -gt 0 ]; do
        case "$1" in
            --)     shift;                              break    ;;

            */*)    eval "local ___X_CMD_LOG__${1%/*}" 2>/dev/null; ___x_cmd_log_set_level "${1%/*}" "${1#*/}" ;;
            +*)     eval "local ___X_CMD_LOG__${1#+}" 2>/dev/null;  ___x_cmd_log_set_level "${1#+}" debug ;;
            -*)     eval "local ___X_CMD_LOG__${1#-}" 2>/dev/null;  ___x_cmd_log_set_level "${1#-}" info ;;
            *)      eval "local ___X_CMD_LOG__${1}" 2>/dev/null;    ___x_cmd_log_set_level "$1" info
        esac
        shift
    done

    "$@"
}

___x_cmd_log_default(){
    local ___X_CMD_LOG___GLOBAL_MODE=1
    local ___X_CMD_LOG___ARG
    for ___X_CMD_LOG___ARG in "$@"; do
        if [ "$___X_CMD_LOG___ARG" = -- ]; then
            ___X_CMD_LOG___GLOBAL_MODE=0
            break
        fi
    done

    if [ "$___X_CMD_LOG___GLOBAL_MODE" -eq 0 ]; then
        ___x_cmd_log_run "$@"
        return
    fi

    while [ "$#" -gt 0 ]; do
        case "$1" in
            */*)    ___x_cmd_log_set_level "${1%/*}" "${1#*/}" ;;
            +*)     ___x_cmd_log_set_level "${1#+}" debug ;;
            -*)     ___x_cmd_log_unset_level "${1#-}" ;;
            *)      ___x_cmd_log_set_level "$1" info
        esac
        shift
    done
}

# LOG_ENABLE=-zuz,+a x zuz
# x log run zuz/warn  --  x zuz

___x_cmd_log_get_level_name(){
    # local level_name
    eval ___x_cmd_log_level_code_to_level_name "\$___X_CMD_LOG__${1:?Provide logger name}"
    # printf "%s" "$level_name"
}

___x_cmd_log_show_level(){
    local level_name
    while [ $# -gt 0 ]; do
        eval ___x_cmd_log_level_code_to_level_name "\$___X_CMD_LOG__$1"
        printf "%s = %s\n" "$1" "$level_name"
        shift
    done
}

___x_cmd_log_level_name(){
    case "${1:?Provide name}" in
        d|debug|1)  level_name=debug ;;
        i|info|2)   level_name=info ;;
        w|warn|3)   level_name=warn ;;
        e|error|4)  level_name=error ;;
        n|none|5)   level_name=none ;;
        *)          level_name=info ;;
    esac
}

___x_cmd_log_level_name_to_level_code(){
    case "${1:?Provide name}" in
        debug)      level_code=1 ;;
        info)       level_code=2 ;;
        warn)       level_code=3 ;;
        error)      level_code=4 ;;
        none)       level_code=5 ;;
        *)          level_code=2 ;;
    esac
}


___x_cmd_log_unset_level(){
    x:trace x/log
    local logger_name="${1:?Provide loggername}"

    # TODO: how to check the logger_name is valid?
    if ! ___x_cmd_validenvname "${logger_name}"; then
        ___x_cmd_log_pr x error "Logger Name should be match [0-9A-Za-z_]+ "
        return 1
    fi

    eval "___X_CMD_LOG__${logger_name}="
}

___x_cmd_log_set_level(){
    x:trace x/log
    local logger_name="${1:?Provide loggername}"

    # TODO: how to check the logger_name is valid?
    if ! ___x_cmd_validenvname "${logger_name}"; then
        ___x_cmd_log_pr x error "Logger Name should be match [0-9A-Za-z_]+ "
        return 1
    fi

    local level_name
    ___x_cmd_log_level_name "${2:?Provide level}"

    local level_code="${3}"

    if [ -z "$level_code" ]; then
        ___x_cmd_log_level_name_to_level_code "$level_name"
    fi

    local var="___X_CMD_LOG__${logger_name}"

    if eval test -z "\$___X_CMD_LOG__0_$logger_name"; then
        eval "$var=$level_code"
    else
        eval "$var=$level_code"
        if [ -d "$___X_CMD_ROOT/$logger_name" ]; then
            ___x_cmd_log_pr "${O:-$logger_name}" warn "Reload the logger by reload the module: xrc:mod \"$logger_name/latest\""
            # xrc:mod "$logger_name/latest"
        fi
    fi

    # eval "$O:debug  \"Level of logger [\$logger_name] is set to [\$level]\""
    ___x_cmd_log_pr x info "Level of logger [$logger_name] is set to [$level_name]"
}

