#pragma once

#include "ShaderTypes.h"

#include <filesystem>
#include <map>
#include <string>
#include <vector>

namespace RenderCadenceCompositor
{
struct FontAtlasBuildConfig
{
	std::filesystem::path repoRoot;
	std::filesystem::path cacheRoot;
	double sizePixelsPerEm = 128.0;
	double pixelRange = 8.0;
	std::string atlasType = "mtsdf";
};

struct FontAtlasBuildOutput
{
	struct Glyph
	{
		double advance = 0.0;
		double planeLeft = 0.0;
		double planeTop = 0.0;
		double planeRight = 0.0;
		double planeBottom = 0.0;
		double atlasLeft = 0.0;
		double atlasTop = 0.0;
		double atlasRight = 0.0;
		double atlasBottom = 0.0;
		bool hasBounds = false;
	};

	std::string fontId;
	std::filesystem::path imagePath;
	std::filesystem::path jsonPath;
	unsigned width = 0;
	unsigned height = 0;
	double ascender = -0.9;
	double descender = 0.25;
	double lineHeight = 1.2;
	std::vector<unsigned char> rgbaPixels;
	std::map<unsigned, Glyph> glyphsByCodepoint;
};

class FontAtlasBuilder
{
public:
	explicit FontAtlasBuilder(FontAtlasBuildConfig config);

	bool BuildPackageFontAtlases(
		const ShaderPackage& shaderPackage,
		std::vector<FontAtlasBuildOutput>& outputs,
		std::string& error) const;

	bool BuildFontAtlas(
		const ShaderPackage& shaderPackage,
		const ShaderFontAsset& fontAsset,
		FontAtlasBuildOutput& output,
		std::string& error) const;

	static bool FindMsdfAtlasGenExecutable(const std::filesystem::path& repoRoot, std::filesystem::path& executablePath);

private:
	std::filesystem::path PackageCacheDirectory(const ShaderPackage& shaderPackage) const;
	bool LoadAtlasJson(FontAtlasBuildOutput& output, std::string& error) const;
	bool LoadAtlasImage(FontAtlasBuildOutput& output, std::string& error) const;
	static std::string SanitizePathToken(const std::string& value);
	static bool RunProcess(const std::string& commandLine, const std::filesystem::path& workingDirectory, std::string& error);

	FontAtlasBuildConfig mConfig;
};
}
