#include "controlseleccio.h"
#include    <sys/timeb.h>
using namespace std;

ControlSeleccio::ControlSeleccio(){
    escena = new Escena();
    gpu = new X_Ray_gpu();
    cpu = new Gray_Scale_cpu();
    texturewidget = new textureWidget();
    cpu->texturewidget = texturewidget;
    colormascara = new vec4(0.0,1.0,1.0,0.0);
}



void ControlSeleccio::setOpacitatGPU(float opacitat, float saturacio, float sampling, float cream){
    ActualitzarRC(opacitat,saturacio,sampling,cream/10);

}

void ControlSeleccio::setSaturacioGPU(float p){ // threshold
  //  cout <<"setSaturacioGPU "<<p<< endl;
    escena->setSaturacio(p);
}

void ControlSeleccio::setCremGPU(float opacitat,float saturacio,float sampling,float crem){
    ActualitzarRC(opacitat,saturacio,sampling,crem);
}

void ControlSeleccio::setK(float p){
    escena->setK(p);
}

void ControlSeleccio::setSamplingGPU(int p){
   // cout <<"setSamplingGPU "<<p<< endl;
}

void ControlSeleccio::cambibackground(){
    escena->cambibackground();
    this->texturewidget->cambibackground();
}

void ControlSeleccio::cargarVolumen(char* fitxer,int anch,int alt,int profu,QString tipoUns ){
    escena->cargarVolumen(fitxer,anch,alt,profu,tipoUns);
}



void ControlSeleccio::onRampChanged(QVector<unsigned int> qrgbcolors){
    escena->setRampColorTable(qrgbcolors);
}

bool ControlSeleccio::confirmarVolum(){
    if( escena->getVolum()!= NULL ) return true;
    else{
        QMessageBox *qMessBox = new QMessageBox(QMessageBox::Warning, "Alerta", "No pots activar el Ray Casting si no has obert cap volum.", QMessageBox::Ok);
        qMessBox->show();
    }
    return false;
}


void ControlSeleccio::rcgGS(float opacitat, float saturacio, float sampling, float cream){
    gpu = new X_Ray_gpu();
    if(confirmarVolum()){

        escena->setOpacitat(opacitat);
        escena->setSaturacio(saturacio/100);
        escena->setSampling(sampling);
        escena->setCrem(cream);

        escena->setGPU(gpu);
        escena->setColorMode(0);

        escena->startRaycasting();


    }

}
void ControlSeleccio::rccGS(float opacitat,float saturacio, float sampling,float cream ){

    cpu = new Gray_Scale_cpu(this->texturewidget);

    if (confirmarVolum()){

        escena->setLoadedLUT();

        Parametres* p = carregaParametres(0,opacitat,saturacio,sampling,cream);


        clock_t startC, finishC;
        struct timeb startT, finishT;
        unsigned int seconds, milliseconds;

        startC = clock();
        ftime(&startT);

        GLubyte *ptTex = cpu->raycastingCPU(p);

       float wi = escena->getCamera().vp.a;
       float he = escena->getCamera().vp.h;

        cpu->ShowRCCPUResults(ptTex,wi,he);

        finishC = clock();
        ftime(&finishT);
        seconds = finishT.time - startT.time - 1;
        milliseconds = (1000 - startT.millitm) + finishT.millitm;
        /*cout <<"raycasting cpu grayscale"<<endl;
        cout << "Time (clock): "    << (finishC - startC)/CLOCKS_PER_SEC << endl;
        cout << "Time (difftime): " << difftime(finishC, startC) << endl;
        cout << "Time (ftime): " << (milliseconds + seconds * 1000) << endl;*/
    }

}

void ControlSeleccio::rcgLut(float opacitat,float saturacio, float sampling,float cream){

    gpu = new Lut_gpu();

    if(confirmarVolum()){

        escena->setOpacitat(opacitat);
        escena->setSaturacio(saturacio/100);
        escena->setSampling(sampling);
        escena->setCrem(cream);

        escena->setGPU(gpu);
        escena->setColorMode(1);



        escena->startRaycasting();



    }
}
void ControlSeleccio::rccLut(float opacitat,float saturacio, float sampling,float cream ){

    cpu = new Lut_cpu(this->texturewidget);

    if (confirmarVolum()){

        escena->setLoadedLUT();

        Parametres* p = carregaParametres(1,opacitat,saturacio,sampling,cream);

        clock_t startC, finishC;
               struct timeb startT, finishT;
               unsigned int seconds, milliseconds;
               startC = clock();
               ftime(&startT);
        GLubyte *ptTex = cpu->raycastingCPU(p);

        float wi = escena->getCamera().vp.a;
        float he = escena->getCamera().vp.h;

        cpu->ShowRCCPUResults(ptTex,wi,he);

        finishC = clock();
        ftime(&finishT);
        seconds = finishT.time - startT.time - 1;
        milliseconds = (1000 - startT.millitm) + finishT.millitm;
     /*   cout << "\n RayCasting cPU lut"<<endl;
        cout << "Time (clock): "    << (finishC - startC)/CLOCKS_PER_SEC << endl;
        cout << "Time (difftime): " << difftime(finishC, startC) << endl;
        cout << "Time (ftime): " << (milliseconds + seconds * 1000) << endl;*/
        }
}

