#include "cardManager.h"


// TODO : remove HU crap that doesn't work anyway... (0.5 done)
// TODO : remove XML stuff for now, not needed.

//---------------------------
void cardManager::setup(string xmlFile){
	xmlCardBank = xmlFile;
	xml.setVerbose(true);
	
	inputToCheck.allocate(CARD_CV_W, CARD_CV_H);
	cardImage.allocate(CARD_CV_W, CARD_CV_H);
	cardImageFlipped.allocate(CARD_CV_W, CARD_CV_H);
	resultImage.allocate(CARD_CV_W, CARD_CV_H);
	
	//loadFromXML();
	loadCardImages();
}	


//---------------------------
void cardManager::loadCardImages(){
	for (int i = 0; i < 52; i++){
		cardImages[i].loadImage("images/" + ofToString(i) + "_cards.png");
	}
	
}

//---------------------------
void cardManager::saveCardAs(card &theCard, int whichCard){
	if( whichCard <= 52 ){
		theCard.whichCard = whichCard;
		int index = whichCard -1;
		cardBank[index] = theCard;
		saveToXML(cardBank[index]);
	}
}

//---------------------------
bool cardManager::loadFromXML(){

	xml.loadFile(xmlCardBank);
	
	for(int i = 0; i < 52; i++){
		string whichCardStr = "card_"+ofToString(i+1);
		if( xml.tagExists(whichCardStr+":hu_1") ){
		
			cardBank[i].HuMoments.hu1 = xml.getValue(whichCardStr+":hu_1", 0.0) / 10000;
			cardBank[i].HuMoments.hu2 = xml.getValue(whichCardStr+":hu_2", 0.0) / 100000;
			cardBank[i].HuMoments.hu3 = xml.getValue(whichCardStr+":hu_3", 0.0) / 1000000;
			cardBank[i].HuMoments.hu4 = xml.getValue(whichCardStr+":hu_4", 0.0) /  10000000;
			cardBank[i].HuMoments.hu5 = xml.getValue(whichCardStr+":hu_5", 0.0) / 10000000;
			cardBank[i].HuMoments.hu6 = xml.getValue(whichCardStr+":hu_6", 0.0) / 10000000;
			cardBank[i].HuMoments.hu7 = xml.getValue(whichCardStr+":hu_7", 0.0) / 10000000;
			
			cardBank[i].whichCard = i + 1;
			cardBank[i].ptsSet = true;
			
			printf("card[%i] h1 is %f - which card %i \n", i, cardBank[i].HuMoments.hu1, cardBank[i].whichCard); 
			
		}
	}
}

//---------------------------
bool cardManager::saveToXML(card &theCard){	

		printf("Trying Saving card\n");	
		if(theCard.whichCard == -1)return false;
		printf("Saving card\n");

		string whichCardStr = "card_"+ofToString(theCard.whichCard);
		
		xml.setValue(whichCardStr+":hu_1", theCard.HuMoments.hu1 * 10000);
		xml.setValue(whichCardStr+":hu_2", theCard.HuMoments.hu2 * 100000);
		xml.setValue(whichCardStr+":hu_3", theCard.HuMoments.hu3 * 1000000);
		xml.setValue(whichCardStr+":hu_4", theCard.HuMoments.hu4 * 10000000);
		xml.setValue(whichCardStr+":hu_5", theCard.HuMoments.hu5 * 10000000);
		xml.setValue(whichCardStr+":hu_6", theCard.HuMoments.hu6 * 10000000);
		xml.setValue(whichCardStr+":hu_7", theCard.HuMoments.hu7 * 10000000);

		xml.saveFile(xmlCardBank);
}

//---------------------------
//void cardManager::resetCards(){
//	for(int i = 0; i < NUM_CARDS; i++){
//		cards[i].reset();
//	}
//}

