/*******************************************************************************
 * (c) Copyright 2015 Microsemi Corporation.  All rights reserved.
 *
 *
 *
 * SVN $Revision: $
 * SVN $Date: $
 */

/*!
 *\file
 *\brief
 *		 Logging Module : Debug, Info and Error logging fuctions
 */

#ifndef __EGL_LOG_H__
#define __EGL_LOG_H__

#include "egl_types.h"

/* ----------------- Enumerations ---------------------- */
typedef enum
{
	eLOG_LEVEL_EMERGENCY = 0,
	eLOG_LEVEL_ALERT,
	eLOG_LEVEL_CRITICAL,
    eLOG_LEVEL_ERROR, /* Unexpected recoverable error, not maskable   (Log ERROR)  */
    eLOG_LEVEL_WARNING,
    eLOG_LEVEL_NOTICE,
    eLOG_LEVEL_INFO,      /* Informational messages						  (Log ERROR & INFO) */
    eLOG_LEVEL_DEBUG      /* Debug messages                               (Log EROR, INFO & DEBUG) */
} log_level_t;

/* ----------------- Defines ---------------------- */

/*!
 *\brief
 *	 Standard Logging Macros
 *
 *	 If the logging-handle has the appropriate level of logging enabled
 *	 the message is logged to all destinations, otherwise the log is discarded.
 *
 *\param[in]	logHandle	Handle for this logging context
 *\param[in]	fmt			'printf' style format string followed by a variable-argument-list
 */
