#ifndef MRL_SHADER
#define MRL_SHADER

#include <string>
#include <fstream>
#include "gl.hpp"
#include "glm/glm.hpp"

//for SetUniform
#include "Vector3d.hpp"

class VertexShader
{
public:
	VertexShader();
	VertexShader(const VertexShader& ref);
	~VertexShader();

	GLuint Load(std::string Filename);///< Create the shader from a file, calls Create()
	GLuint Create(std::string Source);///< Creates the shader from the source
	inline GLuint GetVertexObject() const;
private:
	GLuint m_VertexObject;
};


class FragmentShader
{
public:
	FragmentShader();
	FragmentShader(const FragmentShader& ref);
	~FragmentShader();

	GLuint Load(std::string Filename);///< Create the shader from a file, calls Create()
	GLuint Create(std::string Source);///< Creates the shader from the source
	inline GLuint GetFragmentObject() const;
private:
	GLuint m_FragmentObject;
};


class Shader
{
public:
	Shader();
	Shader(const Shader& ref);//cpy-ctor
	~Shader();

	bool Load(std::string VertexFile, std::string FragmentFile);
	bool Create(std::string VertexSource, std::string FragmentSource);
	void Set() const;
	void Unset() const;
	inline GLuint GetProgram() const {return m_ProgramObject;}

	void SetUniform(std::string Name, float Value);
	void SetUniform(std::string Name, Vector3f Value);
	void SetUniform(std::string Name, int Value);
	void SetUniform(std::string Name, GLuint Value);
	void SetUniform(std::string Name, glm::vec2 Value);
	void SetUniform(std::string Name, glm::uvec2 Value);
	void SetUniform(std::string Name, glm::vec3 Value);
private:
	bool ProcessShader();///< is called after Shader::Load() or Shader::Create()
	GLuint m_ProgramObject;
	VertexShader m_VertexShader;
	FragmentShader m_FragmentShader;
};

#endif // _SHADER_
