#include "testApp.h"

/*
 
 KEYS:
 
 Threshold				-- up key or down key
 Simple Amount			-- left key or right key (how much to simplofy the contour)
 DrawMode				-- 1 key to toggle gray of color image
 Points Direction		-- 2 key to toggle the direction of the points.
 Add some Balls			-- space or b key to add big or small particles

 */
 
//--------------------------------------------------------------
void testApp::setup() {
	
	ofBackground(0, 0, 0);
	ofSetFrameRate(30.0);
	
	bReversePoints	 = false;
	bDrawGray		 = false;
	simpleAmount     = 1.0;
	threshold		 = 152;
	
	vw = 640;
	vh = 480;
	input.initGrabber(vw, vh);
	
	
	color.allocate(vw, vh);
	gray.allocate(vw, vh);
	contourAnalysis.setSize(vw, vh);
	
	
	// Box2d
	box2d.init();
	box2d.setGravity(0, 20);
	box2d.createBounds(0, 0, vw, vh);
	box2d.setFPS(30.0);
}


//--------------------------------------------------------------
void testApp::update() {
	
	
	box2d.update();	
	input.update();
	
	
	if(input.isFrameNew()) {
		
		color.setFromPixels(input.getPixels(), vw, vh);
		gray = color;
		gray.threshold(threshold, true);
		
		contour.findContours(gray, 30, vw*vh, 20, true);
		
		
		// for testing lets just grab the largest blob
		if(contour.nBlobs > 0) {
			
			contourAnalysis.simplify(contour.blobs[0].pts, simpleCountour, simpleAmount);
			
			ofPoint p;
			lineStrip.setWorld(box2d.getWorld());
			lineStrip.clear();
			
			// we need to loop backward to make the top 
			// of the contour the active side else go the 
			// other way.
			if(bReversePoints) {
				for(int i=simpleCountour.size()-1; i>0; i--) {
					p.x = simpleCountour[i].x;
					p.y = simpleCountour[i].y;
					lineStrip.addPoint(p.x, p.y);
				}
			}
			else {
				for(int i=0; i<simpleCountour.size(); i++) {
					p.x = simpleCountour[i].x;
					p.y = simpleCountour[i].y;
					lineStrip.addPoint(p.x, p.y);
				}
			}
			
			// good to go :)
			lineStrip.createShape();
		}
		
	}
	
	
	
	
}

//--------------------------------------------------------------
void testApp::draw() {
	
	ofSetColor(0xffffff);
	if(!bDrawGray) color.draw(0, 0);
	else gray.draw(0, 0);
	
	ofNoFill();
	ofSetColor(255, 0, 0);
	contourAnalysis.draw(simpleCountour, 0, 0, vw, vh);
	
	
	// draw the box2d balls
	for(int i=0; i<customParticles.size(); i++) {
		customParticles[i].draw();
	}
	
	lineStrip.draw();
	
	
	string info = "FPS: "+ofToString(ofGetFrameRate());
	info += "\nThreshold: "+ofToString(threshold);
	info += "\nSimple Amount: "+ofToString(simpleAmount);
	info += "\npress [1] to toggle draw mode. " + ofToString(bDrawGray);	
	info += "\npress [2] to toggle points direction." + ofToString(bReversePoints);
	info += "\n\nPress [space] to add big balls.";
	info += "\nPress [b] to add small balls.";
	ofSetColor(255, 255, 0);
	ofDrawBitmapString(info, 20, 20);
}


//--------------------------------------------------------------
void testApp::keyPressed(int key) {
	
	
	// gray threshold
	if(key == OF_KEY_UP) {
		threshold ++;
		if(threshold > 255) threshold = 255;
	}
	if(key == OF_KEY_DOWN) {
		threshold --;
		if(threshold < 0) threshold = 0;
	}
	
	// the simple amount 
	if(key == OF_KEY_LEFT) {
		simpleAmount += 1.0;
		if(simpleAmount > 100.0) simpleAmount = 100.0;
	}
	if(key == OF_KEY_RIGHT) {
		simpleAmount -= 1.0;
		if(simpleAmount < 1.0) simpleAmount = 1.0;
	}
	
	// toggle the image draw mode
	if(key == '1') bDrawGray = !bDrawGray;
	
	// toggle the points direction
	if(key == '2') bReversePoints = !bReversePoints;
	
	// big balls
	if(key == ' ') {	
		float r = ofRandom(20, 40);		
		CustomParticle p;
		
		// Mass Bounce Friction
		p.setPhysics(0.0001, 0.79, 0.01);
		p.setup(box2d.getWorld(), mouseX, mouseY, r);
		p.c = (int)ofRandom(30, 100);
		customParticles.push_back(p);
		
	}
	
	// small balls
	if(key == 'b') {
		
		float r = ofRandom(8, 15);		
		CustomParticle p;
		
		// Mass Bounce Friction
		p.setPhysics(0.0001, 0.73, 0.9);
		p.setup(box2d.getWorld(), mouseX, mouseY, r);
		p.c = (int)ofRandom(3, 255); // halloween colors boohaha
		customParticles.push_back(p);
		
	}
	
}

//--------------------------------------------------------------
void testApp::mouseMoved(int x, int y ) {
}

//--------------------------------------------------------------
void testApp::mouseDragged(int x, int y, int button) {
}

//--------------------------------------------------------------
void testApp::mousePressed(int x, int y, int button) {
}

//--------------------------------------------------------------
void testApp::mouseReleased(int x, int y, int button) {
}

//--------------------------------------------------------------
void testApp::windowResized(int w, int h) {
}

