#pragma once

#include "colors.h"
#include <sstream>
#include <iostream>
#include <iomanip>
#include <chrono>
#include <ctime>

#ifndef LOG_PREFIX
#define LOG_PREFIX ""
#endif
#define _OUT(expr) {std::ostringstream oss; oss << expr << std::endl; std::cout << oss.str();}
#define _LOG(expr, color) _OUT("[" color << logger::now() << END_COLOR "] " LOG_PREFIX << expr)
#define LOG(expr) _LOG(BOLD << expr << END_COLOR, BOLD)
#define LOG_E(expr) _LOG(expr, RED)
#define LOG_W(expr) _LOG(expr, YELLOW)
#define LOG_I(expr) _LOG(expr, GREEN)
#if LOG_DEBUG
#define LOG_D(expr) _LOG(expr, END_COLOR)
#else
#define LOG_D(expr)
#endif
#if LOG_TRACE
#define LOG_T(expr) _LOG(expr, GREY)
#else
#define LOG_T(expr)
#endif
#define FATAL(expr) LOG_E(expr); exit(EXIT_FAILURE)

namespace logger {
    inline auto now() {
        const auto tp = std::chrono::system_clock::now();
        const auto timet = std::chrono::system_clock::to_time_t(tp);
        return std::put_time(std::localtime(&timet), "%Y-%m-%d %X");
    }
}
