#include "grafPlayerApp.h"

//--------------------------------------------------------------
grafPlayerApp::grafPlayerApp(){


}

grafPlayerApp::~grafPlayerApp(){


}
//--------------------------------------------------------------
void grafPlayerApp::setup(){

	mode			= PLAY_MODE_LOAD;
	screenW			= 1024;
	screenH			= 768;
	lastX			= 0;
	lastY			= 0;
	bShowPanel		= false;
	bRotating		= false;
	bShowName		= false;
	bShowTime		= false;
	bUseFog			= true;
	bUseMask		= true;
	bTakeScreenShot = false;
	bUseGravity		= true;
	prevStroke		= 0;
	
	currentTagID	= 0;
	waitTime		= 2.f;
	waitTimer		= waitTime;
	rotationY		= 0;
	tagMoveForce	= .1;
	tagPosVel.set(0,0,0);
	myTagDirectory = TAG_DIRECTORY;
	
	fontSS.loadFont("fonts/frabk.ttf",9);
	fontS.loadFont("fonts/frabk.ttf",14);
	fontL.loadFont("fonts/frabk.ttf",22);
	imageMask.loadImage("images/mask.jpg");
	
	float FogCol[3]={0,0,0};
    glFogfv(GL_FOG_COLOR,FogCol);
    glFogi(GL_FOG_MODE, GL_LINEAR);
    glFogf(GL_FOG_DENSITY, 0.05f);
	fogStart = 370;
    fogEnd   = 970;
	
	ofxXmlSettings xml;
	xml.loadFile("data/settings/directorySettings");
	myTagDirectory = xml.getValue("directory", TAG_DIRECTORY);
	
	setupContolPanel();
	updateConrolPanel();
	
	//preLoadTags();
	particleDrawer.setup(screenW,screenH);

}

static float lastTime = 0.f;

//--------------------------------------------------------------
void grafPlayerApp::update(){

	dt  = ofGetElapsedTimef()-lastTime;
	lastTime  = ofGetElapsedTimef();
	
	if( mode == PLAY_MODE_LOAD )
	{
		//loadTags();
	}
	else if( mode == PLAY_MODE_PLAY )
	{
		if( tags.size() > 0 && drawer.bSetupDrawer)
			drawer.setup( &tags[currentTagID], tags[currentTagID].distMax );

		if( tags.size() > 0 && !myTagPlayer.bDonePlaying )					// normal play, update tag
		{
			myTagPlayer.update(&tags[currentTagID]);
		
		}else if( !myTagPlayer.bPaused && myTagPlayer.bDonePlaying && waitTimer > 0)			   // pause time after drawn, before fades ut
		{
			waitTimer -= dt;
		}
		else if ( !myTagPlayer.bPaused && myTagPlayer.bDonePlaying && (drawer.alpha > 0 || particleDrawer.alpha > 0))			  // fade away, dissolve
		{
			drawer.transition(dt,.015);
			if( bUseGravity ) particleDrawer.fall(dt);
			if(particleDrawer.alpha  > 0 ) particleDrawer.alpha -= .5*dt;
			
		}
		else if (  !myTagPlayer.bPaused && myTagPlayer.bDonePlaying )							// set next tag
		{
			resetPlayer(0);
		}
	
		//---- update the particle field
		int lastStroke = myTagPlayer.getCurrentStroke();
		int lastPoint = myTagPlayer.getCurrentId();
		
		if( prevStroke != lastStroke ) myTagPlayer.bReset = true; 
		if( lastPoint <= 0 ) myTagPlayer.bReset = true;
		if( tags[currentTagID].myStrokes[ lastStroke].pts.size()-1 == lastPoint ) myTagPlayer.bReset = true;
		
		particleDrawer.update( myTagPlayer.getCurrentPoint(),myTagPlayer.getVelocityForTime(&tags[currentTagID]),  dt,  myTagPlayer.bReset);
		
		myTagPlayer.bReset = false; // important so no particle error on first stroke
		prevStroke		= myTagPlayer.getCurrentStroke();
		//---
		
		
		// update rotation
		if(bRotating) rotationY += .65*dt;
		
		// update pos / vel
		tags[currentTagID].position.x += tagPosVel.x;
		tags[currentTagID].position.y += tagPosVel.y;
		
		tagPosVel.x -= .1*tagPosVel.x;
		tagPosVel.y -= .1*tagPosVel.y;
		
		
		
	}
	
	if( bShowPanel ) updateConrolPanel();
	
}