//---------------------------
int cardManager::identifyCardSimple(card &theCard, float matchThresh){
	
	/*
	float smallestAmnt = 9999999;
	int smallestIndex  = -1;
	
	// zach changed from 52 to 13 just for a sec.
	for(int i = 0; i < 13; i++){
		if(!cardBank[i].ptsSet)continue;
	
		float diff = fabs(newCardBank[i].HuMoments.hu1 - theCard.HuMoments.hu1);
		
		if(diff < smallestAmnt ){
			smallestAmnt = diff;
			smallestIndex = i+1;
		}
	}
	
		
	theCard.diff = smallestAmnt*100000.0;
	theCard.whichCard = smallestIndex;		
	*/
	 return 0;
}


//---------------------------
int cardManager::identifyCardViaHu(card &theCard, float matchThresh){
	/*	
	for (int j = 0; j < 3; j++) {
	
		float smallestAmnt = 9999999;
		int smallestIndex  = -1;
		for(int i = 0; i < 52; i++){
			if(!cardBank[i].ptsSet)continue;
			
			//float diff = fabs(cardBank[i].HuMoments.hu1 - theCard.HuMoments.hu1);
			
			float diff = (float)returnShapeMatchFromOpencvMethod(newCardBank[i].HuMoments, theCard.HuMoments, j+1);
			printf("vs %i -- %f \n", i, (float)diff);
			
			if(diff < smallestAmnt ){
				smallestAmnt = diff;
				smallestIndex = i+1;
			}
		}
		
		theCard.whichCardHu[j] = smallestIndex;
		theCard.diffHu[j] = smallestAmnt;
	}
	//else theCard.whichCard = -1;
	*/
	return 0;
}


int cardManager::identifyCardViaPixels(card &theCard, cardImageSet &theCardImageSet){		
	
	
	theCard.whichCard  = -1; // unknown.
	
	float smallestAmnt = 9999999;
	int smallestIndex  = -1;
	float minDev = 0;
	
	for(int i = 0; i < 52; i++){
		
		// get the diff versus both upside down and right side up.
		// 
		
		if (theCard.bRedSuit	!= newCardBank[i].bRedSuit)				continue;
		if (theCard.bFaceCard	!= newCardBank[i].bFaceCard)			continue;
		if (theCard.bFaceCard == false) {
			if (theCard.nonFaceCardBlobCount != newCardBank[i].nonFaceCardBlobCount) continue;
		}
		
		//printf("checking vs %i \n", i);
		
		unsigned char * pixelsMe			= theCardImageSet.thresholdedImage.getPixels();
		unsigned char * pixelsThem			= newCardBankImages[i].thresholdedImage.getPixels();
		unsigned char * pixelsThemFlipped	= newCardBankImages[i].thresholdedImageFlipped.getPixels();
		
		
		cardImage.setFromPixels(pixelsThem, CARD_CV_W, CARD_CV_H);
		cardImageFlipped.setFromPixels(pixelsThemFlipped, CARD_CV_W, CARD_CV_H);
		inputToCheck.setFromPixels(pixelsMe, CARD_CV_W, CARD_CV_H);
		
		float diff = differenceBetweenImages(inputToCheck, cardImage, 0);
		float diff2 = differenceBetweenImages(inputToCheck, cardImageFlipped, 0);
		float minDiff = MIN(diff, diff2);
		if(minDiff < smallestAmnt ){
			smallestAmnt	= minDiff;
			smallestIndex	= i;
		}
		
		/*
		for (int j = 0; j < 5; j++){
			inputToCheck.setFromPixels(pixelsMe, CARD_CV_W, CARD_CV_H);
			inputToCheck.rotate( (2-j)*4, CARD_CV_W/2, CARD_CV_H/2 );
			float diff = differenceBetweenImages(inputToCheck, cardImage, 0);
			float diff2 = differenceBetweenImages(inputToCheck, cardImageFlipped, 0);
			float minDiff = MIN(diff, diff2);
			if(minDiff < smallestAmnt ){
				smallestAmnt	= minDiff;
				smallestIndex	= i;
			}
		}
		*/
		
		for (int j = 0; j < 3; j++){
		for (int k = 0; k < 3; k++){
			inputToCheck.setFromPixels(pixelsMe, CARD_CV_W, CARD_CV_H);
			inputToCheck.translate( (1-j)*3,(1-k)*3);
			float diff = differenceBetweenImages(inputToCheck, cardImage, 0);
			float diff2 = differenceBetweenImages(inputToCheck, cardImageFlipped, 0);
			float minDiff = MIN(diff, diff2);
			if(minDiff < smallestAmnt ){
				smallestAmnt	= minDiff;
				smallestIndex	= i;
			}
		}
		}
		
		
		
	}
	
	//printf("closest is %i, diff is %f\n", smallestIndex, smallestAmnt);

	theCard.whichCard = smallestIndex; // get the data in...
	

	return 0;
	
}

