#include <iostream>
#include <assert.h>

#include "LocalFeatureLFInterface.h"

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

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

LocalFeatureLFInterface::LocalFeatureLFInterface() : LocalFeature () 
{
  this->lfpres = NULL;
}

LocalFeatureLFInterface::LocalFeatureLFInterface( const NICE::Config * _conf, LocalFeatureRepresentation *_lfpres )
{
  this->initFromConfig( _conf );

  //TODO check for null pointers? where will deletion be performed? what about restoring those objects?  
  this->lfpres = _lfpres;
}

LocalFeatureLFInterface::~LocalFeatureLFInterface()
{
  if ( this->lfpres != NULL )
    delete lfpres;
  this->lfpres = NULL;
}

void LocalFeatureLFInterface::initFromConfig( const NICE::Config* _conf, const std::string& _confSection )
{
  //nothing to do here
  //NOTE how to handle lfrep object? - separate set method?
}

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


int LocalFeatureLFInterface::getDescriptors ( const NICE::Image & img, VVector & positions, VVector & descriptors ) const
{
  //TODO do we want to ignore the positions of lfrep and use the given ones, or do we indeed want to compute positions on our own? If so, why do we use the Interface to LocalFeature, and not directly LocalFeatureRepresentation?    
  lfpres->extractFeatures(img, descriptors, positions);
  assert(descriptors.size() == positions.size());
  return 0;
}

int LocalFeatureLFInterface::getDescriptors ( const NICE::ColorImage & img, VVector & positions, VVector & descriptors) const
{
  //TODO do we want to ignore the positions of lfrep and use the given ones, or do we indeed want to compute positions on our own? If so, why do we use the Interface to LocalFeature, and not directly LocalFeatureRepresentation?
  lfpres->extractFeatures(img, descriptors, positions);
  assert(descriptors.size() == positions.size());
  return 0;
}

void LocalFeatureLFInterface::visualizeFeatures ( NICE::Image & mark,
        const VVector & positions,
        size_t color ) const
{
  //cerr << "LocalFeatureLFInterface::visualizeFeatures(...) not yet implemented" << endl;
  lfpres->visualizeFeatures(mark, positions, color);
}

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

void LocalFeatureLFInterface::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, "LocalFeatureLFInterface" ) )
    {
      std::cerr << " WARNING - attempt to restore LocalFeatureLFInterface, 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, "LocalFeatureLFInterface" ) )
      {
        b_endOfBlock = true;
        continue;
      }      
      
      tmp = this->removeStartTag ( tmp );    
      
      ///////////////////////////////
      //       PARENT OBJECT       //
      ///////////////////////////////
      if ( tmp.compare("lfpres") == 0 )
      {
        // restore parent object
        //TODO this->lfpres->restore ( is );
      }      
      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 LocalFeatureLFInterface::store ( std::ostream & os, int format ) const
{ 
  if (os.good())
  {
    // show starting point
    os << this->createStartTag( "LocalFeatureLFInterface" ) << std::endl;    
        
    ///////////////////////////////
    //       PARENT OBJECT       //
    ///////////////////////////////
    os << this->createStartTag( "lfpres" ) << std::endl;
    //TODO this->lfpres->store(os);  
    os << this->createStartTag( "lfpres" ) << std::endl;   
    
    // done
    os << this->createEndTag( "LocalFeatureLFInterface" ) << std::endl;    
  }
  else
  {
    std::cerr << "OutStream not initialized - storing not possible!" << std::endl;
  }
}

void LocalFeatureLFInterface::clear ()
{
  if ( this->lfpres != NULL )
    delete lfpres;
  this->lfpres = NULL;  
}