#define DO_LOG_EMERGENCY(logHandle, fmt, ...)                                             \
    do                                                                             \
    {                                                                              \
        log_emergency(logHandle, __FILE__, __FUNCTION__, __LINE__, fmt,##__VA_ARGS__); \
    } while(0)

#define DO_LOG_ALERT(logHandle, fmt, ...)                                             \
    do                                                                             \
    {                                                                              \
        log_alert(logHandle, __FILE__, __FUNCTION__, __LINE__, fmt,##__VA_ARGS__); \
    } while(0)

#define DO_LOG_CRITICAL(logHandle, fmt, ...)                                             \
    do                                                                             \
    {                                                                              \
        log_critical(logHandle, __FILE__, __FUNCTION__, __LINE__, fmt,##__VA_ARGS__); \
    } while(0)

#define DO_LOG_ERROR(logHandle, fmt, ...)                                             \
    do                                                                             \
    {                                                                              \
        log_error(logHandle, __FILE__, __FUNCTION__, __LINE__, fmt,##__VA_ARGS__); \
    } while(0)

#define DO_LOG_WARNING(logHandle, fmt, ...)                                             \
    do                                                                             \
    {                                                                              \
        log_warning(logHandle, __FILE__, __FUNCTION__, __LINE__, fmt,##__VA_ARGS__); \
    } while(0)

#define DO_LOG_NOTICE(logHandle, fmt, ...)                                             \
    do                                                                             \
    {                                                                              \
        log_notice(logHandle, __FILE__, __FUNCTION__, __LINE__, fmt,##__VA_ARGS__); \
    } while(0)

#define DO_LOG_DEBUG(logHandle, fmt, ...)                                             \
    do                                                                             \
    {                                                                              \
        log_debug(logHandle, __FILE__, __FUNCTION__, __LINE__, fmt,##__VA_ARGS__); \
    } while(0)

#define DO_LOG_INFO(logHandle, fmt, ...)                                             \
    do                                                                            \
    {                                                                             \
        log_info(logHandle, __FILE__, __FUNCTION__, __LINE__, fmt,##__VA_ARGS__); \
    } while(0)

#define LOG_MAX_LEVEL_STRING_LEN   (10) /** Max length of a 'LEVEL' string returned by #log_getLevelString */

/* ----------------- Enumerations ---------------------- */
/* ----------------- Structs/Types ---------------------- */
/* ----------------- External Functions ---------------------- */

#ifdef __cplusplus
extern "C" {
#endif

/*!
 *\brief
 *	 Initialise Logging for this process
 *
 *	 Must be called before any other logging API are called.  <br>
 *	 May safely be called multiple times, initialisation will be performed only
 *	 on the first instance
 */
extern void log_init(void);

/*!
 *\brief
 *	 Register a Logging 'module'
 *
 *	 Establishes a default logging level of ERROR
 *
 *\param[in]	moduleName		Name of the logging module (Will be displayed in all messages)
 *
 *\returns		\li logging handle to be used in all subsequent calls to logging by this module
 *				\li 0, call has failed
 */
extern uint16_t log_register(const char* name);

/*!
 *\brief
 *	 Set the logging level to DEBUG, this includes INFO and ERROR
 *
 *\param[in]	logHandle		Logging handle for this module
 */
void log_setLevelDebug(const uint16_t logHandle);

/*!
 *\brief
 *	 Set the logging level to INFO, this includes ERROR
 *
 *\param[in]	logHandle		Logging handle for this module
 */
void log_setLevelInfo(const uint16_t logHandle);

/*!
 *\brief
 *	 Set the logging level to INFO, this includes ERROR
 *
 *\param[in]	logHandle		Logging handle for this module
 */
void log_setLevelNotice(const uint16_t logHandle);

/*!
 *\brief
 *	 Set the logging level to INFO, this includes ERROR
 *
 *\param[in]	logHandle		Logging handle for this module
 */
void log_setLevelWarning(const uint16_t logHandle);

/*!
 *\brief
 *	 Set the logging level to ERROR only
 *
 *\param[in]	logHandle		Logging handle for this module
 */
void log_setLevelError(const uint16_t logHandle);

/*!
 *\brief
 *	 Recover a string describing the current level of logging enabled
 *
 *	 One of 'ERROR', 'INFO', 'DEBUG', 'INVALID'  <br>
 *	 'INVALID' is returned if the handle is invalid.
 *
 *\param[in]	logHandle		Logging handle for this module
 *\param[out]	levelString     Address of string pointer to populate with pointer to the static string
 */
void log_getLevelString(const uint16_t logHandle, char** levelStringPtr);

/*!
 *\brief
 *	 Set the logging level for the selected log
 *
 *\param[in]	logHandle		Logging handle for this module
 *\param[out]	level     		The new logging level for the module eLOG_LEVEL_DEBUG to eLOG_LEVEL_ERROR
 *
 * This function is used to change the lowest level severity to log for
 * this module. Values of eLOG_LEVEL_DEBUG (lowest) to eLOG_LEVEL_ERROR
 * can be selected. Levels with greater severity than eLOG_LEVEL_ERROR
 * will default to eLOG_LEVEL_ERROR since severity of eLOG_LEVEL_ERROR
 * and higher are non maskable.
 */
void setModuleLogLevel(const uint16_t logHandle, log_level_t logLevel);

/*
 *	 Log an ERROR level message
 *
 *	 This function is never called directly, only via the #DO_LOG_ERROR macro
 */
extern void log_error(const uint16_t logHandle,
                      const char*    filename,
                      const char*    fnname,
                      const int      linenum,
                      const char*    fmt,
                      ...);

/*
 *	 Log a DEBUG level message
 *
 *	 This function is never called directly, only via the #DO_LOG_DEBUG macro
 */
extern void log_debug(const uint16_t logHandle,
                      const char*    filename,
                      const char*    fnname,
                      const int      linenum,
                      const char*    fmt,
                      ...);

/*
 *	 Log an INFO level message
 *
 *	 This function is never called directly, only via the #DO_LOG_INFO macro
 */
extern void log_info(const uint16_t logHandle,
                     const char*    filename,
                     const char*    fnname,
                     const int      linenum,
                     const char*    fmt,
                     ...);

/*
 *	 Log an EMERGENCY level message
 *
 *	 This function is never called directly, only via the #DO_LOG_INFO macro
 */
extern void log_emergency(const uint16_t logHandle,
                     const char*    filename,
                     const char*    fnname,
                     const int      linenum,
                     const char*    fmt,
                     ...);

/*
 *	 Log an ALERT level message
 *
 *	 This function is never called directly, only via the #DO_LOG_INFO macro
 */
extern void log_alert(const uint16_t logHandle,
                     const char*    filename,
                     const char*    fnname,
                     const int      linenum,
                     const char*    fmt,
                     ...);

/*
 *	 Log a CRITICAL level message
 *
 *	 This function is never called directly, only via the #DO_LOG_INFO macro
 */
extern void log_critical(const uint16_t logHandle,
                     const char*    filename,
                     const char*    fnname,
                     const int      linenum,
                     const char*    fmt,
                     ...);

/*
 *	 Log a WARNING level message
 *
 *	 This function is never called directly, only via the #DO_LOG_INFO macro
 */
extern void log_warning(const uint16_t logHandle,
                     const char*    filename,
                     const char*    fnname,
                     const int      linenum,
                     const char*    fmt,
                     ...);

/*
 *	 Log a NOTICE level message
 *
 *	 This function is never called directly, only via the #DO_LOG_INFO macro
 */
extern void log_notice(const uint16_t logHandle,
                     const char*    filename,
                     const char*    fnname,
                     const int      linenum,
                     const char*    fmt,
                     ...);

#ifdef __cplusplus
}
#endif

#endif  /*__LOG_API_H__*/


