#pragma once
#include <common.hpp>


/** Example usage:

	DEBUG("error: %d", errno);

will print something like

	[0.123 debug myfile.cpp:45] error: 67
*/
#define DEBUG(format, ...) rack::logger::log(rack::logger::DEBUG_LEVEL, __FILE__, __LINE__, __FUNCTION__, format, ##__VA_ARGS__)
#define INFO(format, ...) rack::logger::log(rack::logger::INFO_LEVEL, __FILE__, __LINE__, __FUNCTION__, format, ##__VA_ARGS__)
#define WARN(format, ...) rack::logger::log(rack::logger::WARN_LEVEL, __FILE__, __LINE__, __FUNCTION__, format, ##__VA_ARGS__)
#define FATAL(format, ...) rack::logger::log(rack::logger::FATAL_LEVEL, __FILE__, __LINE__, __FUNCTION__, format, ##__VA_ARGS__)


namespace rack {
/** Logs messages to a file or the terminal */
namespace logger {


extern std::string logPath;


enum Level {
	DEBUG_LEVEL,
	INFO_LEVEL,
	WARN_LEVEL,
	FATAL_LEVEL
};

/** Returns whether logger was successfully initialized. */
PRIVATE bool init();
PRIVATE void destroy();
/** Do not use this function directly. Use the macros above.
Thread-safe, meaning messages cannot overlap each other in the log.
*/
__attribute__((format(printf, 5, 6)))
void log(Level level, const char* filename, int line, const char* func, const char* format, ...);
/** Returns whether the last log file failed to end properly, due to a possible crash.
*/
PRIVATE bool wasTruncated();


} // namespace logger
} // namespace rack
