/**
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * This program is free software, you can redistribute it and/or modify it under the terms and conditions of 
 * CANN Open Software License Agreement Version 2.0 (the "License").
 * Please refer to the License for details. You may not use this file except in compliance with the License.
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, 
 * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
 * See LICENSE in the root of the software repository for the full text of the License.
 */

#include "log_inner.h"

#include "base/err_msg.h"

namespace acl {
bool AclLog::isEnableEvent_ = false;
constexpr size_t const ACL_LIMIT_PER_MESSAGE = 1024U;

std::string AclGetErrorFormatMessage(const mmErrorMsg errnum)
{
    char_t errBuff[acl::MAX_ERROR_STRING + 1U] = {};
    const auto msgPtr = mmGetErrorFormatMessage(errnum, &errBuff[0], acl::MAX_ERROR_STRING);
    const auto errMessage = (msgPtr == nullptr) ? "" : msgPtr;
    return std::string(errMessage);
}

aclLogLevel AclLog::GetCurLogLevel()
{
    int32_t eventEnable = 0;
    const int32_t dlogLevel = dlog_getlevel(ACL_MODE_ID, &eventEnable);
    aclLogLevel curLevel = ACL_INFO;
    switch (dlogLevel) {
        case DLOG_ERROR:
            curLevel = ACL_ERROR;
            break;
        case DLOG_WARN:
            curLevel = ACL_WARNING;
            break;
        case DLOG_INFO:
            curLevel = ACL_INFO;
            break;
        case DLOG_DEBUG:
            curLevel = ACL_DEBUG;
            break;
        default:
            break;
    }

    isEnableEvent_ = (eventEnable == 1); // Out put event enable
    return curLevel;
}

bool AclLog::IsEventLogOutputEnable()
{
    (void)AclLog::GetCurLogLevel();
    return isEnableEvent_;
}

bool AclLog::IsLogOutputEnable(const aclLogLevel logLevel)
{
    const aclLogLevel curLevel = AclLog::GetCurLogLevel();
    return (curLevel <= logLevel);
}

mmPid_t AclLog::GetTid()
{
    static const thread_local mmPid_t tid = static_cast<mmPid_t>(mmGetTid());
    return tid;
}

void AclLog::ACLSaveLog(const aclLogLevel logLevel, const char_t *const strLog)
{
    if (strLog == nullptr) {
        return;
    }
    switch (logLevel) {
        case ACL_ERROR:
            dlog_error(APP_MODE_ID, "%s", strLog);
            break;
        case ACL_WARNING:
            dlog_warn(APP_MODE_ID, "%s", strLog);
            break;
        case ACL_INFO:
            dlog_info(APP_MODE_ID, "%s", strLog);
            break;
        case ACL_DEBUG:
            dlog_debug(APP_MODE_ID, "%s", strLog);
            break;
        default:
            break;
    }
}

std::string AclErrorLogManager::FormatStr(const char_t *const fmt, ...)
{
    if (fmt == nullptr) {
        return "";
    }

    va_list ap;
    va_start(ap, fmt);
    char_t str[acl::MAX_LOG_STRING] = {};
    const int32_t printRet = vsnprintf_s(str, static_cast<size_t>(acl::MAX_LOG_STRING),
        static_cast<size_t>(acl::MAX_LOG_STRING - 1U), fmt, ap);
    if (printRet == -1) {
        va_end(ap);
        return "";
    }
    va_end(ap);
    return str;
}

void AclErrorLogManager::ReportInputError(const char *errorCode, const std::vector<const char *> &key,
    const std::vector<const char *> &val)
{
    REPORT_PREDEFINED_ERR_MSG(errorCode, key, val);
}

void AclErrorLogManager::ReportInnerError(const char_t *const fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    char_t errorMsgStr[ACL_LIMIT_PER_MESSAGE] = {};
    const int32_t ret = vsnprintf_s(errorMsgStr, static_cast<size_t>(ACL_LIMIT_PER_MESSAGE),
        static_cast<size_t>(ACL_LIMIT_PER_MESSAGE - 1U), fmt, ap);
    if (ret == -1) {
        va_end(ap);
        ACL_LOG_ERROR("[Call][Vsnprintf]call vsnprintf failed, ret = %d", ret);
        return;
    }
    va_end(ap);
    REPORT_INNER_ERR_MSG("EH9999", "%s", errorMsgStr);
}

void AclErrorLogManager::ReportCallError(const char_t *const fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    char_t errorMsgStr[ACL_LIMIT_PER_MESSAGE] = {};
    const int32_t ret = vsnprintf_s(errorMsgStr, static_cast<size_t>(ACL_LIMIT_PER_MESSAGE),
        static_cast<size_t>(ACL_LIMIT_PER_MESSAGE - 1U), fmt, ap);
    if (ret == -1) {
        va_end(ap);
        ACL_LOG_ERROR("[Call][Vsnprintf]call vsnprintf failed, ret = %d", ret);
        return;
    }
    va_end(ap);
    REPORT_INNER_ERR_MSG("EH9999", "%s", errorMsgStr);
}

void AclErrorLogManager::ReportInputErrorWithChar(const char_t *const errorCode, const char_t *const argNames[],
    const char_t *const argVals[], const size_t size)
{
    std::vector<const char *> argNameArr;
    std::vector<const char *> argValArr;
    for (size_t i = 0U; i < size; ++i) {
        argNameArr.push_back(argNames[i]);
        argValArr.push_back(argVals[i]);
    }
    REPORT_PREDEFINED_ERR_MSG(errorCode, argNameArr, argValArr);
}
} // namespace acl