//--------------------------------------------------------------
void grafPlayerApp::draw(){

	ofEnableAlphaBlending();
	
	ofSetColor(255,255,255,255);

	if( mode == PLAY_MODE_LOAD )
	{
	}
	else if( mode == PLAY_MODE_PLAY )
	{
	
		
		ofEnableAlphaBlending();
		
		glPushMatrix();
		
		
			if( bUseFog )
			{
				glFogf(GL_FOG_START, fogStart );
				glFogf(GL_FOG_END, fogEnd );
				glEnable(GL_FOG);				
			}
		
			glTranslatef(screenW/2, screenH/2, 0);
		
			glScalef(tags[currentTagID].position.z,tags[currentTagID].position.z,tags[currentTagID].position.z);
		
			glTranslatef(tags[currentTagID].position.x,tags[currentTagID].position.y,0);
			

			
			glPushMatrix();
		
				glRotatef(tags[currentTagID].rotation.x,1,0,0);
				glRotatef(tags[currentTagID].rotation.y+rotationY,0,1,0);
				glRotatef(tags[currentTagID].rotation.z,0,0,1);
		
				glTranslatef(-tags[currentTagID].min.x*tags[currentTagID].drawScale,-tags[currentTagID].min.y*tags[currentTagID].drawScale,-tags[currentTagID].min.z);
				glTranslatef(-tags[currentTagID].center.x*tags[currentTagID].drawScale,-tags[currentTagID].center.y*tags[currentTagID].drawScale,-tags[currentTagID].center.z);
		
				glDisable(GL_DEPTH_TEST);
				particleDrawer.draw(myTagPlayer.getCurrentPoint().z,  screenW,  screenH);
				
				glEnable(GL_DEPTH_TEST);
		
				glPushMatrix();
					glScalef( tags[currentTagID].drawScale, tags[currentTagID].drawScale, 1);
					drawer.draw( myTagPlayer.getCurrentStroke(), myTagPlayer.getCurrentId() );
				glPopMatrix();
		
				glPushMatrix();
					glScalef( tags[currentTagID].drawScale, tags[currentTagID].drawScale, 1);
					//drawer.drawBoundingBox( tags[currentTagID].min, tags[currentTagID].max, tags[currentTagID].center );
				glPopMatrix();
		
			glPopMatrix();
		
			
		
		glPopMatrix();
		
		
		glDisable(GL_DEPTH_TEST);
		glDisable(GL_FOG);
		

	
	
	}
	
	if(bUseMask)
	{
		ofEnableAlphaBlending();
		glBlendFunc(GL_DST_COLOR, GL_ZERO);
		imageMask.draw(0,0,ofGetWidth(),ofGetHeight());
	}
	
	
	if( mode == PLAY_MODE_PLAY )
	{
		ofSetColor(255,255,255,255);
		if( bShowName && tags.size() > 0 ) fontS.drawString( tags[ currentTagID ].tagname, 10,ofGetHeight()-30 );
		if( bShowTime && tags.size() > 0 )
		{
			float time = myTagPlayer.getCurrentTime();
			float wd = fontL.stringWidth( ofToString( time,0) ) / 10.f;
			wd = 10*(int)(wd);
			
			fontL.drawString(ofToString(time,2), ofGetWidth()-wd-70, ofGetHeight()-30);
		}
	
	}


	ofEnableAlphaBlending();
	if(bShowPanel){
		panel.draw();
		fontSS.drawString("x: toggle control panel  |  p: pause/play  |  s: screen capture  |  m: toggle mouse  |  f: toggle fullscreen  |  h: toggle home  |  arrows: next/prev  |  esc: quit", 90, ofGetHeight()-50);
		fontSS.drawString("left mouse: alter position  |  left+shift mouse: zoom  |  right mouse: rotate y  |  right+shift mouse: rotate x", 220, ofGetHeight()-30);

	}
	

	// screenshots
	if(bTakeScreenShot)
	{
		imgsaver.grabScreen(0,0,ofGetWidth(),ofGetHeight() );
		
		dirLister.setPath( ofToDataPath(myTagDirectory + tags[currentTagID].tagname + "/", true));
		dirLister.setExtensionToLookFor("png");
		int num = dirLister.getNumberOfFiles();
		imgsaver.saveThreaded( myTagDirectory + tags[currentTagID].tagname + "/"+tags[currentTagID].tagname+"_"+ofToString(num+1)+".png");
		
		bTakeScreenShot = false;
	}
	
}


