#pragma once

#include "OpenGLRenderer.h"
#include "ShaderTypes.h"

#include <string>
#include <vector>

class ShaderTextureBindings
{
public:
	using LayerProgram = OpenGLRenderer::LayerProgram;
	using PassProgram = OpenGLRenderer::LayerProgram::PassProgram;

	struct RuntimeTextureBinding
	{
		std::string semanticName;
		std::string samplerName;
		GLuint texture = 0;
		GLuint textureUnit = 0;
	};

	struct RuntimeTextureBindingPlan
	{
		std::vector<RuntimeTextureBinding> bindings;
	};

	bool LoadTextureAsset(const ShaderTextureAsset& textureAsset, GLuint& textureId, std::string& error);
	void CreateTextBindings(const RuntimeRenderState& state, std::vector<LayerProgram::TextBinding>& textBindings);
	bool UpdateTextBindingTexture(const RuntimeRenderState& state, LayerProgram::TextBinding& textBinding, std::string& error);
	GLint FindSamplerUniformLocation(GLuint program, const std::string& samplerName) const;
	GLuint ResolveFeedbackTextureUnit(const RuntimeRenderState& state, unsigned historyCap) const;
	GLuint ResolveShaderTextureBase(const RuntimeRenderState& state, unsigned historyCap) const;
	void AssignLayerSamplerUniforms(GLuint program, const RuntimeRenderState& state, const PassProgram& passProgram, unsigned historyCap) const;
	RuntimeTextureBindingPlan BuildLayerRuntimeBindingPlan(
		const PassProgram& passProgram,
		GLuint layerInputTexture,
		GLuint originalLayerInputTexture,
		const RuntimeRenderState& state,
		GLuint feedbackTexture,
		const std::vector<GLuint>& sourceHistoryTextures,
		const std::vector<GLuint>& temporalHistoryTextures) const;
	void BindRuntimeTexturePlan(const RuntimeTextureBindingPlan& plan) const;
	void UnbindRuntimeTexturePlan(const RuntimeTextureBindingPlan& plan) const;
};
