
void display(void);
void mouse_cb(int button, int state, int x, int y);
void motion_cb(int x, int y);
void passive_motion_cb(int x, int y);
void idle_cb(void);
void keyboard_cb(unsigned char key, int x, int y);
void special_key_cb(int key, int x, int y) ;

static int buttonInUse = 0;

//-------------------------------- 
static float timeNow, timeThen, fps;
static int nFramesForFPS;
static int nFrameCount = 0;

static bool 	bFrameRateSet;
int 			millisForFrame;
int 			prevMillis;
int 			diffMillis;

//------------------------------------------------------------
void display(void){	
	
	//-------------------------------- 
	// when I had "glutFullScreen()"
	// in the initOpenGl, I was gettings a "heap" allocation error 
	// when debugging via visual studio.  putting it here, changes that.
	// maybe it's voodoo, or I am getting rid of the problem 
	// by removing something unrelated, but everything seems
	// to work if I put fullscreen on the first frame of display.

	if (nFrameCount == 0 && windowMode == OF_FULLSCREEN) glutFullScreen();
	
	width = ofGetWidth();
	height = ofGetHeight();
	
	height = height > 0 ? height : 1;
	// set viewport, clear the screen
	glViewport( 0, 0, width, height );
	float * bgPtr = ofBgColorPtr();
	bool bClearAuto = ofbClearBg();
	
	// I don't know why, I need more than one frame at the start in fullscreen mode
	// also, in non-fullscreen mode, windows/intel graphics, this bClearAuto just fails.  
	// I seem to have 2 buffers, alot of flickering 
	// and don't accumulate the way I expect.
	// with this line:   if ((bClearAuto == true) || nFrameCount < 3){
	// we do nFrameCount < 3, so that the buffers are cleared at the start of the app
	// or else we have video memory garbage to draw on to...

	if ((bClearAuto == true || windowMode == OF_WINDOW) || nFrameCount < 3){
		glClearColor(bgPtr[0],bgPtr[1],bgPtr[2], bgPtr[3]);
		glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	}
	
	ofSetupScreen();
	OFSAptr->draw();
  	glutSwapBuffers();
  	
  	// -------------- fps calculation:
	timeNow = ofGetElapsedTimef();
	if( (timeNow-timeThen) > 0.05f || nFramesForFPS == 0 ) {
 		fps = (double)nFramesForFPS / (timeNow-timeThen);
      	timeThen = timeNow;
		nFramesForFPS = 0;
		ofFrameRate = 0.9f * ofFrameRate + 0.1f * fps;
  	}
  	nFramesForFPS++;
  	// --------------

	nFrameCount++;		// increase the overall frame count
}


//------------------------------------------------------------
void mouse_cb(int button, int state, int x, int y) {
	
	
	if (!ofbOriginBottomLeft()){
		y = height - y;
	}
	
	if (nFrameCount > 0){
		OFSAptr->mouseX = x; 
		OFSAptr->mouseY = height - y;
		
		if (state == GLUT_DOWN) {
			OFSAptr->mousePressed(x, height - y, button);
		} else if (state == GLUT_UP) {
			OFSAptr->mouseReleased();
		}
		buttonInUse = button;
	}
}

//------------------------------------------------------------
void motion_cb(int x, int y) {

	if (!ofbOriginBottomLeft()){
		y = height - y;
	}
	if (nFrameCount > 0){
		OFSAptr->mouseX = x; 
		OFSAptr->mouseY = height - y;
		OFSAptr->mouseDragged(x, height - y, buttonInUse);
	}
}

//------------------------------------------------------------
void passive_motion_cb(int x, int y) {

	
	if (!ofbOriginBottomLeft()){
		y = height - y;
	}
	if (nFrameCount > 0){
		OFSAptr->mouseX = x; 
		OFSAptr->mouseY = height - y;
		OFSAptr->mouseMoved(x, height - y);
	}
}

//------------------------------------------------------------
void idle_cb(void) {

	if (nFrameCount != 0 && bFrameRateSet == true){
		diffMillis = ofGetElapsedTimeMillis() - prevMillis;
		if (diffMillis > millisForFrame){
			; // we do nothing, we are already slower than target frame
		} else {
			int waitMillis = millisForFrame - diffMillis; 
			#ifdef TARGET_WIN32
				Sleep(waitMillis);			//windows sleep in milliseconds
			#else
				usleep(waitMillis * 1000);	//mac sleep in microseconds - cooler :)
			#endif 
		}	
	} 

	OFSAptr->update();
	glutPostRedisplay();
	
	prevMillis = ofGetElapsedTimeMillis();
}

//------------------------------------------------------------
void keyboard_cb(unsigned char key, int x, int y) {
	OFSAptr->keyPressed((int)key);
	if (key == 27){				// "escape"
		 OF_EXIT_APP(0);
	}
}

//------------------------------------------------------------
void special_key_cb(int key, int x, int y) {
   OFSAptr->keyPressed((int)key);
}