//--------------------------------------------------------------
void grafPlayerApp::keyPressed  (int key){


	
    switch(key){

  		case 'x': bShowPanel=!bShowPanel; break;
		case 'p': 
			myTagPlayer.bPaused = !myTagPlayer.bPaused;
			bRotating = !myTagPlayer.bPaused;
			panel.setValueB("ROTATE",bRotating);
			panel.setValueB("PLAY",!myTagPlayer.bPaused);
			break;
			
			
		case OF_KEY_RIGHT:  resetPlayer(1); break;
        case OF_KEY_LEFT:   resetPlayer(-1); break;
		
		case 's': bTakeScreenShot = true; break;
			
	
		default:
  			break;

  }



}

//--------------------------------------------------------------
void grafPlayerApp::keyReleased(int key){

}

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

	lastX   = x;
	lastY   = y;
}

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

	if( bShowPanel && !panel.minimize) 
	{
		panel.mouseDragged(x,y,button);
	}
	else{
		if( button == 0 )
		{
			if(bShiftOn)
			{
				tagPosVel.x +=  tagMoveForce * (x-lastX);
				tagPosVel.y +=  tagMoveForce * (y-lastY);
			}else if(tags.size() > 0){
				tags[currentTagID].position.z += .01 * (y-lastY);
				tags[currentTagID].position.z = MAX(tags[currentTagID].position.z,.01);
			}
			
		
		}else{
			if( tags.size() > 0 && !bShiftOn) tags[currentTagID].rotation.y += (x-lastX);
			else if( tags.size() > 0 && bShiftOn) tags[currentTagID].rotation.x += (y-lastY);
		}
	}	
	
	
	lastX   = x;
	lastY   = y;

}

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

    if( bShowPanel ) panel.mousePressed(x,y,button);

}

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

	if( bShowPanel && !panel.minimize) 
	{
		panel.mouseReleased();
	}
	 


}

