#pragma once

#include "RenderSnapshotBuilder.h"

#include <mutex>
#include <string>
#include <vector>

class RuntimeEventDispatcher;

struct RuntimeRenderStateSnapshot
{
	RuntimeSnapshotVersions versions;
	unsigned outputWidth = 0;
	unsigned outputHeight = 0;
	std::vector<RuntimeRenderState> states;
};

class RuntimeSnapshotProvider
{
public:
	RuntimeSnapshotProvider(RenderSnapshotBuilder& renderSnapshotBuilder, RuntimeEventDispatcher& runtimeEventDispatcher);

	bool BuildLayerPassFragmentShaderSources(const std::string& layerId, std::vector<ShaderPassBuildSource>& passSources, std::string& error) const;
	unsigned GetMaxTemporalHistoryFrames() const;
	RuntimeSnapshotVersions GetVersions() const;
	void AdvanceFrame();
	RuntimeRenderStateSnapshot PublishRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight) const;
	bool TryPublishRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight, RuntimeRenderStateSnapshot& snapshot) const;
	bool TryRefreshPublishedSnapshotParameters(RuntimeRenderStateSnapshot& snapshot) const;
	void RefreshDynamicRenderStateFields(std::vector<RuntimeRenderState>& states) const;

private:
	bool TryGetPublishedRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight,
		const RuntimeSnapshotVersions& versions, RuntimeRenderStateSnapshot& snapshot) const;
	void StorePublishedRenderStateSnapshot(const RuntimeRenderStateSnapshot& snapshot) const;
	static bool SnapshotMatches(const RuntimeRenderStateSnapshot& snapshot, unsigned outputWidth, unsigned outputHeight,
		const RuntimeSnapshotVersions& versions);
	void PublishRenderSnapshotPublishRequested(unsigned outputWidth, unsigned outputHeight, const std::string& reason) const;
	void PublishRenderSnapshotPublished(const RuntimeRenderStateSnapshot& snapshot) const;

	RenderSnapshotBuilder& mRenderSnapshotBuilder;
	RuntimeEventDispatcher& mRuntimeEventDispatcher;
	mutable std::mutex mPublishedSnapshotMutex;
	mutable bool mHasPublishedRenderStateSnapshot = false;
	mutable RuntimeRenderStateSnapshot mPublishedRenderStateSnapshot;
};
