#include "SupportedShaderCatalog.h"

#include "ShaderPackageRegistry.h"

#include <map>
#include <utility>

namespace RenderCadenceCompositor
{
ShaderSupportResult CheckStatelessSinglePassShaderSupport(const ShaderPackage& shaderPackage)
{
	if (shaderPackage.passes.size() != 1)
		return { false, "RenderCadenceCompositor currently supports only single-pass runtime shaders." };

	if (shaderPackage.temporal.enabled)
		return { false, "RenderCadenceCompositor currently supports only stateless shaders; temporal history is not enabled in this app." };

	if (shaderPackage.feedback.enabled)
		return { false, "RenderCadenceCompositor currently supports only stateless shaders; feedback storage is not enabled in this app." };

	if (!shaderPackage.textureAssets.empty())
		return { false, "RenderCadenceCompositor does not load shader texture assets yet; texture-backed shaders need a CPU-prepared asset handoff first." };

	if (!shaderPackage.fontAssets.empty())
		return { false, "RenderCadenceCompositor does not load shader font assets yet; text shaders need a CPU-prepared asset handoff first." };

	for (const ShaderParameterDefinition& parameter : shaderPackage.parameters)
	{
		if (parameter.type == ShaderParameterType::Text)
			return { false, "RenderCadenceCompositor currently skips text parameters because they require per-shader text texture storage." };
	}

	return { true, std::string() };
}

bool SupportedShaderCatalog::Load(const std::filesystem::path& shaderRoot, unsigned maxTemporalHistoryFrames, std::string& error)
{
	mShaders.clear();
	mPackagesById.clear();

	if (shaderRoot.empty())
	{
		error = "Shader library path is empty.";
		return false;
	}

	ShaderPackageRegistry registry(maxTemporalHistoryFrames);
	std::map<std::string, ShaderPackage> packagesById;
	std::vector<std::string> packageOrder;
	std::vector<ShaderPackageStatus> packageStatuses;
	if (!registry.Scan(shaderRoot, packagesById, packageOrder, packageStatuses, error))
		return false;

	for (const std::string& packageId : packageOrder)
	{
		const auto packageIt = packagesById.find(packageId);
		if (packageIt == packagesById.end())
			continue;

		const ShaderPackage& shaderPackage = packageIt->second;
		const ShaderSupportResult support = CheckStatelessSinglePassShaderSupport(shaderPackage);
		if (!support.supported)
			continue;

		SupportedShaderSummary summary;
		summary.id = shaderPackage.id;
		summary.name = shaderPackage.displayName.empty() ? shaderPackage.id : shaderPackage.displayName;
		summary.description = shaderPackage.description;
		summary.category = shaderPackage.category;
		mShaders.push_back(std::move(summary));
		mPackagesById[shaderPackage.id] = shaderPackage;
	}

	error.clear();
	return true;
}

const ShaderPackage* SupportedShaderCatalog::FindPackage(const std::string& shaderId) const
{
	const auto packageIt = mPackagesById.find(shaderId);
	return packageIt == mPackagesById.end() ? nullptr : &packageIt->second;
}
}
