// -----------------------------------------------------------------------------
// logger.cpp
// -----------------------------------------------------------------------------
// Implementation of the thread-safe file logger. The target file is derived
// from the executable path so the log always lands next to the binary.
// Each line is prefixed with a local timestamp and the severity level name.
// -----------------------------------------------------------------------------

#include "logger.h"

#include <windows.h>
#include <fstream>
#include <mutex>

namespace util {

// Serializes access to the log file from all feature threads.
static std::mutex g_logMutex;

// Maps a severity level to its fixed-width display name.
static const char* LevelName(Level level)
{
	switch (level) {
		case Level::Debug:   return "DEBUG";
		case Level::Info:    return "INFO ";
		case Level::Warning: return "WARN ";
		case Level::Error:   return "ERROR";
		case Level::Fatal:   return "FATAL";
		default:             return "?????";
	}
}

// Returns the current local time formatted as HH:MM:SS.
static std::string CurrentTime()
{
	SYSTEMTIME st;
	GetLocalTime(&st);

	char buffer[32];
	sprintf_s(buffer, "[%04u-%02u-%02u %02u:%02u:%02u]",
		st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
	return buffer;
}

void Log(Level level, const std::string& message)
{
	std::lock_guard<std::mutex> lock(g_logMutex);

	static const std::string logPath = []() {
		char exePath[MAX_PATH];
		GetModuleFileNameA(NULL, exePath, MAX_PATH);

		std::string path(exePath);
		const size_t slash = path.find_last_of("\\/");
		if (slash != std::string::npos) {
			path = path.substr(0, slash + 1);
		}
		return path + "log.txt";
	}();

	static std::ofstream file(logPath, std::ios::app);
	if (file.is_open()) {
		file << CurrentTime() << " [" << LevelName(level) << "] " << message << std::endl;
	}
}

void LogDebug(const std::string& message)
{
#ifndef NDEBUG
	Log(Level::Debug, message);
#else
	(void)message;
#endif
}
void LogInfo(const std::string& message)     { Log(Level::Info, message); }
void LogWarning(const std::string& message)  { Log(Level::Warning, message); }
void LogError(const std::string& message)    { Log(Level::Error, message); }
void LogFatal(const std::string& message)    { Log(Level::Fatal, message); }

} // namespace util