#ifndef _Shader_h_
#define _Shader_h_

#include "opengl.h"
#include <iostream>


/** Permet de manipuler des shaders en GLSL
    Exemple d'utilisation:
    \code
    // shader creation:
    Shader* myShader = new Shader();
    // loading from files (compilation + linking):
    myShader->loadFromFiles("myShaderFile.vtx", "myShaderFile.frg");

    // ...

    // at rending time:
    myShader->activate();
    // draw objects
    \endcode
*/

class Shader
{
public:
    Shader()
      : _is_valid(false)
    {}

    ~Shader();

    /** Compiles and links the shader from 2 source files
        \param fileV vertex shader ("" if no vertex shader)
        \param fileF fragment shader ("" if no fragment shader)
        \return true if no error occurs
    */
    bool loadFromFiles(const std::string& fileV, const std::string& fileF);

    /** Compiles and links the shader from 2 strings
        \param vsrc vertex shader ("" if no vertex shader)
        \param fsrc fragment shader ("" if no fragment shader)
        \return true if no error occurs
    */
    bool loadSources(const std::string& vsrc, const std::string& fsrc);

    /** Enable / Disable the shader
    */
    void activate() const;
    void deactivate() const;

    /** \return the index of the uniform variable \a name
    */
    int getUniformLocation(const char* name) const;

    /** Forces a sampler to a given unit
        Example:
        \code
    glActiveTexture(GL_TEXTURE2);
    glBindTexture(GL_TEXTURE2D, myTextureID);
    myShader->setSamplerUnit("mySampler", 2);
        \endcode
    */
    void setSamplerUnit(const char* samplerName, int textureUnit) const;

    /** \returns the index of the generic attribute \a name
        To be used with glVertexAttribPointer(...)
        Example:
        \code
    int tangentAttribID = myShader->getAttribLocation("tangent");
    Vector3f* tangents = new Vector3f[...];
    glVertexAttribPointer(tangentAttribID, 3, GL_FLOAT, GL_FALSE, 0, tangents);
    glEnableVertexAttribArray(tangentAttribID);
        \endcode
    */
    int getAttribLocation(const char* name) const;

    /** \returns the OpenGL object id of the GLSL program */
    int id() const { return _id; }
    
    bool valid() const { return _is_valid; }
    void clear();

    void dumpInfos() const;

protected:
    static void printProgramInfoLog(GLuint objectID);
    static void printShaderInfoLog(GLuint objectID);

    bool _is_valid;
    GLuint _id;
};

#endif
