////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
// All rights reserved.
// Confidential and Proprietary - Qualcomm Technologies, Inc.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @file  chxdebugprint.h
/// @brief Debug print related defines
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef CHXDEBUGPRINT_H
#define CHXDEBUGPRINT_H

#include <iostream>
#include <stdio.h>
#include <string>
#include <time.h>
#include <inttypes.h>
#include "camxcdktypes.h"
#include "chiofflineloggerinterface.h"
#include "cdkutils.h"

// NOWHINE ENTIRE FILE - Temporarily bypassing for existing CHI files

// The verbosity tag for a given debug print message
typedef UINT32 ChxLog;
static const ChxLog ChxLogError         = 0;            ///< Error messages
static const ChxLog ChxLogWarning       = 1;            ///< Warning messages
static const ChxLog ChxLogCoreCfg       = 2;            ///< Core Config messages
static const ChxLog ChxLogConfig        = 3;            ///< Config messages
static const ChxLog ChxLogInfo          = 4;            ///< Informational messages
static const ChxLog ChxLogDump          = 5;            ///< Dump messages
static const ChxLog ChxLogVerbose       = 6;            ///< Verbose messages
static const ChxLog ChxLogFull          = 7;            ///< Full messages
static const ChxLog ChxLogTrace         = 8;            ///< Trace messages
static const ChxLog ChxLogMax           = 9;            ///< Max verbosity levels

/// @brief Bitmask of logs to enable: Bit 0 - Error, Bit 1 - Warn, Bit 2 - Info, Bit 3 - Debug
extern ChxLog g_enableChxLogs[ChxLogMax];

/// @brief Enables request mapping logs
extern BOOL g_logRequestMapping;

/// @brief Enables System logging
extern BOOL g_enableSystemLog;

static const UINT32 MaxTraceStringLength = 512;     ///< CHX internal trace message length limit

