#pragma once

#include <string>

/**
 * @brief Basic logging class
 *
 * Defines helper functions for logging facility. Configured in Application::init()
 * 
 */
class Log
{
public:
    enum LogLevel
    {
        FATAL,
        ERROR,
        WARN,
        INFO,
        DEBUG,
    };

    LogLevel level = WARN; ///< Default logging level

    /**
     * @brief Prints message to stdout
     *
     * TODO: write to configurable stream, be it stdout, stderr or even a file
     * 
     * @param level the message level
     * @param fmt the message format
     * @param ... variable parameters
     */
    void log(LogLevel level, const std::string &fmt, ...);
    
private:
    inline std::string _getLabel(LogLevel level)
    {
        switch (level)
        {
            case DEBUG: return "DEBUG";
            case INFO:  return "INFO ";
            case WARN:  return "WARN ";
            case ERROR: return "ERROR";
            case FATAL: return "FATAL";
            default:    return "UNK  ";
        }
    }
};

extern Log LOG; /// Global variable :(

#define INFO(fmt, ...) LOG.log(Log::INFO, fmt, ##__VA_ARGS__)
#define WARN(fmt, ...) LOG.log(Log::WARN, fmt, ##__VA_ARGS__)
#define ERROR(fmt, ...) LOG.log(Log::ERROR, fmt, ##__VA_ARGS__)
#define FATAL(fmt, ...) LOG.log(Log::FATAL, fmt, ##__VA_ARGS__)
#define DEBUG(fmt, ...) LOG.log(Log::DEBUG, fmt, ##__VA_ARGS__)
