#ifndef PROJ_HELPER_CVH_H
#define PROJ_HELPER_CVH_H

#include <cxtypes.h>
#include <cxcore.h>
#include <string>
#include <iostream>
#include <cv.h>
#include <highgui.h>
#include <Vector2D.h>
#include <Vector3D.h>
#include <Polygon2D.h>
#include "Helper\Common.h"
//#include <cstddef>

//#include "Vector3D.h"
//#include "Vector2D.h"

/** Zero member index. */
#define ZERO_INDEX 0
/** First member index.*/
#define FIRST_INDEX 1
/** Second member index.*/
#define SECOND_INDEX 2
/** 2D vector length.*/
#define TWOD_VECTOR_LENGHT 2
/** 3D vector length.*/
#define THREED_VECTOR_LENGHT 3

#define TWO_DIM 2
#define TWO_DIM_HOMOGENOUS 3
#define GRAY_MAX 255
#define CV_FLIP_BOTH_AXIS -1

namespace CALIB
{
	/**
	*	@author Jiří Zahrádka
	*  
	* Helper class utilizing openCV functions.
	*/
	class Cvh
	{
		public: 
			/**
			 * Prints matrix to standard output.	
			 * @param CvMat * mat Matrix to print out.
			 * @param std::string name Matrix name to assign in output.
			 */
			static void PrintCvMatrix(CvMat * mat,std::string name); 
			static IplImage * convertRGBtoGray(IplImage * src);
			/**
			 * Adds column to matrix. Enlarges matrix.
			 * @param mat1 Source matrix.
			 * @param mat2 Column matrix, which is added to mat1.
			 * @return Resul matrix with added column.
			 */
			static CvMat * MatrixAddCols(CvMat * mat1,CvMat *mat2);
			/**
			 * Adds row to matrix. Enlarges matrix.
			 * @param mat1 Source matrix.
			 * @param mat2 Row matrix, which is added to mat1.
			 * @return Resul matrix with added row.
			 */
			static CvMat * MatrixAddRows(CvMat * mat1,CvMat *mat2);
			/**
			 * Matrix multiplycation.
			 * @param mat1 Src 1 mat.
			 * @param mat2 Src 2 mat.
			 * @return Result matrix.
			 */
			static CvMat * MatMul(CvMat * mat1,CvMat * mat2);
			/**
			 * Loads image from file into opencv image.
			 * @param filename Image file filename.
			 * @return OpenCV image structure.
			 */
			static IplImage * LoadImage(const char * filename);						
			/**
			 * Merges source matrixes into dst matrix.
			 * @param src1 First source matrix.
			 * @param src2 Second source matrix.
			 * @param dst Destination matrix.
			 */
			static void MergeMatrixes(CvMat * src1,CvMat * src2,CvMat * dst);			
			/**
			 * Converts matrix into vector of 2D points.
			 * @param mat Src matrix.
			 * @return Points vector.
			*/
			static std::vector<geometry::Vector2Df> * ConvertMatToVector2D(CvMat *mat);
			/**
			 * Converts cv matrix intp vector of 2D points.
			 * @param mat Src matrix.
			 * @param points Dst vector of 2D points.
			 */
			static void ConvertMatToVector2D(CvMat *mat,std::vector<geometry::Vector2Df> * dstPoints2D);
			/**
			 * Converts vector of 3D points into matrix.
			 * @param points Src vector of 3D points.
			 * @return Matrix created from vector.
			 */
			static CvMat * ConvertVector3DToMat(std::vector<geometry::Vector3Dd> points);
			/**
			 * Converts matrix into vector of 3D points.
			 * @param mat Src matrix.
			 * @return Vector created from matrix.
			 */
			static std::vector<geometry::Vector3Dd> * ConvertMatToVector3D(CvMat *mat);
			/**
			 * Converts vector of 2D points into matrix.
			 * @param points Src vector of 2D points.
			 * @return Matrix created form vector.
			 */
			static CvMat * ConvertVector2DToMat(std::vector<geometry::Vector2Df> points);	
			static void ConvertPoints2DToMat(CvPoint2D32f* points,int numPoints,CvMat * dst);
			static CvMat * CreateMat2D(int size);
			static CvMat * CreateMat(int rows,int cols,CvScalar value = cvRealScalar(1));
			static CvMat * GetChackerboardInnerCorners(int x, int y, int size,int rows,int cols);
			static CvMat * GetChackerboardCorners(int x, int y, int size,int rows,int cols);
			static void TransformPoints(CvMat * src,CvMat * dst,CvMat * homography);
			static CvMat * ConvertMat3To4(CvMat * src,bool addDiagonalValue = true);
			static void CopyMatrix(CvMat * src,CvMat * dst);
			static void CalculateHomography(CvMat* srcPlanePoints, CvMat* dstPlanePoints,CvMat * homography);
			static IplImage * CreateIplimage(int width,int height,unsigned char * imageData = NULL,int channels = 4,int depth = IPL_DEPTH_8U,bool flipY = false);
			static IplImage * DivImages(IplImage * dividendImage,IplImage * aliquotImage);
			static void AddGrayToAlphaChannel(IplImage * grayImage,IplImage * dstImage);
		private: 
			/**
			* Constructor.
			*/
			Cvh(); 
			/**
			* Destructor.
			*/
			~Cvh(); 			
	};
}

#endif // PROJ_OPENCV_HELPER_H
