#include <Utilities/ConsoleColor.hpp>
#include <Utilities/Utilities.hpp>
#include <iostream>
#include <fstream>
#include <Log/Log.hpp>
#include <mutex>
#include <ctime>
#include <iomanip>

static std::ofstream logStream;

static void writeLog(const std::string &categoryLabel, ConsoleColor categoryColor, const std::string &line)
{
    static const char *dateFormat = "%Y-%m-%d %H:%M:%S";

    static std::mutex logMutex;
    std::unique_lock<std::mutex> lock(logMutex);

    auto t = std::time(nullptr);
    auto tm = *std::localtime(&t);
    
    logStream << "[Voxelverse] [" << std::put_time(&tm, dateFormat) << "] [" << categoryLabel << "] " << line << std::endl;

    std::cout <<
        "[" << ConsoleColor::Magenta << "Voxelverse" << ConsoleColor::Reset << "] " <<
        "[" << ConsoleColor::Cyan << std::put_time(&tm, dateFormat) << ConsoleColor::Reset << "] " <<
        "[" << categoryColor << categoryLabel << ConsoleColor::Reset << "] " <<
        line << std::endl;
}

void Log::init(std::string logFilePath)
{
    logStream.open(logFilePath);
}

void Log::info(std::string line)
{
    writeLog("INFO", ConsoleColor::Blue, line);
}

void Log::warn(std::string line)
{
    writeLog("WARN", ConsoleColor::Yellow, line);
}

void Log::error(std::string line)
{
    writeLog("ERROR", ConsoleColor::Red, line);
}

void Log::debug(std::string line)
{
    writeLog("DEBUG", ConsoleColor::Magenta, line);
}

void Log::flush()
{
    logStream.flush();
}