float cardManager::differenceBetweenImages(ofxCvGrayscaleImage &mom, ofxCvGrayscaleImage &dad, int method){
	
	resultImage.absDiff(mom, dad);
	//resultImage -= dad;
	return resultImage.countNonZeroInRegion(0,0,CARD_CV_W, CARD_CV_H);
	/*
	int totalPixelCount					= CARD_CV_W*CARD_CV_H;
	float diff							= 0;
	
	// 0 = sq diff, 1 = pixel diff, etc
	unsigned char * pixelsMe			=	mom.getPixels();
	unsigned char * pixelsThem			=	dad.getPixels();
	
	for (int j = 0; j < totalPixelCount; j++){
		diff	+= sqrt((pixelsMe[j] - pixelsThem[j])*(pixelsMe[j] - pixelsThem[j]));
	}
	
	return diff;
	*/
}


void cardManager::drawCardMatching(vector <card> &cards, float x, float y){
	glPushMatrix();
	glTranslatef(x, y, 0);
	
	ofEnableAlphaBlending();
	for(int i = 0; i < cards.size(); i++){
		if( cards[i].ptsSet ){
			
			
			
			ofSetColor(0xffffff);
			if( cards[i].whichCard != -1 ){
				int who = cards[i].whichCard;
				newCardBankImages[who].cardImage.draw(640 + cards[i].center.x/2, 240+cards[i].center.y/2,32,40);
				//ofCircle(cards[i].center.x, cards[i].center.y, 40);
			}	
		}
	}
}
																	
												

