#pragma once

#include "xmsdk_export.h"

#include <functional>
#include <string>

namespace xavia::sdk
{
  /**
   * \brief Severity enum used to decide on the level of reporting
   */
  enum class Severity {
    XM_ERROR,   ///< Only errors are reported. Errors represent unexpected situations that might have an impact on the sensor or its output
    XM_WARNING, ///< Report warnings and errors. Warnings should be checked, but the system has mechanism to cope with the situation.
    XM_INFO,    ///< Info or more important. Info messages give information on what is happening.
    XM_DEBUG    ///< Log all information. Debug messages give very detailed information. Enabling this can impact the performance of the SDK.
  };

  using LogCallback = std::function<void(const Severity&, const std::wstring&)>;

  /**
   * \brief Set the log output folder
   * 
   * \param[in] path The path to the log output folder
   * 
   * The name of each file is defined by the current date.
   * 
   * If this function is not called, the sdk will not write logs to disk.
   * Call this function before any other log message is generated. Calling afterwards
   * has no effect.
   * 
   * Default behavior if this function is not called, is to write to std::cout.
   * Remember, combining this with std::wcout is undefined behaviour. In that case
   * create a callback, capture the logs and print them to std::wcout yourself.
   */
  void XMSDK_EXPORT SetLogOutputFolder(const std::wstring& path);

  /**
   * \brief Indicate the desired logging level.
   * 
   * \param[in] severity The desired logging level. Default is INFO.
   */
  void XMSDK_EXPORT SetLogSeverity(const Severity& severity);

  /**
   * \brief Request the current severity that is used for logging
   * 
   * \returns the current severity that is used for logging
   */
  Severity XMSDK_EXPORT GetLogSeverity();

  /**
   * \brief Converts the provided severity to a string;
   * 
   * \param[in] severity the severity to convert
   * 
   * \returns a string representation of the provided severity in English
   */
  std::wstring XMSDK_EXPORT GetLogTypeString(const Severity& severity);

  /**
   * \brief Register a callback for log messages.
   * 
   * \param[in] callback A callback function of signature void(const Severity&, const std::wstring&)
   * 
   * The SDK will pipe every log message to this callback.
   * Only log messages with severity equal or more important than the severity
   * set through `SetLogSeverity()` will be reported to the callback.
   */
  void XMSDK_EXPORT SetLogCallBack(const LogCallback& callback);

  /**
   * \brief Log a message with the specified severity to the SDK log.
   * 
   * \param[in] severity The severity of the log message.
   * \param[in] message The log message.
   * \param[in] i_file The source file from which the log is generated.
   * \param[in] i_line The line number in the source file from which the log is generated.
   * \param[in] i_function The function name from which the log is generated.
   * 
   * \note: the last three parameters can be obtained using the macros __FILE__, __LINE__ and __FUNCTION__ respectively.
   */
  void XMSDK_EXPORT Log(const Severity severity, const std::wstring message,
                    const char* i_file, const size_t& i_line, const char* i_functionName);
} // namespace xavia::sdk
