#include <iostream>

#include "vislearning/features/localfeatures/sift.h"
#include "vislearning/features/localfeatures/LocalFeatureOpponnentSift.h"

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

///////////////////// ///////////////////// /////////////////////
//                   CONSTRUCTORS / DESTRUCTORS
///////////////////// ///////////////////// /////////////////////

LocalFeatureOpponnentSift::LocalFeatureOpponnentSift() : LocalFeatureRGBSift () 
{
}

LocalFeatureOpponnentSift::LocalFeatureOpponnentSift ( const NICE::Config * _conf )
{
  this->initFromConfig( _conf );  
}

LocalFeatureOpponnentSift::~LocalFeatureOpponnentSift()
{
}

void LocalFeatureOpponnentSift::initFromConfig( const NICE::Config* _conf, const std::string& _confSection )
{
  //first of all, call method of parent object
  LocalFeatureRGBSift::initFromConfig( _conf );
}

///////////////////// ///////////////////// /////////////////////
//                      FEATURE STUFF
///////////////////// ///////////////////// ////////////////// 

int LocalFeatureOpponnentSift::getDescriptors ( const NICE::ColorImage & cimg,
    VVector & positions,
    VVector & descriptors ) const
{
  NICE::ColorImage opimg ( cimg.width(), cimg.height() );

  for ( int y = 0; y < ( int ) cimg.height(); y++ )
  {
    for ( int x = 0; x < ( int ) cimg.width(); x++ )
    {
      // Farbkanaele auslesen
      int r = cimg.getPixel ( x, y, 0 );
      int g = cimg.getPixel ( x, y, 1 );
      int b = cimg.getPixel ( x, y, 2 );

      // Transformation in den Opponent Farbraum nach Van de Sande
      int o1 = ( int ) ( ( ( double ) ( r - g ) + 255.0 ) / 2.0 );
      int o2 = ( int ) ( ( ( double ) ( r + g - b ) + 510.0 ) / 4.0 );
      int o3 = ( int ) ( ( double ) ( r + g + b ) / 3.0 );

      opimg.setPixel ( x, y, o1, o2, o3 );
    }
  }

  return LocalFeatureRGBSift::getDescriptors ( opimg, positions, descriptors );
}

///////////////////// INTERFACE PERSISTENT /////////////////////
// interface specific methods for store and restore
///////////////////// INTERFACE PERSISTENT ///////////////////// 

void LocalFeatureOpponnentSift::restore ( std::istream & is, int format )
{
  //delete everything we knew so far...
  this->clear();
  
  
  if ( is.good() )
  {
    
    std::string tmp;
    is >> tmp; //class name 
    
    if ( ! this->isStartTag( tmp, "LocalFeatureOpponnentSift" ) )
    {
      std::cerr << " WARNING - attempt to restore LocalFeatureOpponnentSift, but start flag " << tmp << " does not match! Aborting... " << std::endl;
      throw;
    }   
    
    bool b_endOfBlock ( false ) ;
    
    while ( !b_endOfBlock )
    {
      is >> tmp; // start of block 
      
      if ( this->isEndTag( tmp, "LocalFeatureOpponnentSift" ) )
      {
        b_endOfBlock = true;
        continue;
      }      
      
      tmp = this->removeStartTag ( tmp );    
      
      ///////////////////////////////
      //       PARENT OBJECT       //
      ///////////////////////////////
      if ( tmp.compare("LocalFeatureRGBSift--Parent") == 0 )
      {
        // restore parent object
        LocalFeatureRGBSift::restore(is);
        is >> tmp; // end of block 
        tmp = this->removeEndTag ( tmp );        
      }      
      else
      {
      std::cerr << "WARNING -- unexpected LocalFeatureOpponnentSift object -- " << tmp << " -- for restoration... aborting" << std::endl;
      throw;
      }
    }
  }
  else
  {
    std::cerr << "LocalFeatureOpponnentSift::restore -- InStream not initialized - restoring not possible!" << std::endl;
    throw;
  }
}

void LocalFeatureOpponnentSift::store ( std::ostream & os, int format ) const
{ 
  if (os.good())
  {
    // show starting point
    os << this->createStartTag( "LocalFeatureOpponnentSift" ) << std::endl;    
        
    ///////////////////////////////
    //       PARENT OBJECT       //
    ///////////////////////////////
    os << this->createStartTag( "LocalFeatureRGBSift--Parent" ) << std::endl;
    LocalFeatureRGBSift::store(os);  
    os << this->createStartTag( "LocalFeatureRGBSift--Parent" ) << std::endl;   
    
    // done
    os << this->createEndTag( "LocalFeatureOpponnentSift" ) << std::endl;    
  }
  else
  {
    std::cerr << "OutStream not initialized - storing not possible!" << std::endl;
  }
}

void LocalFeatureOpponnentSift::clear ()
{
}