/** 
* @file ICETools.cpp
* @brief simple ICE GUI tools
* @author Erik Rodner
* @date 03/13/2008

*/
#include "core/image/ImageT.h"
#include "core/vector/VectorT.h"
#include "core/vector/MatrixT.h"
#include <core/imagedisplay/ImageDisplay.h>
#include <core/image/Filter.h>

#include <iostream>

#include <core/image/RectT.h>

#include "vislearning/baselib/ICETools.h"

#include "core/basics/Exception.h"

using namespace OBJREC;

using namespace std;

using namespace NICE;

ICETools::ICETools()
{
}

ICETools::~ICETools()
{
}

void ICETools::selectRectangles ( const NICE::Image & panel, NICE::Image & overlay, vector<Vector> & x, int color )
{
	fthrow(Exception, "ICETools::selectRectangles -- not yet implemented due to old ICE version.");
// #ifndef NOVISUAL
//     // new NICE code
//     vector<RectT<double> > rectangles;
// 	 //TODO check this!
// //     NICE::selectRectangles ( panel, rectangles, "select rectangles" );
// // 	 selectRectangles ( panel, rectangles, "select rectangles" );
// 
//     for ( vector<RectT<double> >::const_iterator i = rectangles.begin();
// 	i != rectangles.end(); i++ )
//     {
// 	Vector vec (4);
// 	vec[0] = i->left;
// 	vec[1] = i->top;
// 	vec[2] = i->right();
// 	vec[3] = i->bottom();
// 
// 	x.push_back ( vec ); 
//     }
// #else
//     fprintf (stderr, "ICETools::selectRectangles: visualization disabled !\n");
// #endif
}

void ICETools::selectPoints ( const NICE::Image & panel, NICE::Image & overlay, vector<Vector> & x, int color )
{
	fthrow(Exception, "ICETools::selectPoints -- not yet implemented due to old ICE version.");
// #ifndef NOVISUAL
//     vector<CoordT<double> > points;
// 	 //TODO check this!
// //     NICE::selectPoints ( panel, points, "select points" );
// // 	selectPoints ( panel, points, "select points" );
// 
//     for ( vector<CoordT<double> >::const_iterator i = points.begin();
// 	i != points.end(); i++ )
//     {
// 	Vector vec (2);
// 	vec[0] = i->x;
// 	vec[1] = i->y;
// 
// 	x.push_back ( vec ); 
//     }
//    
//     /** OLD ICE Code
//     int p[2];
//     int rc = -1;
// 
//     while ( (rc = SelPoint ( DEFAULT, panel, p )) != -1 )
//     {
//         int x1, y1;
//         x1 = p[0]; y1 = p[1];
//         // refactor-nice.pl: check this substitution
//         // old: Marker ( DEFAULT, p[0], p[1], color, 5, overlay );
//         // REFACTOR-FIXME Unable to map this statement
//         // refactor-nice.pl: check this substitution
//         // old: x.push_back ( Vector(x1, y1) );
//         // REFACTOR-FIXME Unable to std::map this statement
//     }
//     */
// #else
//     fprintf (stderr, "ICETools::selectPoints: visualization disabled !\n");
// #endif

}

void ICETools::toColor ( double x, double & r, double & g, double & b )
{
    size_t seg = (size_t)(x * 6.0);
    double y   = ( 6*x - seg );

    switch ( seg ) {
	case 0: r=0.0; g=0.0; b=y;   break; 
	case 1: r=0.0; g=  y; b=1.0; break; 
	case 2: r=0.0; g=1.0; b=1.0-y; break; 
	case 3: r=  y; g=1.0; b=0.0;   break; 
	case 4: r=1.0; g=1.0-y; b=0.0;   break; 
	case 5: r=1.0; g=y; b=y;   break; 
	default: r=1.0; g=1.0; b=1.0; break;
    }
}

void ICETools::convertToRGB ( const NICE::Matrix & m, NICE::ColorImage & img )
{
	img.resize ( m.cols(), m.rows() );
    double max = - numeric_limits<double>::max();
    double min = numeric_limits<double>::max();
    for ( size_t x = 0 ; x < (size_t)m.cols(); x++ )
	for ( size_t y = 0 ; y < (size_t)m.rows() ; y++ )
	{
	    if (m(y, x) > max ) max =m(y, x);
	    if (m(y, x) < min ) min =m(y, x);
	}
    
    for ( size_t y = 0 ; y < (size_t)m.rows() ; y++ )
	for ( size_t x = 0 ; x < (size_t)m.cols(); x++ )
	{
	    double val =(m(y, x) - min) / (max-min);
	    double r,g,b;
	    toColor(val, r, g, b);
	    img.setPixel(x,y,0,(int)(r*255));
	    img.setPixel(x,y,1,(int)(g*255));
	    img.setPixel(x,y,2,(int)(b*255));
	}
}

