#ifndef GLSHADER_GLM_HPP_
#define GLSHADER_GLM_HPP_


#include <GL/glew.h>

#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>

#include <glshader.hpp>


#define GLSHADER_UNIFORM_GLM_N_(N, GLM_TYPE, SUFFIX) \
    GLSHADER_UNIFORM( \
        glm::GLM_TYPE##N, \
        glUniform##N##SUFFIX##v( \
            location, 1, glm::value_ptr(value) \
        ); \
    )

#define GLSHADER_UNIFORM_GLM_N_BOOL_(N) \
    GLSHADER_UNIFORM( \
        glm::bvec##N, \
        GLint int_value[N]; \
        for (auto i = 0; i < N; ++i) \
            int_value[i] = value[i]; \
        glUniform##N##iv( \
            location, 1, &int_value[0] \
        ); \
    )

#define GLSHADER_UNIFORM_GLM_MATRIX_N_(N) \
    GLSHADER_UNIFORM( \
        glm::mat##N, \
        glUniformMatrix##N##fv( \
            location, 1, GL_FALSE, glm::value_ptr(value) \
        ); \
    )

#define GLSHADER_UNIFORM_GLM_MATRIX_N_M_(N, M) \
    GLSHADER_UNIFORM( \
        glm::mat##N##x##M, \
        glUniformMatrix##N##x##M##fv( \
            location, 1, GL_FALSE, glm::value_ptr(value) \
        ); \
    )

GLSHADER_UNIFORM_GLM_N_BOOL_(2)
GLSHADER_UNIFORM_GLM_N_BOOL_(3)
GLSHADER_UNIFORM_GLM_N_BOOL_(4)
GLSHADER_UNIFORM_GLM_N_(2, ivec, i)
GLSHADER_UNIFORM_GLM_N_(3, ivec, i)
GLSHADER_UNIFORM_GLM_N_(4, ivec, i)
GLSHADER_UNIFORM_GLM_N_(2, uvec, ui)
GLSHADER_UNIFORM_GLM_N_(3, uvec, ui)
GLSHADER_UNIFORM_GLM_N_(4, uvec, ui)
GLSHADER_UNIFORM_GLM_N_(2, vec, f)
GLSHADER_UNIFORM_GLM_N_(3, vec, f)
GLSHADER_UNIFORM_GLM_N_(4, vec, f)

GLSHADER_UNIFORM_GLM_MATRIX_N_(2)
GLSHADER_UNIFORM_GLM_MATRIX_N_(3)
GLSHADER_UNIFORM_GLM_MATRIX_N_(4)

GLSHADER_UNIFORM_GLM_MATRIX_N_M_(2, 3)
GLSHADER_UNIFORM_GLM_MATRIX_N_M_(2, 4)
GLSHADER_UNIFORM_GLM_MATRIX_N_M_(3, 2)
GLSHADER_UNIFORM_GLM_MATRIX_N_M_(3, 4)
GLSHADER_UNIFORM_GLM_MATRIX_N_M_(4, 2)
GLSHADER_UNIFORM_GLM_MATRIX_N_M_(4, 3)


#endif // GLSHADER_GLM_HPP_
