/** 
* @file computeNormalizedHistogramFeatures.cpp
* @brief simply compute randomly generated, normalized histogram features
* @author Alexander Freytag
* @date 07-05-2012 (dd-mm-yyyy)
*/

#include <vector>
#include <iostream>
#include <cstdlib>
#include <ctime>

#include <core/basics/Config.h>
#include <core/vector/MatrixT.h>
#include <core/vector/VectorT.h>
#include <core/vector/Algorithms.h>
#include <core/vector/MatrixT.h>

using namespace std;
using namespace NICE;


int main (int argc, char* argv[])
{

  Config conf ( argc, argv );

  int n = conf.gI("main", "nrOfExamplesPerClass", 10);
  int d = conf.gI("main", "nrOfDimensions", 20);
  int m = conf.gI("main", "nrOfClasses", 2);
  string destination = conf.gS( "main", "destination", "/tmp/features.data");
  bool saveLastDimension = conf.gB( "main", "saveLastDimension", false);
  
  if (d < m)
  {
    std::cerr << "Sry, you specified less dimensions than number of classes" << std::endl;
    return -1;
  }
  if (d <= 1 )
  {
    std::cerr << "Sry, you have to specify at least two dimensions" << std::endl;
    return -1;
  }
  
  NICE::Vector y (n*m);
  NICE::Vector yBin (n*m);
  NICE::Matrix data;
  
  if (saveLastDimension)
  {
    data.resize( n*m, d-1 );
  }
  else
  {
    data.resize( n*m, d-1 );
  }
  data.set( 0.0 );

  int classCount(0);
  for (int i = 0; i < n*m; i++)
  {
    double meanPrimary ( std::min(0.25, 1.0/(d-1) ) );
    double meanSecondary ( 0.75 / (2.0*d) );
    double stdDev( 0.75 / (3.0*d) );
       
    double sum(0.0);
    double sampleValue(0.0);
    
    for (int dim = 0; dim < d-1; dim++)
    {

      do 
      { 
        sampleValue = fabs( randGaussDouble ( stdDev ) );
        
        if (dim == classCount)
          sampleValue += meanPrimary;
        else
          sampleValue += meanSecondary;
      } while ( ( sum + sampleValue ) >= 1.0) ; //pay attention that the normalization works properly
      sum += sampleValue;      
      data(i, dim) = sampleValue;
    }
    
    //normalization
    if ( saveLastDimension )
    {
      data( i, d-1 ) = 1.0 - sum;
      std::cerr << "i: " << i << " d-1: " << d-1 << " sum: " << sum << " 1.0 - sum: " << 1.0-sum << std::endl;
    }
    
    //save the corresponding label
    y[i] = classCount;
    if (classCount < m/2.0)
      yBin[i] = 0;
    else
      yBin[i] = 1;

    if ( (i % n ) == (n-1))
    {
      classCount++;
    }
  }
  
  
  std::filebuf fb;
  fb.open (destination.c_str(),ios::out);
  std::ostream os(&fb);
//
  os << data << std::endl;  
  os << yBin << std::endl;
  os << y;
// 
  fb.close();  
  
  return 0;
}