#ifndef _GUI_QUAD_
#define _GUI_QUAD_

#include "ofMain.h"
#include "ofAddons.h"
#include "baseGui.h"

#include "ofCvConstants.h"
/////////////////////////
//	REQUIRES ofPoint2f to  
//	be defined as so:
/*
	typedef struct {
		float x;
		float y;
	} ofPoint2f;
*/
/////////////////////////

class guiQuad : public baseGui{
	
	public:
		
		//----------------------------------------------------
		
		guiQuad(){
			selected = -1;
			quadName = "QUAD_";
		}

		//----------------------------------------------------
		void setup(string _quadName){
			quadName = _quadName;
		}

		//----------------------------------------------------
		void releaseAllPoints(){
			selected = -1;
		}

		//----------------------------------------------------
		//these should be in the range x(0-maxX) y(0-maxH) 
		//with 	width  = maxW
		//		height = maxH 
		void setQuadPoints( ofPoint2f * inPts ){
				
			for(int i = 0; i < 4; i++){
				srcZeroToOne[i].x	= inPts[i].x;
				srcZeroToOne[i].y	= inPts[i].y;
				
				if(srcZeroToOne[i].x > 1) srcZeroToOne[i].x = 1;
				if(srcZeroToOne[i].y > 1) srcZeroToOne[i].y = 1;
			}
		}
		
		//----------------------------------------------------
		void readFromFile(string filePath){
			
			xml.initFromFile(filePath, "PARAMS");
			loadSettings();	
		}

		//----------------------------------------------------
		void loadSettings(){
			
			string str;
			
			
			for(int i = 0; i < 4; i++){
				
				//These two lines give us:
				// "QUAD_SRC_0"
				// "QUAD_SRC_1" etc...
										
				str = quadName;
				str += ofToString(i);									
																								
				srcZeroToOne[i].x = xml.getValue(str+"_X", srcZeroToOne[i].x);
				srcZeroToOne[i].y = xml.getValue(str+"_Y", srcZeroToOne[i].y);		
				
				if(srcZeroToOne[i].x > 1) srcZeroToOne[i].x = 1;
				if(srcZeroToOne[i].y > 1) srcZeroToOne[i].y = 1;
											
			}	
						
		}
		
		//----------------------------------------------------
		bool selectPoint(float x, float y, float offsetX, float offsetY, float width, float height, float hitArea){

			//make sure selected is -1 unless we really find a point			
			//selected = -1;

			if(width == 0 || height == 0 || x < offsetX || x > offsetX + width || y < offsetY ||  y > offsetY + height){
				//then we are out of our possible quad area
				//so we ignore :)
				return false;
			}  
			
			//lets get it in range x(0 - width) y(0 - height)
			float px = x - offsetX;
			float py = y - offsetY;
			
			//now get in 0-1 range
			px /= width;
			py /= height;
			
			hitArea /= width;
			
			//we want to store the smallest distance found
			//because in the case when two points are in the 
			//hit area we want to pick the closet
			float storeDist = 9999999.0;
			
			for(int i = 0; i < 4; i++){
				float dx = abs(px -  srcZeroToOne[i].x);
				float dy = abs(py -  srcZeroToOne[i].y);
				
				float dist = sqrt(dx*dx + dy*dy);
				
				if(dist > hitArea)continue;
				
				if(dist < storeDist){
					selected = i;
					storeDist = dist;
				}
			}

			if(selected != -1){
				srcZeroToOne[selected].x 	= px;
				srcZeroToOne[selected].y 	= py;	
				srcScaled[selected].x		= px;
				srcScaled[selected].y		= py;					
			
				if(selected == 0)setCommonText("status: Quad - Top Left");
				else
				if(selected == 1)setCommonText("status: Quad - Top Right");
				else
				if(selected == 2)setCommonText("status: Quad - Bottom Right");
				else 
				if(selected == 3)setCommonText("status: Quad - Bottom Left");
				
				return true;
			}
			
			return false;
		}

		//----------------------------------------------------
		bool updatePoint(float x, float y, float offsetX, float offsetY, float width, float height){
			
			//nothing to update
			if(selected == -1) return false;
			
			if(width == 0 || height == 0){
				//dangerous so we ignore :)
				return false;
			}  
			
			if( x < offsetX ) 			x = offsetX;
			if( x > offsetX + width ) 	x = offsetX + width;
			if( y < offsetY ) 			y = offsetY;
			if( y > offsetY + height) 	y = offsetY + height;
			
			//lets get it in range x(0 - width) y(0 - height)
			float px = x - offsetX;
			float py = y - offsetY;
						
			//now get in 0-1 range
			px /= width;
			py /= height;
			
			srcZeroToOne[selected].x 	= px;
			srcZeroToOne[selected].y 	= py;	
			srcScaled[selected].x		= px;
			srcScaled[selected].y		= py;
			
			return true;
		}

		//----------------------------------------------------
		//returns pts to width by height range 
		ofPoint2f * getScaledQuadPoints(float width, float height){
		
			for(int i = 0; i < 4; i++){
				srcScaled[i].x = srcZeroToOne[i].x * width;
				srcScaled[i].y = srcZeroToOne[i].y * height;				
			}
			
			return srcScaled;
		}


		//----------------------------------------------------
		//returns pts in 0-1 scale
		ofPoint2f * getQuadPoints(){
			return srcZeroToOne;
		}

		
		//----------------------------------------------------
		void saveToFile(string filePath, string newQuadName){
			string str;
				
			for(int i = 0; i < 4; i++){
			
				str = newQuadName;
				str += ofToString(i);

				xml.setValue(str+"_X", srcZeroToOne[i].x);
				xml.setValue(str+"_Y", srcZeroToOne[i].y);		
			}
			
			xml.saveFile(filePath);
		}		
		
		//----------------------------------------------------
		void saveToFile(string filePath){
			saveToFile(filePath, quadName);
		}

		//----------------------------------------------------
		void draw(float x, float y, float width, float height, int red, int green, int blue, int thickness){
			
			getScaledQuadPoints(width, height);
			glPushMatrix();
				glTranslatef(x, y, 0);
				
				ofNoFill();
				
				ofSetColor(red, green, blue);
				glLineWidth(thickness);
				glBegin(GL_LINE_LOOP);
				for(int i = 0; i < 4; i++){
					glVertex2f(srcScaled[i].x, srcScaled[i].y);
				}
				glEnd();
				
				glLineWidth(1);
				ofSetRectMode(OF_RECTMODE_CENTER);
				for(int i = 0; i < 4; i++){
					
					if(i == 0)ofSetColor(255, 0, 0);
					if(i == 1)ofSetColor(0, 255, 0);
					if(i == 2)ofSetColor(0, 0, 255);
					if(i == 3)ofSetColor(0, 255, 255);

					ofRect(srcScaled[i].x, srcScaled[i].y, 8, 8);
				}
			
				
				ofSetRectMode(OF_RECTMODE_CORNER);
				ofFill();
				
				glEnd();
			glPopMatrix();
		}

		//----------------------------------------------------
		void draw(float x, float y, float width, float height){
			
			//default to a think yellow line
			draw(x, y, width, height, 255, 255, 0, 1);
		}

		
	protected:
		ofXML	xml;
		ofPoint2f srcZeroToOne[4];
		ofPoint2f srcScaled[4];
		string quadName;
		int selected;
};

#endif	



