/** 
* @file VCAmitSVM.cpp
* @brief interface to the svm generalization of Amit et al. 2007
* @author Erik Rodner
* @date 11/28/2007

*/

#include <iostream>
#include <fstream>

#include "vislearning/classifier/vclassifier/VCAmitSVM.h"
#include "core/basics/FileMgt.h"

using namespace OBJREC;

using namespace std;
// refactor-nice.pl: check this substitution
// old: using namespace ice;
using namespace NICE;

VCAmitSVM::VCAmitSVM( const Config *conf ) : VCLearnFromSC( conf )
{
    amitDir = conf->gS( "amit", "amit_dir", "/home/rodner/osl/labor/cvs/vislearning/vclassifier/amitMatlab/");
    matlabExec = conf->gS("matlab", "matlab_exec", "/home/rodner/script/matlab");
    matlabArgs = conf->gS("matlab", "matlab_args", "-nosplash -nojvm -nodesktop");
    C = conf->gD ("amit", "C", 1.0);
    gamma = conf->gD ("amit", "gamma", 1.0);
}

VCAmitSVM::~VCAmitSVM()
{
}

/** classify using simple vector */
// refactor-nice.pl: check this substitution
// old: ClassificationResult VCAmitSVM::classify ( const ice::Vector & x ) const
ClassificationResult VCAmitSVM::classify ( const NICE::Vector & x ) const
{
    // refactor-nice.pl: check this substitution
    // old: Vector voting = W*x;
    NICE::Vector voting;
    voting.multiply(W, x);
    double maxVoting = - std::numeric_limits<double>::max();
    int classno = 0;

    for ( size_t i = 0 ; i < voting.size() ; i++ )
    {
	fprintf (stderr, "class %d, voting %f\n", (int)i, voting[i] );
	if ( voting[i] > maxVoting )
	{
	    classno = i;
	    maxVoting = voting[i];
	}
    }

    return ClassificationResult ( classno, maxVoting, maxClassNo );
}

void VCAmitSVM::preTeach ( const LabeledSetVector & teachSet )
{
    fprintf (stderr, "VCAmitSVM::preTeach: WARNING not yet implemented!\n");
}

void VCAmitSVM::teach ( const LabeledSetVector & teachSet )
{
    maxClassNo = teachSet.getMaxClassno();

    // refactor-nice.pl: check this substitution
    // old: string vecFN = FileMgt::createTempFile ("/tmp/amitvec_%s.tmp");
    std::string vecFN = FileMgt::createTempFile ("/tmp/amitvec_%s.tmp");
    ofstream ofs ( vecFN.c_str(), ios::out );   
    teachSet.store(ofs);   
    ofs.close();

    // refactor-nice.pl: check this substitution
    // old: string execCMD = matlabExec + " " + matlabArgs;
    std::string execCMD = matlabExec + " " + matlabArgs;
    // refactor-nice.pl: check this substitution
    // old: string chdirCMD = "cd '" + amitDir + "'\n";
    std::string chdirCMD = "cd '" + amitDir + "'\n";

    // ----------- routine argument -------------
    // refactor-nice.pl: check this substitution
    // old: string matFN = FileMgt::createTempFile ("/tmp/amitmat_%s.tmp");
    std::string matFN = FileMgt::createTempFile ("/tmp/amitmat_%s.tmp");
    // refactor-nice.pl: check this substitution
    // old: ostringstream ss;
    std::ostringstream ss;
    ss << "W = trainAmit('" << vecFN << "', '" << matFN << "'," << C << "," << gamma << ");" << endl;
    // refactor-nice.pl: check this substitution
    // old: string routineCMD = ss.str();
    std::string routineCMD = ss.str();


    // ----------- executing matlab -------------

    FILE *f = popen ( execCMD.c_str(), "w");
    if ( f == NULL )
    {
	fprintf (stderr, "VCAmitSVM::teach: FATAL ERROR cannot write labeled set!\n");
	exit(-1);
    }
    fputs (chdirCMD.c_str(), f);
    fputs (routineCMD.c_str(), f);
    pclose(f);

    
    // ----------- reading result ---------------

    FILE *g = fopen ( matFN.c_str(), "r" );
    if ( g == NULL )
    {
	fprintf (stderr, "VCAmitSVM::teach: FATAL ERROR can not read W matrix!\n");
	exit(-1);
    }
    int n = teachSet.numClasses();
    int d = teachSet.dimension();
    W = Matrix(n, d);

    for ( int j = 0 ; j < d ; j++ )
    {
	for ( int i = 0 ; i < n ; i++ )
	{
	    double val;
	    if ( fread ( &val, sizeof(double), 1, g) <= 0 )
	    {
		fprintf (stderr, "VCAmitSVM::teach: FATAL ERROR reading matrix file\n");
		exit(-1);
	    }
	    // refactor-nice.pl: check this substitution
	    // old: W[i][j] = val;
	    W(i, j) = val;
	}
    }

    fclose(g);

    FileMgt::deleteTempFile ( matFN );
    FileMgt::deleteTempFile ( vecFN );

    // refactor-nice.pl: check this substitution
    // old: fprintf (stderr, "VCAmitSVM::teach Matrix successfully loaded !!\n");
    fprintf (stderr, "VCAmitSVM::teach NICE::Matrix successfully loaded !!\n");
}

void VCAmitSVM::restore ( std::istream & is, int format )
{
    fprintf (stderr, "NOT YET IMPLEMENTED !!\n");
    exit(-1);
}

void VCAmitSVM::store ( std::ostream & is, int format ) const
{
    fprintf (stderr, "NOT YET IMPLEMENTED !!\n");
    exit(-1);
}

void VCAmitSVM::clear ()
{
    fprintf (stderr, "NOT YET IMPLEMENTED !!\n");
    exit(-1);
}