#ifndef _COMPUTER_VISION_
#define _COMPUTER_VISION_

#include "ofMain.h"
#include "ofAddon.h"

class computerVision{

	public:
		computerVision(){
			//something here	
		}
		
		void init(int w, int h){
			
			W = w;
			H = h;
			
			fPixels = new float[W*H]; //for the background learning					
			mPixels = new float[W*H]; //for the motion history image					

			GRAB.initGrabber(W, H);
			GRAB.setVerbose(true);
			VID.loadMovie("movies/cvTest.mov");

			//our openCV inits
			CameraFrame.allocate(W, H);
			Background.allocate(W, H);
			CurrentFrame.allocate(W, H);
			WarpedFrame.allocate(W, H);
			TempFrame.allocate(W, H);
			MotionHistory.allocate(W, H);
			Subtraction.allocate(W, H);
			
			//our texture for the mhi
			TEX.allocate(W, H, GL_LUMINANCE);

			//CAMERA QUAD SETTINGS;
			//SET DEFAULT VALUES HERE
			//0.0-1.0 range
			warpSrc[0].x = 0;
			warpSrc[0].y = 0;
			
			warpSrc[1].x = 0.9;
			warpSrc[1].y = 0;
			
			warpSrc[2].x = 0.9;
			warpSrc[2].y = 0.9;

			warpSrc[3].x = 0;
			warpSrc[3].y = 0.9;
			
			//Now we update out quad with the default
			//values and if then if the file is found
			//we overwrite with values from xml file
			QUAD.setQuadPoints(warpSrc);
			QUAD.readFromFile("quad.xml");
			
			warpDst[0].x = 0;
			warpDst[0].y = 0;
			
			warpDst[1].x = 320;
			warpDst[1].y = 0;
			
			warpDst[2].x = 320;
			warpDst[2].y = 240;

			warpDst[3].x = 0;
			warpDst[3].y = 240;	
		
		}		
		
		void grabBackground(){
			Background = WarpedFrame;
			//fuck - cause openCV is gay 
			//need float * for background learning
			unsigned char * pix = WarpedFrame.getPixels();
			for(int i = 0; i < W*H; i++){
				fPixels[i] = (float)pix[i];
			}
		}
		
		void processFrame(float threshold, float learnRate, float motionFade, bool useCamera){
			
			unsigned char * pixCam;
			int 			tWidth;
			int 			tHeight;

			if(!useCamera){
				VID.idleMovie();	
				pixCam 	= VID.getPixels();
				tWidth 	= VID.width;
				tHeight = VID.height;
			}else{
				GRAB.grabFrame();
				pixCam 	= GRAB.getPixels();		
				tWidth 	= GRAB.width;
				tHeight = GRAB.height;		
			}
				
			CameraFrame.setFromPixels(pixCam, tWidth, tHeight);
			CurrentFrame.setFromColorImage(CameraFrame);

			WarpedFrame.warpIntoMe(CurrentFrame, QUAD.getScaledQuadPoints(W,H), warpDst);

			//lets blend the background with a small pct of the new frame
			if(learnRate > 0.0){
				
				float iPct = 1.0 - learnRate;

				unsigned char * pW = WarpedFrame.getPixels();		
				
				for(int i = 0; i < W*H; i++){
					float tmp = (float)pW[i] * learnRate;
					fPixels[i] *= iPct;
					fPixels[i] += tmp;
					pW[i] = (unsigned char)fPixels[i];
				}			

				Background.setFromPixels(pW, W, H);
			}

			//do the background subtraction!
			Subtraction.absDiff(WarpedFrame, Background);
			Subtraction.threshold(threshold);
			
			//Motion history the old fashioned way!
			//About 10fps slower than openCV
			//That could be because openCV getPixels 
			//is slow
			
			/*
			//lets update our motion history image			
			unsigned char * mW = Subtraction.getPixels();		
				
			for(int i = 0; i < W*H; i++){
				mPixels[i] *= motionFade;
				mPixels[i] += mW[i];
				if(mPixels[i] > 255)mPixels[i] = 255;
				mW[i] = (unsigned char)mPixels[i];
			}			

			TEX.loadData(mW, W, H, GL_LUMINANCE);
			*/
			
			//openCV motion history
			//doing funny stuff because 
			//it is a char array 
			//but it is good enough for 
			//what we need and it is faster
			MotionHistory *= motionFade;
			MotionHistory += Subtraction;
			
			
			
		} 
		
		unsigned char * getMotionPixels(){
			unsigned char * pix = MotionHistory.getPixels();
			return pix;
		} 

		void draw(float x, float y){
			CurrentFrame.draw(0,0);
			WarpedFrame.draw(W, 0);
			Background.draw(W,H);
			MotionHistory.draw(W*2,H);
			//TEX.draw(W*2, H);
			Subtraction.draw(W*2,0);
	
			ofSetColor(0xFFFF00);	
			QUAD.draw(0,0,W,H);
		}

		void drawQuadSetupImage(float x, float y, float w, float h){
			ofSetColor(0xFFFFFF);	
			ofRect(0,0,w, h);
			CurrentFrame.draw(16, 12, w-32, h-24);
			ofSetColor(0xFFFF00);	
			QUAD.draw(16, 12, w-32, h-24);
		}
	
		guiQuad				QUAD;
		ofVideoGrabber 		GRAB;
		ofVideoPlayer		VID;
		ofTexture			TEX;
		
		ofCvGrayscaleImage 	Background;
		ofCvGrayscaleImage 	CurrentFrame;
		ofCvGrayscaleImage 	WarpedFrame;
		ofCvGrayscaleImage 	TempFrame;
		ofCvGrayscaleImage	MotionHistory;
		ofCvGrayscaleImage 	Subtraction;
		ofCvColorImage 		CameraFrame;
		
		ofPoint2f 			warpSrc[4];
		ofPoint2f 			warpDst[4];
		
		float *				fPixels;
		float * 			mPixels;
		int					W, H;
		
};

#endif