#pragma once

enum class LogLevel
{
    DEBUG,
    INFO,
    WARN,
    ERROR
};

enum class Backend
{
    Serial,
    Console
};

#define PRINTF_LIKE(n, m) __attribute__((format(printf, n, m)))

namespace KernelLog
{
    void log(const char* function, LogLevel level, const char* message, ...) PRINTF_LIKE(3, 4);
    void logln(const char* function, LogLevel level, const char* message, ...) PRINTF_LIKE(3, 4);
    void toggle_log_level(LogLevel level);
    void toggle_log_backend(Backend backend);
    void enable_log_backend(Backend backend);
}

#ifndef MODULE
#define kcommonlog(function, level, ...) KernelLog::function(__FUNCTION__, level, __VA_ARGS__)
#else
#define kcommonlog(function, level, ...) KernelLog::function(MODULE, level, __VA_ARGS__)
#endif

#define kdbg(...) kcommonlog(log, LogLevel::DEBUG, __VA_ARGS__)
#define kdbgln(...) kcommonlog(logln, LogLevel::DEBUG, __VA_ARGS__)
#define kinfo(...) kcommonlog(log, LogLevel::INFO, __VA_ARGS__)
#define kinfoln(...) kcommonlog(logln, LogLevel::INFO, __VA_ARGS__)
#define kwarn(...) kcommonlog(log, LogLevel::WARN, __VA_ARGS__)
#define kwarnln(...) kcommonlog(logln, LogLevel::WARN, __VA_ARGS__)
#define kerror(...) kcommonlog(log, LogLevel::ERROR, __VA_ARGS__)
#define kerrorln(...) kcommonlog(logln, LogLevel::ERROR, __VA_ARGS__)