#include <cub.h>
Cub::Cub(){}

Cub::Cub(float anchura, float altura, float profundidad)
{
    //std::cout<<"Estic en el constructor del cub\n";
    // Cub centrat al 0,0,0 amb dimensió 1 a totes les seves arestes
    xorig = 0; yorig = 0; zorig = 0;
    a = anchura;
    h = altura;
    p = profundidad;

    Index = 0; // index de control dels vertexs a enviar a la GPU

}


// Constructora amb tots els parametres
Cub::Cub(int an, int al, int profu, const GLfloat x0, GLfloat y0, GLfloat z0)
{
    Index = 0; // index de control dels vertexs a enviar a la GPU

   // std::cout<<"Estic en el constructor parametritzat del cub\n";
    a = an;
    h = al;
    p = profu;
    xorig = x0;
    yorig = y0;
    zorig = z0;
}

// Destructora
Cub::~Cub()
{
}

// quad generates two triangles for each face and assigns colors
//    to the vertices

void Cub::quad( int a, int b, int c, int d )
{
    colors[Index] = vertex_colors[a]; points[Index] = vertices[a]; tex_coords3D[Index] = verticesTex[a]; Index++;
    colors[Index] = vertex_colors[b]; points[Index] = vertices[b]; tex_coords3D[Index] = verticesTex[b]; Index++;
    colors[Index] = vertex_colors[c]; points[Index] = vertices[c]; tex_coords3D[Index] = verticesTex[c]; Index++;
    colors[Index] = vertex_colors[a]; points[Index] = vertices[a]; tex_coords3D[Index] = verticesTex[a]; Index++;
    colors[Index] = vertex_colors[c]; points[Index] = vertices[c]; tex_coords3D[Index] = verticesTex[c]; Index++;
    colors[Index] = vertex_colors[d]; points[Index] = vertices[d]; tex_coords3D[Index] = verticesTex[d]; Index++;
}


// Realitzacio de la geometria del cub en una genList o en el vertex array, segons el que visualitzem

void Cub::make()
{
    //std::cout<<"Estic en el make del cub\n";
    // generacio de la geometria dels triangles per a visualitzar-lo
    Index = 0;
    genQuads(a , h , p);




}

void Cub::vertex(float x, float y, float z)
{
    colors[Index] = vec4(x,y,z, 1.0);
    tex_coords3D[Index] = vec4(x/a, y/h, z/p, 1.0);
    points[Index] = vec4(x,y,z, 1.0);
    Index++;
}

void Cub::genQuads(float x, float y, float z)
{

    /* Back side */
    vertex(0.0, 0.0, 0.0);
    vertex(0.0, y, 0.0);
    vertex(x, y, 0.0);
    vertex(x, 0.0, 0.0);

    /* Front side */
    vertex(0.0, 0.0, z);
    vertex(x, 0.0, z);
    vertex(x, y, z);
    vertex(0.0, y, z);

    /* Top side */
    vertex(0.0, y, 0.0);
    vertex(0.0, y, z);
    vertex(x, y, z);
    vertex(x, y, 0.0);

    /* Bottom side */
    vertex(0.0, 0.0, 0.0);
    vertex(x, 0.0, 0.0);
    vertex(x, 0.0, z);
    vertex(0.0, 0.0, z);

    /* Left side */
    vertex(0.0, 0.0, 0.0);
    vertex(0.0, 0.0, z);
    vertex(0.0, y, z);
    vertex(0.0, y, 0.0);

    /* Right side */
    vertex(x, 0.0, 0.0);
    vertex(x, y, 0.0);
    vertex(x, y, z);
    vertex(x, 0.0, z);

}

void Cub::translate(double x, double y, double z) {

    //Movem tots els punts de la figura
    for(int i = 0; i < Index; i++){
        points[i].x += x;
        points[i].y += y;
        points[i].z += z;
    }
}


