#include "ogl4_texture.h"
#include <memory.h>
#include <GL/gl.h>

namespace sleek
{
    namespace driver
    {
        template<>
        ogl4_texture<false>::ogl4_texture(texture *o) noexcept : identifier(o)
        {
            glGenTextures(1, &gl);
            glBindTexture(GL_TEXTURE_2D, gl);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        }

        template<>
        ogl4_texture<true>::ogl4_texture(texture *o) noexcept : identifier(o)
        {
            glGenTextures(1, &gl);
            glTextureParameteriEXT(gl, GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
            glTextureParameteriEXT(gl, GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
            glTextureParameteriEXT(gl, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTextureParameteriEXT(gl, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        }

        template<bool i>
        ogl4_texture<i>::~ogl4_texture() noexcept
        {
            glDeleteTextures(1, &gl);
        }

        template<bool i>
        void* ogl4_texture<i>::getHardwareLink() const noexcept
        {
            GLuint *tmp = (GLuint*)&gl;
            return tmp;
        }

        template<bool i>
        void ogl4_texture<i>::bind() noexcept
        {
            glBindTexture(GL_TEXTURE_2D, gl);
        }

        template<bool i>
        void ogl4_texture<i>::unbind() noexcept
        {
            glBindTexture(GL_TEXTURE_2D, 0);
        }

        template<>
        void ogl4_texture<false>::update() noexcept
        {
            texture *tmp = static_cast<texture*>(owner);
            glEnable(GL_TEXTURE_2D);
            glActiveTexture(GL_TEXTURE0_ARB);

            bind();

            glTexImage2D(
                GL_TEXTURE_2D, 0, tmp->getComposantCount(),
                tmp->getOriginalSize().x, tmp->getOriginalSize().y, 0,
                ogl4_texture_format[tmp->getFormat()-1],
                ogl4_texture_type[tmp->getFormat()-1],
                tmp->getBuffer()
            );
        }

        template<>
        void ogl4_texture<true>::update() noexcept
        {
            texture *tmp = static_cast<texture*>(owner);
            glTextureImage2DEXT(
                gl, GL_TEXTURE_2D, 0, tmp->getComposantCount(),
                tmp->getOriginalSize().x, tmp->getOriginalSize().y, 0,
                ogl4_texture_format[tmp->getFormat()-1],
                ogl4_texture_type[tmp->getFormat()-1],
                tmp->getBuffer()
            );
        }
    }
}