// The group tag for a given debug print message
typedef UINT64 ChxLogGroup;
static const ChxLogGroup ChxLogGroupCore           = (static_cast<UINT64>(1) << 0);    ///< CHX Core
static const ChxLogGroup ChxLogGroupUsecase        = (static_cast<UINT64>(1) << 1);    ///< Usecase
static const ChxLogGroup ChxLogGroupF2Core         = (static_cast<UINT64>(1) << 2);    ///< Feature2Core
static const ChxLogGroup ChxLogGroupMCXCore        = (static_cast<UINT64>(1) << 3);    ///< MCXUsecase
static const ChxLogGroup ChxLogGroupF2GS           = (static_cast<UINT64>(1) << 4);    ///< Feature2GraphSelector
static const ChxLogGroup ChxLogGroupF2Feature      = (static_cast<UINT64>(1) << 5);    ///< Feature2Feature
static const ChxLogGroup ChxLogGroupF2Req          = (static_cast<UINT64>(1) << 6);    ///< Feature2Request
static const ChxLogGroup ChxLogGroupOffCam         = (static_cast<UINT64>(1) << 7);    ///< OfflineCamera
static const ChxLogGroup ChxLogGroupSBM            = (static_cast<UINT64>(1) << 8);    ///< StreamBufferManager
static const ChxLogGroup ChxLogGroupTBM            = (static_cast<UINT64>(1) << 9);    ///< TargetBufferManager
static const ChxLogGroup ChxLogGroupUtils          = (static_cast<UINT64>(1) << 10);   ///< Utilities
static const ChxLogGroup ChxLogGroupChiNode        = (static_cast<UINT64>(1) << 11);   ///< ChiNode
static const ChxLogGroup ChxLogGroupHMS            = (static_cast<UINT64>(1) << 12);   ///< HelathMonitor
static const ChxLogGroup ChxLogGroupChiMetadata    = (static_cast<UINT64>(1) << 13);   ///< ChiMetadata
static const ChxLogGroup ChxLogGroupProviderExt    = (static_cast<UINT64>(1) << 14);   ///< ProviderExtension

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Class that implements the Log class
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class ChiLog
{
public:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @brief The maximum length for a single debug print message
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static const UINT MaxLogLength = 1024;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @brief The maximum length for a timestamp debug print message
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static const UINT MaxTimeStampLength = 80;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @brief Flag which matches with settings manager whether ASCII logger is enabled
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CDK_VISIBILITY_PUBLIC static BOOL   g_asciiLogEnable;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// LogSystem
    ///
    /// @brief  Logs the given format, va_args to the system's standard output mechanism
    ///
    /// @param  level    Verbosity level of the log
    /// @param  pFormat  Format string, printf style
    /// @param  ...      Parameters required by format
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC VOID LogSystem(
        const CHAR*     module,
        const CHAR*     pLoglevelchar,
        const CHAR*     pGrpName,
        const CHAR*     pFileName,
        const CHAR*     pFuncName,
        INT32           lineNum,
        const CHAR*     pFormat,
        ...);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CoredumpLogSystem
    ///
    /// @brief  Coredump Logs the given format, va_args to the system's standard output mechanism
    ///
    /// @param  pFormat  Format string, printf style
    /// @param  ...      Parameters required by format
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC VOID CoredumpLogSystem(
        INT             fd,
        const CHAR*     pFormat,
        ...);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsEnableOfflineLoggerCoredumpLogSystem
    ///
    /// @brief Return if offlinelogger coredump is enable
    ///
    /// @return BOOL
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC BOOL IsEnableOfflineLoggerCoredumpLogSystem();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetOfflineLoggerOps
    ///
    /// @brief  To set CamX offlinelogger hooks for CHI to use
    ///
    /// @param  pOfflineLogOps    Function pointers to CamX offlinelogger operation
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC VOID SetOfflineLoggerOps(
        CHIOFFLINELOGOPS* pOfflineLogOps);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GroupToString
    ///
    /// @brief  Converts a LogGroup into a human readable string
    ///
    /// @param  group Group tag to stringize
    ///
    /// @return Stringized LogGroup
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC const CHAR* GroupToString(
        ChxLogGroup group)
    {
        const CHAR* pString = NULL;
        switch (group)
        {
            case ChxLogGroupCore:           pString = "[CORE   ]";       break;
            case ChxLogGroupUsecase:        pString = "[USECASE]";       break;
            case ChxLogGroupF2Core:         pString = "[F2Core ]";       break;
            case ChxLogGroupMCXCore:        pString = "[MCXCore]";       break;
            case ChxLogGroupF2GS:           pString = "[F2GS   ]";       break;
            case ChxLogGroupF2Feature:      pString = "[F2Feature]";     break;
            case ChxLogGroupF2Req:          pString = "[F2Req  ]";       break;
            case ChxLogGroupOffCam:         pString = "[OffCam ]";       break;
            case ChxLogGroupTBM:            pString = "[TBM    ]";       break;
            case ChxLogGroupSBM:            pString = "[SBM    ]";       break;
            case ChxLogGroupUtils:          pString = "[UTILS  ]";       break;
            case ChxLogGroupChiNode:        pString = "[ChiNode]";       break;
            case ChxLogGroupHMS:            pString = "[HMS    ]";       break;
            case ChxLogGroupChiMetadata:    pString = "[ChiMeta]";       break;
            case ChxLogGroupProviderExt:    pString = "[ProviderExt]";   break;
            default:                        pString = "[UNKNOWN]";       break;
        }
        return pString;
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetFileName
    ///
    /// @brief  To get full file path for log system
    ///
    /// @param  pFilePath    filepath
    ///
    /// @return CHAR*
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static const inline CHAR* GetFileName(
    const CHAR* pFilePath)
    {
        const CHAR* pFileName = strrchr(pFilePath, '/');

        if (NULL != pFileName)
        {
            // StrRChr will return a pointer to the /, advance one to the filename
            pFileName += 1;
        }
        else
        {
            pFileName = pFilePath;
        }

        return pFileName;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// DPrintF
    ///
    /// @brief  Write formatted data from variable argument list to sized buffer
    ///
    /// @param  fd       File descriptor to print to
    /// @param  pFormat  Format string, printf style
    /// @param  ...      Parameters required by format
    ///
    /// @return Number of characters written
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC INT DPrintF(
        INT         fd,
        const CHAR* pFormat,
                    ...);

private:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Log
    ///
    /// @brief Default constructor
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ChiLog() = default;
    ChiLog(const ChiLog&) = delete;
    ChiLog& operator=(const ChiLog&) = delete;
};

// Indentation headings
#define INDENTATION_MARGIN          (2)
#define HEADING(depth, indent)      (indent + (depth * INDENTATION_MARGIN))

#if defined (_WINDOWS)    // This file for Win32 build only

#include <malloc.h>
#include <windows.h>
#define CHX_LOG_ERROR
#define CHX_LOG_WARN
#define CHX_LOG_CONFIG
#define CHX_LOG_INFO
#define CHX_LOG_VERBOSE
#define CHX_LOG
#define CHX_LOG_REQMAP
#define CHX_LOG_DUMP
#define CHX_LOG_DEBUG
#define CHX_LOG_TO_FILE(...)
#define CHX_LOG_TO_COREDUMP(...)
#define CHX_TRACE_MESSAGE
#define CHX_TRACE_SYNC_BEGIN
#define CHX_TRACE_SYNC_END
#define CHX_TRACE_ASYNC_BEGIN
#define CHX_TRACE_ASYNC_END

#else
#include <unistd.h>                 // library functions getpid gettid
#include <stdlib.h>
#include <log.h>
#undef LOG_TAG
#define LOG_TAG "ChiX"

#define CHX_FILENAME ChiLog::GetFileName

#define CHX_LOG_SYSTEM(module, group, loglevelchar, fmt, args...)              \
        ChiLog::LogSystem(                                                     \
        module,                                                                \
        loglevelchar,                                                          \
        ChiLog::GroupToString(group),                                          \
        ChiLog::GetFileName(__FILE__),                                         \
        __func__,                                                              \
        __LINE__,                                                              \
        fmt,                                                                   \
        ##args);                                                               \

#define CHX_LOG_REQMAP(group, fmt, args...)                                                                 \
    if (TRUE == g_logRequestMapping)                                                                        \
    {                                                                                                       \
        if (TRUE == g_enableSystemLog)                                                                      \
        {                                                                                                   \
            ALOGI(" %d %d [REQMAP]%s %s:%d %s() " fmt "\n", getpid(), gettid(), ChiLog::GroupToString(group),                          \
                  CHX_FILENAME(__FILE__), __LINE__, __func__, ##args);                                      \
        }                                                                                                   \
        CHX_LOG_SYSTEM("[REQMAP]", group, "I", fmt , ##args);                                               \
    }

#define CHX_LOG_ERROR(group, fmt, args...)                                                                 \
    if (g_enableChxLogs[ChxLogError] & group)                                                              \
    {                                                                                                      \
        if (TRUE == g_enableSystemLog)                                                                     \
        {                                                                                                  \
            ALOGE(" %d %d [ERROR]%s %s:%d %s() " fmt "\n", getpid(), gettid(), ChiLog::GroupToString(group),                          \
                  CHX_FILENAME(__FILE__), __LINE__, __func__, ##args);                                     \
        }                                                                                                  \
        CHX_LOG_SYSTEM("[ERROR]", group, "E", fmt , ##args);                                               \
    }

#define CHX_LOG_WARN(group, fmt, args...)                                                                 \
    if (g_enableChxLogs[ChxLogWarning] & group)                                                           \
    {                                                                                                     \
        if (TRUE == g_enableSystemLog)                                                                    \
        {                                                                                                 \
            ALOGW(" %d %d [ WARN]%s %s:%d %s() " fmt "\n", getpid(), gettid(), ChiLog::GroupToString(group),                         \
                  CHX_FILENAME(__FILE__), __LINE__, __func__, ##args);                                    \
        }                                                                                                 \
        CHX_LOG_SYSTEM("[ WARN]", group, "W", fmt , ##args);                                              \
    }

#define CHX_LOG_CONFIG(group, fmt, args...)                                                                \
    if (g_enableChxLogs[ChxLogConfig] & group)                                                             \
    {                                                                                                      \
        if (TRUE == g_enableSystemLog)                                                                     \
        {                                                                                                  \
            ALOGI(" %d %d [CONFIG]%s %s:%d %s() " fmt "\n", getpid(), gettid(), ChiLog::GroupToString(group),                         \
                  CHX_FILENAME(__FILE__), __LINE__, __func__, ##args);                                     \
        }                                                                                                  \
       CHX_LOG_SYSTEM("[CONFIG]", group, "I", fmt , ##args);                                               \
    }


#define CHX_LOG_CORE_CFG(group, fmt, args...)                                                              \
    if (g_enableChxLogs[ChxLogCoreCfg] & group)                                                            \
    {                                                                                                      \
        if (TRUE == g_enableSystemLog)                                                                     \
        {                                                                                                  \
            ALOGI(" %d %d [CORE_CFG]%s %s:%d %s() " fmt "\n", getpid(), gettid(), ChiLog::GroupToString(group),                       \
                  CHX_FILENAME(__FILE__), __LINE__, __func__, ##args);                                     \
        }                                                                                                  \
       CHX_LOG_SYSTEM("[CORE_CFG]", group, "I", fmt , ##args);                                             \
    }


#define CHX_LOG_INFO(group, fmt, args...)                                                                  \
    if (g_enableChxLogs[ChxLogInfo] & group)                                                               \
    {                                                                                                      \
        if (TRUE == g_enableSystemLog)                                                                     \
        {                                                                                                  \
            ALOGI(" %d %d [ INFO]%s %s:%d %s() " fmt "\n", getpid(), gettid(), ChiLog::GroupToString(group),                          \
                  CHX_FILENAME(__FILE__), __LINE__, __func__, ##args);                                     \
        }                                                                                                  \
        CHX_LOG_SYSTEM("[ INFO]", group, "I", fmt , ##args);                                               \
    }

#define CHX_LOG_DUMP(group, fmt, args...)                                                                 \
    if (g_enableChxLogs[ChxLogDump] & group)                                                              \
    {                                                                                                     \
        if (TRUE == g_enableSystemLog)                                                                    \
        {                                                                                                 \
            ALOGD(" %d %d [ DUMP]%s %s:%d %s() " fmt "\n", getpid(), gettid(), ChiLog::GroupToString(group),                         \
                  CHX_FILENAME(__FILE__), __LINE__, __func__, ##args);                                    \
        }                                                                                                 \
        CHX_LOG_SYSTEM("[ DUMP]", group, "I", fmt , ##args);                                              \
    }

#define CHX_LOG_VERBOSE(group, fmt, args...)                                                              \
    if (g_enableChxLogs[ChxLogVerbose] & group)                                                           \
    {                                                                                                     \
        if (TRUE == g_enableSystemLog)                                                                    \
        {                                                                                                 \
            ALOGI(" %d %d [VERBOSE]%s %s:%d %s() " fmt "\n", getpid(), gettid(), ChiLog::GroupToString(group),                       \
                  CHX_FILENAME(__FILE__), __LINE__, __func__, ##args);                                    \
        }                                                                                                 \
        CHX_LOG_SYSTEM("[VERBOSE]", group, "V", fmt , ##args);                                            \
    }

#define CHX_LOG     CHX_LOG_FULL

#define CHX_LOG_DEBUG(group, fmt, args...)                                                                \
    if (TRUE == g_enableSystemLog)                                                                        \
    {                                                                                                     \
        ALOGD(" %d %d [DEBUG]%s %s:%d %s() " fmt "\n", getpid(), gettid(), ChiLog::GroupToString(group),                             \
               CHX_FILENAME(__FILE__), __LINE__, __func__, ##args);                                       \
    }                                                                                                     \
    CHX_LOG_SYSTEM("[DEBUG]", group, "D", fmt , ##args);                                                  \

#define CHX_LOG_FULL(group, fmt, args...)                                                                 \
    if (g_enableChxLogs[ChxLogFull] & group)                                                              \
    {                                                                                                     \
        if (TRUE == g_enableSystemLog)                                                                    \
        {                                                                                                 \
            ALOGD(" %d %d [ FULL]%s %s:%d %s() " fmt "\n", getpid(), gettid(), ChiLog::GroupToString(group),                         \
                  CHX_FILENAME(__FILE__), __LINE__, __func__, ##args);                                    \
        }                                                                                                 \
        CHX_LOG_SYSTEM("[ FULL]", group, "F", fmt , ##args);                                              \
    }

#define CHX_TRACE_MESSAGE(group, fmt, args...)                                                            \
    if (g_enableChxLogs[ChxLogTrace] & group)                                                             \
    {                                                                                                     \
        CHAR traceNameRandomString[MaxTraceStringLength];                                                 \
        CdkUtils::SNPrintF(traceNameRandomString, sizeof(traceNameRandomString), fmt, ##args);            \
        CdkUtils::TraceBegin(traceNameRandomString);                                                      \
        CdkUtils::TraceEnd();                                                                             \
    }

#define CHX_TRACE_SYNC_BEGIN(group, pName)                                                                \
    if (g_enableChxLogs[ChxLogTrace] & group)                                                             \
    {                                                                                                     \
        CdkUtils::TraceBegin(pName);                                                                      \
    }

#define CHX_TRACE_SYNC_END(group)                                                                         \
    if (g_enableChxLogs[ChxLogTrace] & group)                                                             \
    {                                                                                                     \
        CdkUtils::TraceEnd();                                                                             \
    }

#define CHX_TRACE_ASYNC_BEGIN(group, id, ...)                                                             \
    if (g_enableChxLogs[ChxLogTrace] & group)                                                             \
    {                                                                                                     \
        CHAR traceNameRandomString[MaxTraceStringLength];                                                 \
        CdkUtils::SNPrintF(traceNameRandomString, sizeof(traceNameRandomString), ##__VA_ARGS__);          \
        CdkUtils::TraceAsyncBegin(traceNameRandomString, static_cast<UINT32>(id));                        \
    }

#define CHX_TRACE_ASYNC_END(group, id, ...)                                                               \
    if (g_enableChxLogs[ChxLogTrace] & group)                                                             \
    {                                                                                                     \
        CHAR traceNameRandomString[MaxTraceStringLength];                                                 \
        CdkUtils::SNPrintF(traceNameRandomString, sizeof(traceNameRandomString), ##__VA_ARGS__);          \
        CdkUtils::TraceAsyncEnd(traceNameRandomString, static_cast<UINT32>(id));                          \
    }

#define CHX_TRACE_INT32_F(group, id, ...)                                                                 \
    if (g_enableChxLogs[ChxLogTrace] & group)                                                             \
    {                                                                                                     \
        CHAR traceNameRandomString[MaxTraceStringLength];                                                 \
        CdkUtils::SNPrintF(traceNameRandomString, sizeof(traceNameRandomString), ##__VA_ARGS__);          \
        CdkUtils::TraceINT(traceNameRandomString, static_cast<UINT32>(id));                               \
    }

#define CHX_IS_LOG_ENABLED(group)                                                                         \
    (g_enableChxLogs[ChxLogCoreCfg] & group)                                                              \

#define CHX_IS_VERBOSE_ENABLED(group)                                                                     \
        (g_enableChxLogs[ChxLogVerbose] & group)                                                          \

#define CHX_IS_INFO_ENABLED(group)                                                                        \
        (g_enableChxLogs[ChxLogInfo] & group)                                                             \

#define CHX_IS_FULL_ENABLED(group)                                                                       \
        (g_enableChxLogs[ChxLogFull] & group)                                                            \

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Macro for coredump to use offline logging system with group
///
/// @param group    Log Group.
/// @param fd       File Descriptor. (if fd = -1, then dump would happen to logcat. to dump the logs in file fd is mandatory)
/// @param fmt      Format string.
/// @param indent   Indents.
/// @param ...      Parameters required by format
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define CHX_LOG_TO_COREDUMP(group, fd, indent, fmt, args...)                                                 \
    if (-1 == fd)                                                                                            \
    {                                                                                                        \
        /* dump to logcat with dump tag if fd is -1 i.e not available */                                     \
        if (g_enableChxLogs[ChxLogDump] & group)                                                             \
        {                                                                                                    \
            if (TRUE == g_enableSystemLog)                                                                   \
            {                                                                                                \
                ALOGD(" %d %d [ DUMP]%s %s:%d %s() " fmt "\n", getpid(), gettid(), ChiLog::GroupToString(group),                        \
                      CHX_FILENAME(__FILE__), __LINE__, __func__, ##args);                                   \
            }                                                                                                \
            CHX_LOG_SYSTEM("[ DUMP]", group, "I",  fmt , ##args);                                            \
        }                                                                                                    \
    }                                                                                                        \
    else                                                                                                     \
    {                                                                                                        \
        ChiLog::CoredumpLogSystem(fd, "%*s" fmt, indent, "", ##args);                                        \
    }

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Macro for coredump to use offline logging system
///
/// @param group    Log Group.
/// @param fd       File Descriptor. (if fd = -1, then dump would happen to logcat. to dump the logs in file fd is mandatory)
/// @param fmt      Format string.
/// @param indent   Indents.
/// @param ...      Parameters required by format
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define CHX_LOG_TO_FILE(group, fd, indent, fmt, args...)                                                     \
    if (-1 == fd)                                                                                            \
    {                                                                                                        \
        /* dump to logcat with dump tag if fd is -1 i.e not available */                                     \
        if (g_enableChxLogs[ChxLogDump] & group)                                                             \
        {                                                                                                    \
            if (TRUE == g_enableSystemLog)                                                                   \
            {                                                                                                \
                ALOGD(" %d %d [ DUMP]%s %s:%d %s() " fmt "\n", getpid(), gettid(), ChiLog::GroupToString(group),                        \
                      CHX_FILENAME(__FILE__), __LINE__, __func__, ##args);                                   \
            }                                                                                                \
            CHX_LOG_SYSTEM("[ DUMP]", group, "I", fmt , ##args);                                             \
        }                                                                                                    \
    }                                                                                                        \
    else                                                                                                     \
    {                                                                                                        \
        ChxUtils::DPrintF(fd, "%*s" fmt "\n", indent, "", ##args);                                           \
    }

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Macro for printing logs to a fd with log group (always enabled)
///
/// @param group    Log Group.
/// @param fd       File Descriptor.
/// @param fmt      Format string.
/// @param indent   Indents.
/// @param ...      Parameters required by format
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define CHX_LOG_GROUP_TO_FILE(group, fd, indent, fmt, ...)                                                   \
    CdkUtils::DPrintF(fd, "%s %*s" fmt "\n", CamX::Log::GroupToString(group), indent, "", ##__VA_ARGS__);

#define LOG_TO_FILE(fd, indent, fmt, ...)                                                                    \
    ChiLog::DPrintF(fd, "%*s" fmt "\n", indent, "", ##__VA_ARGS__);
#endif // WIN32

#define CHX_SET_AND_LOG(variable, value, fmt_specifier) do {                                                 \
    CHX_LOG_INFO(ChxLogGroupCore, "Setting " #variable " from: %" fmt_specifier " to: %" fmt_specifier,      \
                 variable,                                                                                   \
                 value);                                                                                     \
    variable = value;                                                                                        \
} while(0)

#define CHX_INC_AND_LOG(variable, fmt_specifier) do {                                                        \
    CHX_LOG_INFO(ChxLogGroupCore, "Incrementing " #variable " from: %" fmt_specifier " to: %" fmt_specifier, \
                 variable,                                                                                   \
                 (variable+1));                                                                              \
    variable++;                                                                                              \
} while(0)

#define CHX_SET_AND_LOG_UINT64(variable, value) CHX_SET_AND_LOG(variable, static_cast<UINT64>(value), PRIu64)
#define CHX_INC_AND_LOG_UINT64(variable) CHX_INC_AND_LOG(variable, PRIu64)

#define CHX_PRINT_IF_FAIL(result, logStatement)                                                            \
    if (CDKResultSuccess != result)                                                                        \
    {                                                                                                      \
        logStatement                                                                                       \
    }

#define CHX_PRINT_EVERY_N_REQ(reqId, n, logStatement)                                                      \
    if (0 == (reqId % n))                                                                                  \
    {                                                                                                      \
        logStatement                                                                                       \
    }

#endif // CHXDEBUGPRINT_H