void ICETools::convertToRGB ( const NICE::FloatImage & m, NICE::ColorImage & img )
{
	img.resize ( m.width(), m.height() );
    double max = - numeric_limits<double>::max();
    double min = numeric_limits<double>::max();
    for ( size_t x = 0 ; x < (size_t)m.width(); x++ )
	for ( size_t y = 0 ; y < (size_t)m.height() ; y++ )
	{
	    double v = m.getPixel(x,y);
	    if ( v > max ) max = v;
	    if ( v < min ) min = v;
	}
    
    for ( size_t y = 0 ; y < (size_t)m.height() ; y++ )
	for ( size_t x = 0 ; x < (size_t)m.width(); x++ )
	{
	    double val = (m.getPixel(x,y) - min) / (max-min);
	    double r,g,b;
	    toColor(val, r, g, b);
	    img.setPixel(x,y,0,(int)(r*255));
	    img.setPixel(x,y,1,(int)(g*255));
	    img.setPixel(x,y,2,(int)(b*255));
	}
}

void ICETools::calcGrayImage ( const NICE::ColorImage & img, NICE::Image & imgg )
{
    imgg.resize(img.width(), img.height());
    for ( int y = 0 ; y < img.height(); y++ )
      for ( int x = 0 ; x < img.width() ; x++ )
      {
        unsigned char g = (unsigned char)(0.299*img.getPixel(x,y,0) + 
          0.587*img.getPixel(x,y,1) + 0.114*img.getPixel(x,y,2));
        imgg.setPixel(x,y,g);
      }
}

double *ICETools::convertICE2M ( const NICE::Matrix & M )
{
    double *raw = new double [ M.rows() * M.cols() ];
    long index = 0;
    for ( uint i = 0 ; i < M.rows() ; i++ )
      for ( uint j = 0 ; j < M.cols() ; j++, index++ )
        raw[index] = M(i, j);

    return raw;
}

void ICETools::convertM2ICE ( NICE::Matrix & M, double *raw )
{
    long index = 0;
    for ( int i = 0 ; i < (int)M.rows() ; i++ )
		for ( int j = 0 ; j < (int)M.cols() ; j++, index++ )
	    	M(i, j) = raw[index];
}

#ifndef NOVISUAL
int ICETools::markImage (const NICE::Image & img, NICE::Image & mark, int marksize, int color)
{
    fprintf (stderr, "ICETools::markImage: reimplement this function for NICE\n");
    exit(-1);

/*
    int flags;
    int p[2];
    int xo = -1;
    int yo = -1;
    
    while(1) {
	// refactor-nice.pl: check this substitution
	// old: flags = Mouse(img,p[0],p[1]);
	// REFACTOR-FIXME Unable to map this statement
	if ( (flags & M_LEFT_DOWN) > 0 ) {
	    if ( (p[0] != xo) || (p[1] != yo) ) {
		if ( marksize == 1 ) {
		    // refactor-nice.pl: check this substitution
		    // old: PutVal( mark, p[0], p[1], color );
		    mark.setPixel(p[0],p[1],color);
		} else {
		    // refactor-nice.pl: check this substitution
		    // old: Marker(3, p[0], p[1], color, marksize, mark);
		    // REFACTOR-FIXME Unable to map this statement
		}
       
		xo = p[0];
		yo = p[1];
	    }
	}
	if ( (flags & M_RIGHT_DOWN) > 0 ) {
	    while ( (flags & M_RIGHT_DOWN) > 0 ) {
		// refactor-nice.pl: check this substitution
		// old: flags = Mouse(img,p[0],p[1]);
		// REFACTOR-FIXME Unable to map this statement
	    };
	    return -1;
	}
    }
*/

    return 0;
}

// refactor-nice.pl: check this substitution
// old: int ICETools::showImages ( vector<Image> & imagelist )
int ICETools::showImages ( vector<NICE::Image> & imagelist )
{
#ifndef NOVISUAL
    for ( size_t j = 0 ; j < imagelist.size() ; j++ )
    {
	// refactor-nice.pl: check this substitution
	// old: Show(ON, imagelist[j]);
	showImage(imagelist[j]);
    }
#endif

    // assumption: same size
    // refactor-nice.pl: check this substitution
    // old: int xsize = imagelist[0]->xsize;
    int xsize = imagelist[0].width();
    // refactor-nice.pl: check this substitution
    // old: int ysize = imagelist[0]->ysize;
    int ysize = imagelist[0].height();

    int n = imagelist.size();
    int n1 = (int)sqrt(n);
    int n2 = n/n1 + 1;

    NICE::Image img (n1*xsize, n2*ysize);
    img.set(0);
    int k = 0;
    for ( int j = 0 ; j < n2 ; j++ )
	for ( int i = 0 ; i < n1 ; i++,k++ )
	    if ( k >= n ) break;
	    else {
		for ( int y = 0 ; y < imagelist[k].height(); y++ )
		    for ( int x = 0 ; x < imagelist[k].width(); x++ )
		    {
          img.setPixel( i*xsize + x, j*ysize + y,
              imagelist[k].getPixel(x,y) );
		    }
	    }

    img.write ("display.bmp");

    getchar();

    return 0;
}

#endif