/**
 * @file tees_log.h
 * @brief Multibuild's logging interface declarations
 * @author Iaroslav Makarchuk (i.makarchuk@samsung.com)
 * @date Created Oct 3, 2016
 * @par In Samsung Ukraine R&D Center (SURC) under a contract between
 * @par LLC "Samsung Electronics Ukraine Company" (Kiev, Ukraine) and
 * @par "Samsung Elecrtronics Co", Ltd (Seoul, Republic of Korea)
 * @par Copyright: (c) Samsung Electronics Co, Ltd 2015. All rights reserved.
 *
 * This software is proprietary of Samsung Electronics.
 * No part of this software, either material or conceptual may be copied
 * or distributed, transmitted, transcribed, stored in a retrieval system
 * or translated into any human or computer language in any form by any means,
 * electronic, mechanical, manual or otherwise, or disclosed to third parties
 * without the express written permission of Samsung Electronics.
 */

#ifndef TEES_LOG_H_
#define TEES_LOG_H_

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

#ifndef PLATFORM_LOG_TAG
  #define PLATFORM_LOG_TAG "Unknown"
#endif /* !PLATFORM_LOG_TAG */

typedef enum TEES_LogLevelEnum {
  TEES_LOG_LEVEL_NONE = 0,
  TEES_LOG_LEVEL_DEFAULT,
  TEES_LOG_LEVEL_VERBOSE,
  TEES_LOG_LEVEL_DEBUG,
  TEES_LOG_LEVEL_INFO,
  TEES_LOG_LEVEL_WARNING,
  TEES_LOG_LEVEL_ERROR,
  TEES_LOG_LEVEL_CRITICAL,
  TEES_LOG_LEVEL_MAX,
} TEES_LogLevel;

typedef enum TEES_LogTargetEnum {
  TEES_LOG_TARGET_DEFAULT = 0,
  TEES_LOG_TARGET_FILE,
} TEES_LogTarget;

/**
 * @brief Sets log destination
 *
 * @note The function sets the place the log will be written to. Default
 * destination depends on the platform. Currently only TEES_LOG_TARGET_DEFAULT
 * is supported.
 *
 * @param[in]  target       A target to write the logs
 * @param[in]  param        Destination-specific parameter, i.e. filename for
 *                          TEES_LOG_TARGET_FILE
 * @param[in]  param_length Destination-specific parameter, length of param in
 *                          bytes
 *
 */
void TEES_LogSetTarget(TEES_LogTarget target,
                          const void *param,
                          uint32_t param_len);

/**
 * @brief Sets the minimum log level
 *
 * @note The function sets the minimum log level. The logs with lesser level
 * will not be shown.
 *
 * @param[in]  level   Minimum log level
 *
 */
void TEES_LogSetLevel(TEES_LogLevel level);

#define TEES_LOG(level, ...) TEES_Log(level, __FUNCTION__, __LINE__, PLATFORM_LOG_TAG, __VA_ARGS__)
#define TEES_LOGMEM(level, data, data_len) {TEES_LOG(level, #data"[%u]:\n", (size_t)data_len); TEES_LogMem(level, __FUNCTION__, __LINE__, PLATFORM_LOG_TAG, data, data_len);}

/**
 * @brief Prints the log message with the specified parameters
 *
 * @note The function prints the message to the log with the specified
 * parameters. If the log level of the message is less then the one set with
 * TEES_LogSetLevel(), nothing will be printed.
 *
 * @param[in]  level         The log level of the message
 * @param[in]  function_name A name of the function, the message is related to
 * @param[in]  line          A line number the message is related to
 * @param[in]  project_name  The name of the project, the log is related to
 * @param[in]  fmt           Output format of the message. It is
 *                           printf-compatible
 */
void TEES_Log(TEES_LogLevel level, const char *function_name, int line, const char *project_name, const char *fmt, ...);

/**
 * @brief Prints the hex dump of the data, specified by pointer and size
 *
 * @note The function prints the data of specified size located at specified
 * address in hexademical mode. If the log level of the message is less then the
 * one set with TEES_LogSetLevel(), nothing will be printed.
 *
 * @param[in]  level         The log level of the message
 * @param[in]  function_name A name of the function, the message is related to
 * @param[in]  line          A line number the message is related to
 * @param[in]  project_name  The name of the project, the log is related to
 * @param[in]  data          A pointer to the data, which is dumped to the log
 * @param[in]  data_len      Data length to be dumped.
 */
void TEES_LogMem(TEES_LogLevel level, const char *function_name, int line, const char *project_name, const void *data, uint32_t data_len);

#ifdef MB_NO_LOGS

#define MB_LOGV(...)
#define MB_LOGI(...)
#define MB_LOGD(...)
#define MB_LOGW(...)
#define MB_LOGE(...)

#define MB_LOGMEMV(...)
#define MB_LOGMEMI(...)
#define MB_LOGMEMD(...)
#define MB_LOGMEMW(...)
#define MB_LOGMEME(...)

#else

/**
 * @brief Basic logging interface.
 * Contains platform-independent logging macros. Supports several log levels.
 * Other log levels to be triggered using TEES_LOG() macro.
 * MB_LOG* logs may be disabled defining MB_NO_LOGS flag.
 */
#define MB_LOGV(...) TEES_LOG(TEES_LOG_LEVEL_VERBOSE, __VA_ARGS__)
#define MB_LOGI(...) TEES_LOG(TEES_LOG_LEVEL_INFO, __VA_ARGS__)
#define MB_LOGD(...) TEES_LOG(TEES_LOG_LEVEL_DEBUG, __VA_ARGS__)
#define MB_LOGW(...) TEES_LOG(TEES_LOG_LEVEL_WARNING, __VA_ARGS__)
#define MB_LOGE(...) TEES_LOG(TEES_LOG_LEVEL_ERROR, __VA_ARGS__)

#define MB_LOGMEMV(...) TEES_LOGMEM(TEES_LOG_LEVEL_VERBOSE, __VA_ARGS__)
#define MB_LOGMEMI(...) TEES_LOGMEM(TEES_LOG_LEVEL_INFO, __VA_ARGS__)
#define MB_LOGMEMD(...) TEES_LOGMEM(TEES_LOG_LEVEL_DEBUG, __VA_ARGS__)
#define MB_LOGMEMW(...) TEES_LOGMEM(TEES_LOG_LEVEL_WARNING, __VA_ARGS__)
#define MB_LOGMEME(...) TEES_LOGMEM(TEES_LOG_LEVEL_ERROR, __VA_ARGS__)

#endif

#ifdef __cplusplus
}
#endif

#endif /* TEES_LOG_H_ */
