#include "FontAtlasBuilder.h"
#include "ShaderPackageRegistry.h"

#include <filesystem>
#include <iostream>

namespace
{
int gFailures = 0;

void Expect(bool condition, const char* message)
{
	if (condition)
		return;

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

std::filesystem::path RepoRoot()
{
	std::filesystem::path path = std::filesystem::current_path();
	while (!path.empty())
	{
		if (std::filesystem::exists(path / "3rdParty" / "msdf-atlas-gen" / "msdf-atlas-gen.exe"))
			return path;
		const std::filesystem::path parent = path.parent_path();
		if (parent.empty() || parent == path)
			break;
		path = parent;
	}
	return std::filesystem::current_path();
}

bool HasBundledExecutable(std::filesystem::path& executablePath)
{
	return RenderCadenceCompositor::FontAtlasBuilder::FindMsdfAtlasGenExecutable(RepoRoot(), executablePath);
}

bool IsMsdfAtlasGenToolError(const std::string& error)
{
	return error.find("msdf-atlas-gen") != std::string::npos;
}

void TestFindsBundledExecutable()
{
	std::filesystem::path executablePath;
	Expect(
		HasBundledExecutable(executablePath),
		"bundled msdf-atlas-gen executable is found");
	Expect(std::filesystem::exists(executablePath), "bundled msdf-atlas-gen executable exists");
}

void TestBuildsTextOverlayFontAtlas()
{
	std::filesystem::path executablePath;
	if (!HasBundledExecutable(executablePath))
	{
		std::cout << "SKIP: msdf-atlas-gen executable is not available; skipping font atlas integration build.\n";
		return;
	}

	const std::filesystem::path repoRoot = RepoRoot();
	ShaderPackageRegistry registry(4);
	ShaderPackage shaderPackage;
	std::string error;
	Expect(registry.ParseManifest(repoRoot / "shaders" / "text-overlay" / "shader.json", shaderPackage, error), "text overlay manifest parses");
	Expect(!shaderPackage.fontAssets.empty(), "text overlay declares a font asset");

	RenderCadenceCompositor::FontAtlasBuildConfig config;
	config.repoRoot = repoRoot;
	config.cacheRoot = repoRoot / "runtime" / "test_font_cache";
	RenderCadenceCompositor::FontAtlasBuilder builder(config);
	std::vector<RenderCadenceCompositor::FontAtlasBuildOutput> outputs;
	if (!builder.BuildPackageFontAtlases(shaderPackage, outputs, error))
	{
		if (IsMsdfAtlasGenToolError(error))
		{
			std::cout << "SKIP: msdf-atlas-gen could not run in this environment: " << error << "\n";
			return;
		}
		Expect(false, ("text overlay font atlas builds: " + error).c_str());
		return;
	}
	Expect(outputs.size() == 1, "one font atlas output is produced");
	if (!outputs.empty())
	{
		Expect(std::filesystem::exists(outputs[0].imagePath), "font atlas image exists");
		Expect(std::filesystem::exists(outputs[0].jsonPath), "font atlas json exists");
		Expect(std::filesystem::file_size(outputs[0].imagePath) > 0, "font atlas image is not empty");
		Expect(std::filesystem::file_size(outputs[0].jsonPath) > 0, "font atlas json is not empty");
	}
}
}

int main()
{
	TestFindsBundledExecutable();
	TestBuildsTextOverlayFontAtlas();

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

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