#pragma once

#include "GLExtensions.h"
#include "../runtime/RuntimeShaderArtifact.h"

#include <cstdint>
#include <string>
#include <vector>

class RuntimeShaderRenderer
{
public:
	RuntimeShaderRenderer() = default;
	RuntimeShaderRenderer(const RuntimeShaderRenderer&) = delete;
	RuntimeShaderRenderer& operator=(const RuntimeShaderRenderer&) = delete;
	~RuntimeShaderRenderer();

	bool CommitFragmentShader(const std::string& fragmentShaderSource, std::string& error);
	bool CommitShaderArtifact(const RuntimeShaderArtifact& artifact, std::string& error);
	bool HasProgram() const { return mProgram != 0; }
	void RenderFrame(uint64_t frameIndex, unsigned width, unsigned height);
	void ShutdownGl();

private:
	bool EnsureStaticGlResources(std::string& error);
	bool CompileShader(GLenum shaderType, const char* source, GLuint& shader, std::string& error) const;
	bool BuildProgram(const std::string& fragmentShaderSource, GLuint& program, GLuint& vertexShader, GLuint& fragmentShader, std::string& error);
	void AssignSamplerUniforms(GLuint program) const;
	void UpdateGlobalParams(uint64_t frameIndex, unsigned width, unsigned height);
	void BindRuntimeTextures();
	void DestroyProgram();
	void DestroyStaticGlResources();

	RuntimeShaderArtifact mArtifact;
	GLuint mProgram = 0;
	GLuint mVertexShader = 0;
	GLuint mFragmentShader = 0;
	GLuint mVertexArray = 0;
	GLuint mGlobalParamsBuffer = 0;
	GLsizeiptr mGlobalParamsBufferSize = 0;
	GLuint mFallbackSourceTexture = 0;
	std::vector<unsigned char> mGlobalParamsScratch;
};