//--------------------------------------------------------------
void grafPlayerApp::resetPlayer( int next)
{
	if(tags.size() <= 0 ) return;
	
	myTagPlayer.reset();
	
	nextTag(next);
	
	drawer.setup( &tags[currentTagID], tags[currentTagID].distMax );
	
	particleDrawer.reset();
	
	waitTimer = waitTime;
	
	rotationY = 0;
	
	tagPosVel.set(0,0,0);
	
	prevStroke = 0;

	
}
//--------------------------------------------------------------
void grafPlayerApp::nextTag(int dir)
{
	
	if(dir==1)
	{
		currentTagID++;
		currentTagID %= tags.size();
	}
	else if(dir==-1){
		currentTagID--;
		if(currentTagID < 0 ) currentTagID = tags.size()-1;
	}
		
	
}
//--------------------------------------------------------------
void grafPlayerApp::loadTags()
{
	if( tags.size() < totalToLoad )
	{
		tags.push_back( grafTagMulti() );
		int toLoad = tags.size()-1;
		
		gIO.loadTag( filesToLoad[ toLoad ], &tags[ toLoad ]);
		tags[ toLoad ].tagname = filenames[ toLoad ];
		
		smoother.smoothTag(4, &tags[ toLoad ]);
		tags[toLoad].average();
		tags[toLoad].average();
	}
	else{
		mode = PLAY_MODE_PLAY;
		resetPlayer(0);
	}
	
}
//--------------------------------------------------------------
void grafPlayerApp::loadTag(string path, string filename)
{
	tags.push_back( grafTagMulti() );
	
	int tagId = tags.size()-1;
	
	gIO.loadTag( path+filename+".gml", &tags[ tagId ]);
	tags[ tagId ].tagname = filename;
	
	smoother.smoothTag(4, &tags[ tagId ]);
	tags[tagId].average();
	//tags[tagId].average();
	
	mode = PLAY_MODE_PLAY;
	resetPlayer(tagId);
}
//--------------------------------------------------------------
void grafPlayerApp::preLoadTags()
{
	filesToLoad.clear();
	filenames.clear();
	totalToLoad = 0;
	
	vector<string> dirs;
	dirLister.setPath( ofToDataPath(myTagDirectory,true) );
	dirLister.findSubDirectories(dirs);
	
	for( int i = 0; i < dirs.size(); i++)
	{
		dirLister.setPath( ofToDataPath(myTagDirectory+dirs[i]+"/",true) );
		dirLister.setExtensionToLookFor("gml");
		int num = dirLister.getNumberOfFiles();
		if( num > 0 )
		{
			filenames.push_back(dirs[i]);
			filesToLoad.push_back(  ofToDataPath(myTagDirectory+dirs[i]+"/"+dirs[i]+".gml") );
		}
	}
	
	
	dirs.clear();
	dirLister.setPath( ofToDataPath(myTagDirectory,true) );
	dirLister.setExtensionToLookFor( "gml" );
	dirLister.getFileNames(dirs);
	
	for( int i = 0; i < dirs.size(); i++)
	{
		filesToLoad.push_back( ofToDataPath(myTagDirectory+dirs[i]) );
		
		string name = dirs[i];
		int endgml = name.find(".gml");
		if( endgml >= 0 )
			name.erase( endgml,name.size() );
		
		filenames.push_back(name);
	}
	
	totalToLoad = filesToLoad.size();
}
//--------------------------------------------------------------
void grafPlayerApp::setupContolPanel()
{
	
	panel.setup("Graffiti Analysis", 20, 20, 300, 500);
	panel.addPanel("App Settings", 1, false);
	panel.addPanel("Draw Settings", 1, false);
	
	
	//---- application sttings
	panel.setWhichPanel("App Settings");
	panel.addToggle("Play / Pause", "PLAY", true);
	panel.addToggle("Rotate", "ROTATE", true);
	panel.addToggle("Display filename", "SHOW_NAME", true);
	panel.addToggle("Display time", "SHOW_TIME", true);
	panel.addToggle("FullScreen", "FULL_SCREEN", false);
	panel.addToggle("Use Fog", "USE_FOG", false);
	panel.addSlider("Fog Start","FOG_START",fogStart,-2000,2000,true);
	panel.addSlider("Fog End","FOG_END",fogEnd,-2000,2000,true);
	
	panel.setWhichPanel("Draw Settings");
	panel.addSlider("Line Alpha","LINE_ALPHA",.92,0,1,false);
	panel.addSlider("Outline Width","LINE_WIDTH",2,1,10,false);
	panel.addSlider("Line Scale","LINE_SCALE",.05,0,.1,false);
	panel.addSlider("Particle Size","P_SIZE",2,0,10,false);
	panel.addSlider("Particle Alpha","P_ALPHA",.75,0,1,false);
	panel.addSlider("Particle Damping","P_DAMP",.15,0,.25,false);
	panel.addSlider("Number Particles","P_NUM",1,0,4,true);
	//panel.addSlider("Wait time","WAIT_TIME",1,0,4,true);
	panel.addToggle("Use gravity", "USE_GRAVITY", true);
	panel.addToggle("Use edge mask", "USE_MASK", false);
	panel.loadSettings("settings/appSettings.xml");
}

//--------------------------------------------------------------
void grafPlayerApp::updateConrolPanel()
{
	panel.update();
	myTagPlayer.bPaused = !panel.getValueB("PLAY");
	bRotating = panel.getValueB("ROTATE");
	bShowName = panel.getValueB("SHOW_NAME");
	bShowTime = panel.getValueB("SHOW_TIME");
	if( panel.getValueB("FULL_SCREEN") )
	{
		panel.setValueB("FULL_SCREEN",false);
		ofToggleFullscreen();
	}
	
	bUseFog = panel.getValueB("USE_FOG");
	fogStart = panel.getValueI("FOG_START");
	fogEnd = panel.getValueI("FOG_END");
	
	drawer.setAlpha(panel.getValueF("LINE_ALPHA"));
	drawer.lineWidth = panel.getValueF("LINE_WIDTH");
	
	drawer.setLineScale( panel.getValueF("LINE_SCALE") );
	
	particleDrawer.setParticleSize( panel.getValueF("P_SIZE") );
	particleDrawer.setDamping( panel.getValueF("P_DAMP") );
	particleDrawer.particle_alpha = panel.getValueF("P_ALPHA") ;
	particleDrawer.numXtras = panel.getValueI("P_NUM");
	bUseGravity = panel.getValueB("USE_GRAVITY");
	bUseMask = panel.getValueB("USE_MASK");
	
}

string grafPlayerApp::getCurrentTagName()
{
	if(tags.size() <= 0 ) return " ";
	else if( mode == PLAY_MODE_LOAD) return tags[tags.size()-1].tagname;
	else return tags[currentTagID].tagname;
}