void Cub::toGPU(QGLShaderProgram *program) {

    // Creació d'un vertex array object
    GLuint vao;
    glGenVertexArrays( 1, &vao );
    glBindVertexArray( vao );

    // Creacio i inicialitzacio d'un buffer object
    GLuint buffer;
    glGenBuffers( 1, &buffer );
    glBindBuffer( GL_ARRAY_BUFFER, buffer );
    glBufferData( GL_ARRAY_BUFFER, sizeof(points) + sizeof(colors) + sizeof(tex_coords3D),
    NULL, GL_STATIC_DRAW );
    glBufferSubData( GL_ARRAY_BUFFER, 0, sizeof(points), points );
    glBufferSubData( GL_ARRAY_BUFFER, sizeof(points), sizeof(colors), colors );
    glBufferSubData( GL_ARRAY_BUFFER, sizeof(points)+sizeof(colors), sizeof(tex_coords3D), tex_coords3D);
    // set up vertex arrays

    int vertexLocation = program->attributeLocation("vPosition");
    int colorLocation = program->attributeLocation("vColor");
    int texcoordLocation = program->attributeLocation("vTexCoord3D");


    program->enableAttributeArray(vertexLocation);
    program->setAttributeBuffer(vertexLocation, GL_FLOAT, 0, 4);
    // program->setAttributeArray(vertexLocation, points, 4, Index);

    program->enableAttributeArray(colorLocation);
    program->setAttributeBuffer(colorLocation, GL_FLOAT, sizeof(points), 4);

    program->enableAttributeArray(texcoordLocation);
    program->setAttributeBuffer(texcoordLocation, GL_FLOAT, sizeof(points)+sizeof(colors), 4);

    program->bindAttributeLocation("vPosition", vertexLocation);
    program->bindAttributeLocation("vColor", colorLocation);
    program->bindAttributeLocation("vTexCoord3D", texcoordLocation);
    program->link();

    program->bind();
    glEnable( GL_DEPTH_TEST );



}

// Pintat de les Vertex Arrays
void Cub::draw(QGLShaderProgram *program)
{

    int vertexLocation = program->attributeLocation("vPosition");
    int colorLocation = program->attributeLocation("vColor");
    int texcoordLocation = program->attributeLocation("vTexCoord3D");

    glBufferSubData( GL_ARRAY_BUFFER, 0, sizeof(points), points );
    glBufferSubData( GL_ARRAY_BUFFER, sizeof(points), sizeof(colors), colors );
    glBufferSubData(GL_ARRAY_BUFFER, sizeof(points)+sizeof(colors), sizeof(tex_coords3D), tex_coords3D);

    program->enableAttributeArray(vertexLocation);
    program->setAttributeBuffer(vertexLocation, GL_FLOAT, 0, 4);

    program->enableAttributeArray(colorLocation);
    program->setAttributeBuffer(colorLocation, GL_FLOAT, sizeof(points), 4);

    program->enableAttributeArray(texcoordLocation);
    program->setAttributeBuffer(texcoordLocation, GL_FLOAT, sizeof(points)+sizeof(colors), 4);

    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    glDrawArrays( GL_QUADS, 0, NumVerticesC );
    program->disableAttributeArray(vertexLocation);
    program->disableAttributeArray(colorLocation);
    program->disableAttributeArray(texcoordLocation);

    program->release();

}


Capsa3D Cub::calculCapsa3D()
{


// A modificar

    /*pmin.x = 0;
    pmin.y = 0;
    pmin.z = 0;
    pmax.x = 1;
    pmax.y = 1;
    pmax.z = 1;*/

    vec3 pmin, pmax;

    pmin.x = 10000000000000;
    pmin.y = 10000000000000;
    pmin.z = 10000000000000;
    pmax.x = -10000000000000;
    pmax.y = -10000000000000;
    pmax.z = -10000000000000;

    for(int i = 0; i < Index; i++){


        if(pmin.x > points[i].x){
            pmin.x = points[i].x;
        }
        if(pmin.y > points[i].y){
            pmin.y = points[i].y;
        }
        if(pmin.z > points[i].z){
            pmin.z = points[i].z;
        }
        if(pmax.x < points[i].x){
            pmax.x = points[i].x;
        }
        if(pmax.y < points[i].y){
            pmax.y = points[i].y;
        }
        if(pmax.z < points[i].z){
            pmax.z = points[i].z;
        }
    }

    capsa.pmin = pmin;
    capsa.a = pmax[0]-pmin[0];
    capsa.h = pmax[1]-pmin[1];
    capsa.p = pmax[2]-pmin[2];
    return capsa;
}


void Cub::addListaVoxels(float x,float y,float z,float v,float i){}
void Cub::openVolumen(int a, int al, int p, QString t) {}
void Cub::setLut(const char *nF) {}
void Cub::abrirVolumen() {}
void Cub::setVoxel(int i, int j, int k, float v){}
float Cub::getVoxel(int i, int j, int k) { return 0.0f; }
void Cub::setVoxelMask(int i, int j, int k, float v){}
float Cub::getVoxelMask(int i, int j, int k) { return 0.0f; }

GLubyte* Cub::raycastingCPU(Camera cam, Capsa3D cub, float opacitat, float saturacio, float sampling, int colorMode, Llum *llum, float crem){}
void Cub::initMaterialsVolum(QGLShaderProgram *program){}
void Cub::setLoadedLUT(Lut *LUT){}