void ControlSeleccio::rcgPB(float opacitat,float saturacio, float sampling,float cream){

    gpu = new Phong_Blinn_gpu();

    if(confirmarVolum()){

        escena->setOpacitat(opacitat);
        escena->setSaturacio(saturacio/100);
        escena->setSampling(sampling);
        escena->setCrem(cream);

        escena->setGPU(gpu);
        escena->setColorMode(2);



        escena->startRaycasting();


    }

}
void ControlSeleccio::rccPB(float opacitat,float saturacio, float sampling,float cream ){

    cpu = new Phong_Blinn_cpu(this->texturewidget);

    if (confirmarVolum()){

        escena->setLoadedLUT();

        Parametres* p = carregaParametres(2,opacitat,saturacio,sampling,cream);

        GLubyte *ptTex = cpu->raycastingCPU(p);

        float wi = escena->getCamera().vp.a;
        float he = escena->getCamera().vp.h;

        clock_t startC, finishC;
        struct timeb startT, finishT;
        unsigned int seconds, milliseconds;

        startC = clock();
        ftime(&startT);

        cpu->ShowRCCPUResults(ptTex,wi,he);

        finishC = clock();
        ftime(&finishT);
        seconds = finishT.time - startT.time - 1;
        milliseconds = (1000 - startT.millitm) + finishT.millitm;
    /*    cout << "\n RayCasting CPU phong blinn "<<endl;
        cout << "Time (clock): "    << (finishC - startC)/CLOCKS_PER_SEC << endl;
        cout << "Time (difftime): " << difftime(finishC, startC) << endl;
        cout << "Time (ftime): " << (milliseconds + seconds * 1000) << endl;*/

    }
}

void ControlSeleccio::rcgMip(float opacitat,float saturacio, float sampling,float cream){

    gpu = new Mip_gpu();

    if(confirmarVolum()){

        escena->setOpacitat(opacitat);
        escena->setSaturacio(saturacio/100);
        escena->setSampling(sampling);
        escena->setCrem(cream);

        escena->setGPU(gpu);
        escena->setColorMode(3);



        escena->startRaycasting();


    }
}
void ControlSeleccio::rccMip(float opacitat,float saturacio, float sampling,float cream ){

    cpu = new Mip_cpu(this->texturewidget);

    if (confirmarVolum()){

        escena->setLoadedLUT();

        Parametres* p = carregaParametres(3,opacitat,saturacio,sampling,cream);

        clock_t startC, finishC;
               struct timeb startT, finishT;
               unsigned int seconds, milliseconds;
               startC = clock();
               ftime(&startT);
        GLubyte *ptTex = cpu->raycastingCPU(p);

        float wi = escena->getCamera().vp.a;
        float he = escena->getCamera().vp.h;


        cpu->ShowRCCPUResults(ptTex,wi,he);

        finishC = clock();
        ftime(&finishT);
        seconds = finishT.time - startT.time - 1;
        milliseconds = (1000 - startT.millitm) + finishT.millitm;
    /*    cout << "\n RayCasting cPU mip"<<endl;
        cout << "Time (clock): "    << (finishC - startC)/CLOCKS_PER_SEC << endl;
        cout << "Time (difftime): " << difftime(finishC, startC) << endl;
        cout << "Time (ftime): " << (milliseconds + seconds * 1000) << endl;*/
    }
}

