
#ifndef SPECTRE_GRAPHICS_SHADER_PROGRAM_H
#define SPECTRE_GRAPHICS_SHADER_PROGRAM_H

#include <string>
#include <Spectre/Math/Matrix4.h>
#include "Shader.h"

struct Color;

class ShaderProgram
{
public :
	ShaderProgram();
	~ShaderProgram();

	void create();

	void destroy();

	void addShader(const Shader& shader);

	// Load a shader program from file.
	//
	// The following naming conventions are supported:
	//	<name>.glsl		- Virtual file, will load all real shader files with the same name.
	//	<name>.vert.glsl	- Vertex shader.
	//	<name>.frag.glsl	- Fragment shader.
	bool loadFromFile(const std::string& filename);

	// Load a shader from file.
	bool loadFromFile(const std::string& filename, Shader::Type type);

	// Load a shader from memory.
	bool loadFromMemory(const std::string& source, Shader::Type type);

	// Link the program.
	bool link();

	// Returns true if the program was linked successfully
	bool isLinked() const;
	
	// Enable this shader 
	// All shader operations after this call will affect this shader.
	void enable() const;
	
	// Disable this shader
	// Operations will no longer affect this shader after this call.
	void disable() const;

	// Get the last shader error.
	std::string getLastError() const;

	// ---------------------
	// Variables.
	// ---------------------

	bool setMVPMatrix(const Matrix4f& matrix);

	// ---------------------
	//  General Variables.
	// ---------------------

	bool setAttribute(const std::string& name, float value) const;

	bool setAttribute(const std::string& name, const Matrix4f& matrix) const;

	bool setUniform(const std::string& name, const Matrix4f& matrix) const;

	bool setUniform(const std::string& name, const Color& color) const;

protected :

	bool getAttribLoc(const std::string& name, int& loc) const;
	bool getUniformLoc(const std::string& name, int& loc) const;

	std::string fetchErrorLog();

protected :

	unsigned int		m_id; // program id

	mutable std::string	m_error;
};

#endif /* SPECTRE_GRAPHICS_SHADER_PROGRAM_H */