#ifdef NICE_USELIB_OPENMP
#include <omp.h>
#endif

#include <iostream>

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

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


LocalFeatureRGBSift::LocalFeatureRGBSift ( const Config *conf ) : LocalFeatureSift ( conf )
{
  deletemode = false;
}

LocalFeatureRGBSift::~LocalFeatureRGBSift()
{

}

int
LocalFeatureRGBSift::getDescriptors ( const NICE::ColorImage & img, VVector & positions, VVector & descriptors ) const
{
  sortPositions ( positions );
  descriptors.clear();
  for ( int i = 0; i < ( int ) positions.size(); i++ )
  {
    NICE::Vector v;
    descriptors.push_back ( v );
  }

  vector<VVector> desc ( 3 );

#ifdef NICE_USELIB_OPENMP
  // check whether siftGPU should be used
  int numberOfCPU = omp_get_num_procs();
  int numberOfThreads = 0;
  if ( isGpuUsed() )
  {
    // in case of siftGPU it is possible to use one device
    numberOfThreads = 1;
    clog << "[log] LocalFeatureRGBSift: no multithreading" << endl;
  }
  else
  {
    // in case of siftpp it is possible to use all given cores
    numberOfThreads = numberOfCPU;
    clog << "[log] LocalFeatureRGBSift: multithreading with (max) " << numberOfCPU << " threads" << endl;
  }
#endif

#pragma omp parallel for num_threads(numberOfThreads)
  for ( int i = 0; i < 3; i++ ) {
    NICE::Image tmp ( img.width(), img.height() );

    for ( int y = 0; y < img.height(); y++ ) {
      for ( int x = 0; x < img.width(); x++ ) {
        tmp.setPixel ( x, y, img.getPixel ( x, y, i ) );
      }
    }
    VVector pos = positions;
    computeDesc ( tmp, pos, desc[i] );
  }

  for ( int i = 0; i < 3; i++ ) {
    assert ( desc[i].size() == descriptors.size() );

    if ( i == 0 ) {
#pragma omp parallel for num_threads( numberOfCPU )
      for ( int j = 0; j < ( int ) desc[i].size(); j++ ) {
        descriptors[j] = desc[i][j];
      }
    }
    else {
#pragma omp parallel for num_threads( numberOfCPU )
      for ( int j = 0; j < ( int ) desc[i].size(); j++ ) {
        descriptors[j].append ( desc[i][j] );
      }
    }
  }

  return positions.size();
}
