

#ifndef Markov_h
#define Markov_h

#include "som.h"

class Markov
{
public:
        Markov();                                  //load Markov net, if empty, default norm=0
		Markov(const wchar_t *fname);                                              //load SOM net, if empty, default norm=0
        ~Markov();

        enum TrainMode {SLOW, FAST};


// Operators
        //const Markov& operator=(const Markov& som);

// Operations
        //training
        float **transitionMat;  
		float **directionMat;
		float *firstStateMat;
		float *firstAngleMat;
		float *som_dist_map;

		int * int_data_carrier;
		
		
        
		void train(const vector<float *> *vectors, 
                   float R, float learning_rule);       //not used

		int getTransitionVector(SOM *som, PREC rec);//pre-process of transition vector for testing
		int getTransitionVector(SOM *som, PREC rec, int irep);//pre-process of transition vector 
		void getVectorTransitionMatrixPerClass(SOM *som, PREC rec, int reps);//process of transition vector 
		int getTransitionAngle(PREC rec); //pre-process of transition angles vector for testing
		int getTransitionAngle(PREC rec, int irep); //pre-process of transition angles vector
		void getAngleTransitionMatrixPerClass(PREC rec, int reps);//process of transition angles vector
		void print2DMarkovMatrix(float **mat, int matsize);//display 2D Markov Matrix (of equal size AxA)
		float get_angle(const float *vec1, const float *vec2); //angle between 2 vectors (2D) in degrees
		int get_angle_index(float angle);
		float *get_angle3d(const float *vec1, const float *vec2);
		int get_angle_index(float *angle);
		float get_angle_distance(int node, int x_node);
		inline int get_classnum(void) const; 
		inline int get_somsize(void) const;

		float getTransProb(SOM *som, PREC rec, int *bmuArray, int transitions, int classid, int somsize);
		float getAngleProb(PREC rec, int *angleArray, int transitions, int classid);
		float getLevenshteinProb(int *bmuArray, int transitions, int classid);

        void evaluate(SOM *som, PREC rec, const wchar_t *som_map_name);
		//int readMat(FILE *fp);
		float* readMat(FILE *fp);
		int readGMedian(FILE *fp);
		float readMeanDist(FILE *fp);
		int saveMarkov(const wchar_t *fname, int classnum, int somsize ) const;
		int saveMat(const wchar_t *fname, float **matrix, int matsize) const;
		int saveVec(const wchar_t *fname, float *fvector, int m_size) const;

		int getGeneralMedian(wchar_t *s1, int size_s1, wchar_t *s2, int size_s2);
		int getSumOfDistance(SOM *som, PREC rec, int *test_mat, int size1, int ** temp_mat, int rows);
		int vec2str(int * vec, int matsize);
		int getLevenshteinDistance(wchar_t *s1, int size_s1, wchar_t *s2, int size_s2);
                                            

private:
        Markov(const Markov& markov);
        const Markov& operator=(const Markov& markov); 
		
		static const int dirsize = 8;
		int *angleClassIndexArray;
		int *bmuClassIndexArray;		
		int classnum;
		int som_size;
		float ML;
		wchar_t lev_string[_MAX_PATH];
		//wchar_t gmedian_string[_MAX_PATH];
};

inline int Markov::get_classnum(void) const
{
	return classnum;
}   
inline int Markov::get_somsize(void) const
{
	return som_size;
} 


#endif