#include "Example.h"

#ifdef NICE_USELIB_OPENMP
#include <omp.h>
#endif

using namespace OBJREC;
using namespace std;
using namespace NICE;

Example::Example()
{
	weight = 0.0;
	height = 0;
	width = 0;
	x = 0;
	y = 0;
	vec = NULL;
	svec = NULL;
  ce = NULL;
	position = 0;
}

Example::~Example ()
{
}

Example::Example ( CachedExample *_ce )
{
    _ce->getImageSize ( width, height );

    if ( width % 2 == 0 )
	width--;

    if ( height % 2 == 0 )
	height--;

    x = width/2;
    y = height/2;

    ce = _ce; 
    vec = NULL;
    svec = NULL;
    weight = 1.0;
	position = 0;
}

Example::Example ( CachedExample *_ce, 
						   int _x,
						   int _y,
						   double _weight )
{
    ce = _ce;
    x  = _x;
    y  = _y;
    width = 0;
    height = 0;
    vec = NULL;
    svec = NULL;
    weight = _weight;
	position = 0;
}

Example::Example ( CachedExample *_ce, 
						   int _x,
						   int _y,
						   int _width,
						   int _height,
						   double _weight )
{
    ce = _ce;
    x  = _x;
    y  = _y;
    width = _width;
    height = _height;
    assert ( (width > 0) && (height > 0) );

    vec = NULL;
    svec = NULL;
    weight = _weight;
	position = 0;
}

Example::Example ( NICE::Vector *_vec, 
						   double _weight )
{
    x = y = 0;
    width = height = 0;
    ce = NULL;
    vec = _vec;
    svec = NULL;
    weight = _weight;
	position = 0;
}

void Example::clean ()
{
	if ( ce != NULL )
	{
		delete ce;
		ce =  NULL;
	}

	if ( vec != NULL )
	{
		delete vec;
		vec = NULL;
	}
    
	if ( svec != NULL )
	{
		delete svec;
		svec = NULL;
	}
}


Example::Example ( const Example &ex)
{
	copy(ex);
}

void Example::copy ( const Example &ex)
{
	vec = ex.vec;
	svec = ex.svec;
	weight = ex.weight;
	position = ex.position;
	width = ex.width;
	height = ex.height;
	x = ex.x;
	y = ex.y;
	ce = ex.ce;
	scale = ex.scale;
}

void Example::restore (istream & is, int format)
{
	is >> weight;
	is >> x;
	is >> y;
	is >> width;
	is >> height;
	is >> position;
	int tmp;
	is >> tmp;

	if(tmp == 1)
	{
		svec = new SparseVector();
		svec->restore(is);
	}
	else
		svec = NULL;
	is >> tmp;
	if(tmp >= 0 )
	{
		vec = new Vector(tmp);
		for(int i = 0; i < tmp; i++)
		{
			is >> vec[i];
		}
	}
	else
		vec = NULL;
}

void Example::store (ostream & os, int format) const
{
	os << weight << " " <<  x << " " << y << " " << width << " " << height << " " << position << endl;
	if(svec == NULL)
		os << 0 << endl;
	else
	{
		os << 1 << endl;
		svec->store(os);
	}
	
	if(vec == NULL)
		os << -1 << endl;
	else
	{
		os << vec->size() << endl;
		for(int i = 0; i < (int)vec->size(); i++)
		{
			os << vec[i] << " ";
		}
	}
}

void Examples::clean ()
{
	for ( iterator i = begin(); i != end(); i++ )
	{
		Example & example = i->second;
		example.clean();
	}
    clear();
}

bool Examples::wrapExamplesAroundFeatureMatrix(const Matrix &p_MatFeaturesColumWiseSamples, const Vector &p_VecLabels, Examples &p_Examples)
{
    size_t t_iNumSamples  = p_MatFeaturesColumWiseSamples.cols();
    size_t t_iNumFeatures = p_MatFeaturesColumWiseSamples.rows();

    if(p_VecLabels.size() != t_iNumSamples) // for every columnwise sample there need to be a label
        return false;

    p_Examples.reserve( t_iNumSamples );

    const double *pDataPtr = p_MatFeaturesColumWiseSamples.getDataPointer();
    for (size_t i = 0; i < t_iNumSamples; i++, pDataPtr+= t_iNumFeatures )
    {
        NICE::Vector *t_pVecTrainData = new NICE::Vector( pDataPtr , t_iNumFeatures);
        double t_fWeight = 1.0f;
        OBJREC::Example t_Example(t_pVecTrainData, t_fWeight);

        p_Examples.push_back( std::pair<int, OBJREC::Example>( (int)p_VecLabels[i], t_Example ) );
    }

    return true;
}

bool Examples::wrapExamplesAroundFeatureMatrix(const Matrix &p_MatFeaturesColumWiseSamples, const VectorT<int> &p_VecLabels, Examples &p_Examples)
{
    size_t t_iNumSamples  = p_MatFeaturesColumWiseSamples.cols();
    size_t t_iNumFeatures = p_MatFeaturesColumWiseSamples.rows();

    if(p_VecLabels.size() != t_iNumSamples) // for every columnwise sample there need to be a label
        return false;
    p_Examples.resize( t_iNumSamples );
    const double *pDataPtr = p_MatFeaturesColumWiseSamples.getDataPointer();
    
#ifdef NICE_USELIB_OPENMP
#pragma omp parallel for default(none) shared(p_VecLabels, p_Examples, t_iNumFeatures, t_iNumSamples, pDataPtr)
#endif
    for (size_t i = 0; i < t_iNumSamples; i++)
    {
	const double *pDataIteration = pDataPtr + (i * t_iNumFeatures);
        NICE::Vector *t_pVecTrainData = new NICE::Vector( (double*) pDataIteration , t_iNumFeatures, VectorBase::external);
        // OBJREC::Example t_Example(t_pVecTrainData, t_fWeight);

	p_Examples[i] = std::pair<int, OBJREC::Example>( p_VecLabels[i], OBJREC::Example(t_pVecTrainData, 1.0) ) ;
    }

    return true;
}
