/**
* @file LFReadCache.tcc
* @author Erik Rodner
* @date 02/14/2008

*/
#include "core/vector/VectorT.h"
#include "core/vector/MatrixT.h"
#include "core/image/ImageT.h"

#include <iostream>
#include <fstream>

#include "vislearning/features/localfeatures/LFReadCache.h"

#include "vislearning/baselib/Globals.h"
#include "core/basics/StringTools.h"
#include "core/basics/FileMgt.h"
#include "core/vector/VVector.h"

namespace OBJREC
{

template <class ImageClass>
int LFReadCache::extractFeaturesTemplate ( const ImageClass & img,
    NICE::VVector & features,
    NICE::VVector & positions ) const
{
  std::string filename = Globals::getCacheFilename ( cachedir, cachemode );
  std::string filename_desc = filename + ".desc";
  std::string filename_pos = filename + ".key";

  int ret = 0;

  if ( ! NICE::FileMgt::fileExists ( filename_desc ) ||
       ! NICE::FileMgt::fileExists ( filename_pos ) )
  {
    fprintf ( stderr, "LFReadCache::extractFeatures: recovering data (%s,%s not found)\n", filename_desc.c_str(),
              filename_pos.c_str() );
    if ( lfrep == NULL )
      fthrow ( NICE::Exception, "LocalFeatureRepresentation not available, recovering is impossible!" );

    std::cerr << "extract features with lfrep used in ReadCache" << std::endl;
    lfrep->extractFeatures ( img, features, positions );
    std::cerr << "features extracted" << std::endl;

    features.save ( filename_desc, descFormat );
    positions.save ( filename_pos, NICE::VVector::FILEFORMAT_LINE );
  }
  else
  {
    if ( ( descFormat == NICE::VVector::FILEFORMAT_BINARY_DOUBLE ) || ( descFormat == NICE::VVector::FILEFORMAT_BINARY_CHAR ) )
    {
      if ( lfrep == NULL )
      {
        fthrow ( NICE::Exception, "Raw binary format needs a LocalFeatureRepresentation as prototype" );
      }
      else
      {
        features.setBufSize ( lfrep->getDescSize() );
      }
    }

    features.read ( filename_desc, descFormat );
    positions.read ( filename_pos, NICE::VVector::FILEFORMAT_LINE );

    if ( positions.size() != features.size() )
    {
      std::cerr << "LFReadCache::extractFeatures: format error ! positions.size=" << positions.size() <<
                " features.size()=" << features.size() << std::endl;
      std::cerr << "features: " << filename_desc << std::endl;
      std::cerr << "positions: " << filename_pos << std::endl;
      exit ( -1 );
    }

    if ( ( numFeatures >= 0 ) && ( features.size() > ( size_t ) numFeatures ) )
    {
      size_t n = features.size() - numFeatures; // >= 1
      fprintf ( stderr, "LFReadCache: number of local features is restricted: localfeature_count %d, real %d\n",
                numFeatures, ( int ) features.size() );

      if ( n > ( size_t ) numFeatures )
      {
        NICE::VVector nf;
        NICE::VVector np;
        for ( size_t l = 0 ; l < ( size_t ) numFeatures ; l++ )
        {
          size_t i = rand() % features.size();
          nf.push_back ( features[i] );
          np.push_back ( positions[i] );
          features.erase ( features.begin() + i );
          positions.erase ( positions.begin() + i );
        }
        positions = np;
        features = nf;
      }
      else
      {
        for ( size_t l = 0 ; l < n ; l++ )
        {
          size_t i = rand() % features.size();
          features.erase ( features.begin() + i );
          positions.erase ( positions.begin() + i );
        }
      }
    }
  }


  return ret;
}

}
