#include "Mosaic.h"

//Constructeurs et destructeurs
Mosaic::Mosaic(std::string const vertexShader, std::string const fragmentShader, std::string const fichierImg, Uint8 redMask, Uint8 greenMask, Uint8 blueMask)
:m_shader(vertexShader, fragmentShader)
{
    /// Chargement de l'image
    SDL_Surface* image = SDL_LoadBMP(fichierImg.c_str());
    SDL_LockSurface( image );

    /// Attribution des couleurs
    if (image!=0)
    {
        // Préaparation des variables d'info et de manip
        unsigned char* pixels = (unsigned char*) image->pixels;
        Uint8 taille(image->format->BytesPerPixel);
        Uint32 ligne(DIM*taille);
        Uint8 red,green,blue,addRed,addBlue;
        if(image->format->Rmask == 0xff){
            addRed = 0;
            addBlue = 2;
        }
        else{
            addRed = 2;
            addBlue = 0;
        }

        // Balayage
        for (int y(0); y<DIM; y++)
            for (int x(0); x<DIM; x++)
            {
                // Chargement des couleurs
                red = pixels[(ligne*y)+x*taille+addRed];
                green = pixels[(ligne*y)+x*taille+1];
                blue = pixels[(ligne*y)+x*taille+addBlue];

                // Voxel non-affiché
                if (red==redMask && green==greenMask && blue==blueMask)
                    m_opaque[DIM-y-1][x]=false;

                // Voxel affiché : attribution des couleurs
                else
                {
                    m_opaque[DIM-y-1][x]=true;
                    m_mosaic[DIM-y-1][x].setColor((float)red/255.0f,(float)green/255.0f,(float)blue/255.0f);
                }

            }
    }
    else
        std::cout <<"Impossible de charger "<<fichierImg<<" dans Mosaic."<< std::endl;

    /// Shader
    m_shader.charger();

    /// Placement des cubes
    glm::vec3 deplacement(-DIM/2,-DIM/2,-0.5f);
    for (int y(0); y<DIM; y++)
    {
        for (int x(0); x<DIM; x++)
        {
            m_mosaic[y][x].move(deplacement);
            deplacement.x++;
        }
        deplacement.y++;
        deplacement.x=-DIM/2;
    }

    /// Déverouillage
    SDL_UnlockSurface( image );

    // Libération de la mémoire
    SDL_FreeSurface(image);
}

Mosaic::~Mosaic()
{

}


//Méthodes
void Mosaic::afficher(glm::mat4 &projection, glm::mat4 modelview)
{
    /// OpenGL verrouillages
    // Activation du shader
    glUseProgram(m_shader.getProgramID());
    // Envoi des matrices
    glUniformMatrix4fv(glGetUniformLocation(m_shader.getProgramID(), "projection"), 1, GL_FALSE, glm::value_ptr(projection));
    glUniformMatrix4fv(glGetUniformLocation(m_shader.getProgramID(), "modelview"), 1, GL_FALSE, glm::value_ptr(modelview));

    /// Balayage
    for (int y(0); y<DIM; y++)
        for (int x(0); x<DIM; x++)
            if(m_opaque[y][x])
                m_mosaic[y][x].afficher();

    /// OpenGL déverrouillages
    // Désactivation du shader
    glUseProgram(0);
}