#include "Logger.h"

#include <chrono>
#include <iostream>
#include <string>
#include <thread>

namespace
{
int gFailures = 0;

void Expect(bool condition, const std::string& message)
{
	if (condition)
		return;

	++gFailures;
	std::cerr << "FAILED: " << message << "\n";
}

void TestLevelNames()
{
	using namespace RenderCadenceCompositor;
	Expect(std::string(LogLevelName(LogLevel::Log)) == "log", "log level name");
	Expect(std::string(LogLevelName(LogLevel::Warning)) == "warning", "warning level name");
	Expect(std::string(LogLevelName(LogLevel::Error)) == "error", "error level name");
}

void TestLevelFiltering()
{
	using namespace RenderCadenceCompositor;

	LoggerConfig config;
	config.minimumLevel = LogLevel::Warning;
	config.writeToConsole = false;
	config.writeToDebugOutput = false;
	config.writeToFile = false;
	config.maxQueuedMessages = 16;

	Logger& logger = Logger::Instance();
	logger.Start(config);
	logger.Write(LogLevel::Log, "test", "filtered");
	logger.Write(LogLevel::Warning, "test", "kept");
	logger.Write(LogLevel::Error, "test", "kept");
	logger.Stop();

	const LoggerCounters counters = logger.Counters();
	Expect(counters.queued == 2, "logger queues only messages at or above minimum level");
	Expect(counters.written == 2, "logger writes queued messages before stop returns");
	Expect(counters.dropped == 0, "logger does not drop under queue capacity");
}

void TestTryWriteDropsWhenQueueIsFull()
{
	using namespace RenderCadenceCompositor;

	LoggerConfig config;
	config.minimumLevel = LogLevel::Log;
	config.writeToConsole = false;
	config.writeToDebugOutput = false;
	config.writeToFile = false;
	config.maxQueuedMessages = 0;

	Logger& logger = Logger::Instance();
	logger.Start(config);

	const bool sawDrop = !logger.TryWrite(LogLevel::Log, "test", "message");
	logger.Stop();

	Expect(sawDrop || logger.Counters().dropped > 0, "try-write reports or counts queue pressure");
}
}

int main()
{
	TestLevelNames();
	TestLevelFiltering();
	TestTryWriteDropsWhenQueueIsFull();

	if (gFailures != 0)
	{
		std::cerr << gFailures << " RenderCadenceCompositorLogger test failure(s).\n";
		return 1;
	}

	std::cout << "RenderCadenceCompositorLogger tests passed.\n";
	return 0;
}