//---------------------------
void cardManager::draw(vector <card> &cards, float x, float y){
	glPushMatrix();
	glTranslatef(x, y, 0);
	
	ofEnableAlphaBlending();
	for(int i = 0; i < cards.size(); i++){
		if( cards[i].ptsSet ){
			
			ofSetColor(0, 100, 255);
			ofNoFill();
			ofBeginShape();
			for(int j = 0; j < 4; j++){
				ofVertex(cards[i].c[j].x, cards[i].c[j].y);
				//ofVertex(cards[i].sqPts[j].x, cards[i].sqPts[j].y);
			}
			ofEndShape(true);
			
			ofSetColor(255,255,0,200);
			ofFill();
			for(int j = 0; j < 4; j++){
				ofCircle(cards[i].c[j].x, cards[i].c[j].y, 10);
				//ofCircle(cards[i].sqPts[j].x, cards[i].sqPts[j].y, 10);
			}
			
			ofSetColor(0,0,0,255);
			ofDrawBitmapString("a",cards[i].c[ cards[i].pta ].x-3, cards[i].c[ cards[i].pta ].y);
			ofDrawBitmapString("b",cards[i].c[ cards[i].ptb ].x-3, cards[i].c[ cards[i].ptb ].y);
			ofDrawBitmapString("c",cards[i].c[ cards[i].ptc ].x-3, cards[i].c[ cards[i].ptc ].y);
			ofDrawBitmapString("d",cards[i].c[ cards[i].ptd ].x-3, cards[i].c[ cards[i].ptd ].y);
			
			
			if( cards[i].whichCard != -1 ){
				ofSetColor(20, 20, 160, 190);
				ofRect(cards[i].center.x-8, cards[i].center.y-12, 56, 23);
				ofSetColor(0x00FF00);	
				ofDrawBitmapString(ofToString(cards[i].id)+ " act: " + ofToString(cards[i].activity), cards[i].center.x - 4, cards[i].center.y + 2);
			}
			
			
			ofSetColor(0xffffff);
			
			//printf("%i \n", cards[i].whichCard);
			
			if( cards[i].whichCard != -1 ){
				int who = cards[i].whichCard;
				newCardBankImages[who].cardImage.draw(640 + cards[i].center.x/2, 240+cards[i].center.y/2,32,40);
				//ofCircle(cards[i].center.x, cards[i].center.y, 40);
			}	
			
			//newCardBankImages[(int)ofRandom(0,40)].cardImage.draw(0,0,300,300);
			
			// useful to toggle this drawin.g
			cards[i].drawAnalysisResults(cards[i].center.x, cards[i].center.y);
			
			//				
			//				
			//				if( cards[i].whichCard != -1 ){
			//					ofSetColor(20, 20, 160, 190);
			//					ofRect(cards[i].center.x-8, cards[i].center.y-12, 56, 23);
			//					ofSetColor(0x00FF00);	
			//					ofDrawBitmapString(ofToString(cards[i].whichCard)+ " = " + ofToString(cards[i].getCard()) + " " + ofToString(cards[i].diff, 3), cards[i].center.x - 4, cards[i].center.y + 2);
			//				}
			//				
			//				for (int j = 0; j < 3; j++){
			//					if( cards[i].whichCardHu[j] != -1 ){
			//						ofSetColor(20, 20, 160, 190);
			//						ofRect(cards[i].center.x-8, cards[i].center.y-12 + (j+1)*15, 56, 23);
			//						ofSetColor(0x00FF00);	
			//						ofDrawBitmapString(ofToString(cards[i].whichCardHu[j]) + " " + ofToString(cards[i].diffHu[j]*10, 3), cards[i].center.x - 4, cards[i].center.y + 2 + (1+j)*15);
			//					}
			//				}
			//				
			//				// this should be a function, yikes: 
			//				
			//				ofSetColor(20, 20, 160, 190);
			//				ofRect(cards[i].center.x-8, cards[i].center.y-12 +60, 56, 23);
			//				ofSetColor(0x00FF00);	
			//				ofDrawBitmapString("pct white " + ofToString(cards[i].pctWhitePixels, 4), cards[i].center.x - 4, cards[i].center.y + 2 + 60);
			//									
			//				ofSetColor(20, 20, 160, 190);
			//				ofRect(cards[i].center.x-8, cards[i].center.y-12 +75, 56, 23);
			//				ofSetColor(0x00FF00);	
			//				ofDrawBitmapString( ofToString((int)cards[i].avgColor.x) + " " + ofToString((int)cards[i].avgColor.y) + " " + ofToString((int)cards[i].avgColor.z), cards[i].center.x - 4, cards[i].center.y + 2 + 75);
			//				
			//				ofSetColor(20, 20, 160, 190);
			//				ofRect(cards[i].center.x-8, cards[i].center.y-12 +90, 56, 23);
			//				ofSetColor(0x00FF00);	
			//				ofDrawBitmapString( cards[i].bFaceCard == true ? "face card" : "number card" , cards[i].center.x - 4, cards[i].center.y + 2 + 90);
			//				
			//				ofSetColor(20, 20, 160, 190);
			//				ofRect(cards[i].center.x-8, cards[i].center.y-12 +105, 56, 23);
			//				ofSetColor(0x00FF00);	
			//				ofDrawBitmapString( cards[i].bRedSuit == true ? "red card" : "black card (or face card)" , cards[i].center.x - 4, cards[i].center.y + 2 + 105);
			//				
			
		}
	}
	ofDisableAlphaBlending();		
	
	glPopMatrix();
}



