#ifndef __GLCP__
#define __GLCP__

#include <map>
#include <vector>
#include <iostream>
#include <set>
#include "image2d.h"
#include "databuffer.h"
#include "matrix.h"

#define GLCPGRAY 32.0

/// calculates the GLCP texture feature
/**
 * currently the angles is set at intervals of 22.5 degrees
 * delta increments at the rate of 2 pixels up to half the window size
 *
 * <delta, theta> pair is used as the key for the matrix and statisticial values
 * theta value is written in tenths of a degree 
 */
class GLCP
{
 public:
  
  /// mask to ignore certian stuff
  /**
   * values can be either 0 or 1 to taggle the respective features
   */
  struct mask
  {
    int entropy;
    int contrast;
    int correlation;
    int power;
    int mean;
  };

  GLCP();
  ~GLCP();

  /// calculate the feature vector
  /**
   * @param im pointer to image pixels range [0, 1]
   * @param cx center x
   * @param cy center y
   * @param w window size
   */
  int init( image2d *im, int cx, int cy, int w );

  int getfeaturevector( std::vector< double > &fv );
  int getfeaturevector( double* f );

  /// obtain the feature vector as a time series
  /**
   * time is represented as the change in theta
   * each time step would have the statistical descriptors for
   * all deltas written down.  
   *
   * new memory is allocated for each time step
   *
   * @param f vector will contain the time series data
   * @param sz the size of the feature vector for each time step
   */
  int getfeaturets( std::vector< double* > &f, int &sz );

  /// obtain time series with the posibility to now include some descriptors
  /**
   * all parameters are the same as the standard function except the mask 
   * will define which feature vector will be used
   */
  int getfeaturets( std::vector< double* > &f, mask &fm, int &sz );

  /// obtain time series with the posibility to now include some descriptors
  /**
   * all parameters are the same as the standard function except the mask 
   * will define which feature vector will be used
   */
  int getfeaturets( std::vector< matrix > &f, mask &fm, int &sz );

  /// obtain time series with each time step averaged
  /**
   * @param f vector containing final time series
   * @param sz size of vector at each time step
   * @param fm mask of which parameter to include
   * for each theta the parameters are averaged over the different deltas
   */ 
  int getfeaturetsavg( std::vector< double* > &f, mask &fm, int &sz );

  int size();

  int del();
  int print();

  int distance( GLCP &o );
  int checkequal( GLCP &o );

  int serialize( databuffer &buf );
  int deserialize( char *buf, int sz );

  int meanthetadelta( mask &fm, std::vector<double> &res );
  int varthetadelta( mask &fm, std::vector<double> &res );

 private:

  int addtoglcp( double v1, double v2, double *cf );
  int calccomatrix( image2d *im,  double delta, 
                    double theta, double *cf );

  int calcentropy();
  double calcentropy( double *p );
  int calccontrast();
  double calccontrast( double *p );
  int calccorrelation();
  double calccorrelation( double *p );
  int calcpower();
  double calcpower( double *p );
  int calcmean();

  image2d *myim;

  int centerx, centery;
  int window;            ///< window width

  int lowx, lowy, highx, highy;

  std::set< int > deltas;
  std::set< int > angles;

  /// co-occurrence matrix
  std::map< std::pair< int, int >, double* >
    coocmatrix;
  std::map< std::pair< int, int >, double>
    entropy;
  std::map< std::pair< int, int >, double>
    contrast;
  std::map< std::pair< int, int >, double>
    correlation;
  std::map< std::pair< int, int >, double>
    power;
  double mean;
};

#endif