void ControlSeleccio::rcgMida(float opacitat,float saturacio, float sampling,float cream){

    gpu = new Mida_gpu();

    if(confirmarVolum()){

        escena->setOpacitat(opacitat);
        escena->setSaturacio(saturacio/100);
        escena->setSampling(sampling);
        escena->setCrem(cream);

        escena->setGPU(gpu);
        escena->setColorMode(4);


        escena->startRaycasting();

    }
}
void ControlSeleccio::rccMida(float opacitat,float saturacio, float sampling,float cream ){

    cpu = new Mida_cpu(this->texturewidget);

    if (confirmarVolum()){

        escena->setLoadedLUT();

        Parametres* p = carregaParametres(4,opacitat,saturacio,sampling,cream);

        clock_t startC, finishC;
               struct timeb startT, finishT;
               unsigned int seconds, milliseconds;
               startC = clock();
               ftime(&startT);
        GLubyte *ptTex = cpu->raycastingCPU(p);

        float wi = escena->getCamera().vp.a;
        float he = escena->getCamera().vp.h;

        cpu->ShowRCCPUResults(ptTex,wi,he);

        finishC = clock();
        ftime(&finishT);
        seconds = finishT.time - startT.time - 1;
        milliseconds = (1000 - startT.millitm) + finishT.millitm;

     /*   cout << "Time (clock): "    << (finishC - startC)/CLOCKS_PER_SEC << endl;
        cout << "Time (difftime): " << difftime(finishC, startC) << endl;
        cout << "Time (ftime): " << (milliseconds + seconds * 1000) << endl; */ }
}

void ControlSeleccio::rcgMida2(float opacitat,float saturacio, float sampling,float cream){

    gpu = new Mida2_gpu();

    if(confirmarVolum()){

        escena->setOpacitat(opacitat);
        escena->setSaturacio(saturacio/100);
        escena->setSampling(sampling);
        escena->setCrem(cream);

        escena->setGPU(gpu);
        escena->setColorMode(4);


        escena->startRaycasting();

    }
}

Parametres* ControlSeleccio::carregaParametres(int opcio, float opacitat,float saturacio, float sampling,float cream){

    Parametres* p = new Parametres();

    p->camera = escena->getCamera();
    p->capsaminima = escena->getCapsaMinima();
    p->opacitat = opacitat;
    p->saturacio = saturacio;
    p->sampling = sampling;

    p->colorMode = opcio;

    p->llum = escena->getLlum();
    p->crem = cream;
    p->voxels = escena->getVolum()->getVoxels();
    p->mask = escena->getVolum()->getMask();
    p->primari = escena->getVolum()->getPrimari();
    p->secundari = escena->getVolum()->materialSecundari;
    p->colores = escena->getVolum()->colores;
    p->lista = escena->getVolum()->lista;
    p->uns = escena->getVolum()->uns;
    p->f1 = escena->getVolum()->f1;
    p->imagen = escena->getVolum()->imagen;
    p->nombreFichero = escena->getVolum()->nombreFichero;
    p->unsCS=escena->getVolum()->unsCS;
    p->capas = escena->getVolum()->capas;
    p->points = escena->getVolum()->points;
    p->normals = escena->getVolum()->normals;
    p->colors = escena->getVolum()->colors;
    p->hit = escena->getVolum()->hit;

    p->altura = escena->getVolum()->altura;
    p->profundidad = escena->getVolum()->profundidad;
    p->anchura = escena->getVolum()->anchura;
    p->NumVoxelsMon = escena->getVolum()->NumVoxelsMon;
    p->ColorMascara = this->colormascara;
    p->gamma = &(escena->gammaMida);
    return p;
}
void ControlSeleccio::activaMask(bool p){
    escena->activaMask(p);
}

void ControlSeleccio::onlyMask(bool p){
    escena->onlyMask(p);
}

void ControlSeleccio::ActualitzarRC(float opacitat,float saturacio, float sampling,float cream){

    if(confirmarVolum()){

        // actualitzar RC GPU
       // escena->setLoadedLUT();
        escena->setOpacitat(opacitat);
        escena->setSaturacio(saturacio/100);
        escena->setSampling(sampling);
        escena->setCrem(cream);

        escena->setGPU(gpu);
       // escena->setColorMode(4);
        escena->startRaycasting();

        // Actualitzar RC CPU
      /*  escena->setLoadedLUT();

        Parametres* p = carregaParametres(4,opacitat,saturacio,sampling,cream);

        GLubyte *ptTex = cpu->raycastingCPU(p);

        float wi = escena->getCamera().vp.a;
        float he = escena->getCamera().vp.h;

        cpu->ShowRCCPUResults(ptTex,wi,he);*/

    }
}

void ControlSeleccio::setColorMascara(QColor c){
    colormascara->x = abs(c.red()-255);
    colormascara->y = abs(c.green()-255);
    colormascara->z = abs(c.blue()-255);
    colormascara->w = abs(c.alpha()-255);

    escena->setColorMask(c);

}

