#include "ofAppRunner.h"

//========================================================================
// static variables:
static ofSimpleApp * 		OFSAptr;
int							windowMode;
bool 						bMousePressed;
bool						bRightButton;
int							width, height;
static float 				ofFrameRate;
string						windowTitle;
int							storedWindowX;
int							storedWindowY;
int							storedWindowW;
int							storedWindowH;
bool						bCustomFullscreen = false;


//========================================================================
// callbacks:
#include "ofAppGlutGlue.h"	

//--------------------------------------
void ofSetupOpenGL(int w, int h, int screenMode){
	int argc = 1;
	char *argv = "openframeworks";
	char **vptr = &argv;
	glutInit(&argc, vptr);
	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_ALPHA);
		
	windowMode = screenMode;
	
	
	if (windowMode != OF_GAME_MODE){
		glutInitWindowSize(w, h);
		glutCreateWindow("");
		

		ofBackground(200,200,200);		// default bg color
		ofSetColor(0xFFFFFF); 			// default draw color
										// used to be black, but 
										// black + texture = black
										// so maybe grey bg
										// and "white" fg color
										// as default works the best...

		requestedWidth  = glutGet(GLUT_WINDOW_WIDTH);
		requestedHeight = glutGet(GLUT_WINDOW_HEIGHT);	
	} else {
		glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_ALPHA );
    	// w x h, 32bit pixel depth, 60Hz refresh rate
		char gameStr[64];
		sprintf( gameStr, "%dx%d:%d@%d", w, h, 32, 60 );
    	glutGameModeString(gameStr);
    	// start fullscreen game mode
    	glutEnterGameMode();
	}
}

//----------------------- 	gets called when the app exits
// 							currently looking at who to turn off
//							at the end of the application

void ofExitCallback();
void ofExitCallback(){
	
	// who to kill off ? 
	// -- fmod
	// -- quicktime
	// -- freeImage
	// anyone else?
	
	#ifdef WIN32_HIGH_RES_TIMING
		timeEndPeriod(1);
	#endif
	
	//delete OFSAptr;		
	
}

//--------------------------------------
void ofRunApp(ofSimpleApp * OFSA){
	
	OFSAptr = OFSA;
	
	atexit(ofExitCallback);
	
	#ifdef WIN32_HIGH_RES_TIMING	
		timeBeginPeriod(1);		// ! experimental, sets high res time
								// you need to call timeEndPeriod.  
								// if you quit the app other than "esc" 
								// (ie, close the console, kill the process, etc)
								// at exit wont get called, and the time will 
								// remain high res, that could mess things
								// up on your system. 
								// info here:http://www.geisswerks.com/ryan/FAQS/timing.html
								
	#endif							
								
	
	bFrameRateSet = false;
	
	//----------------------
	// setup the callbacks 
	glutMouseFunc(mouse_cb);
	glutMotionFunc(motion_cb);
	glutPassiveMotionFunc(passive_motion_cb);
	glutIdleFunc(idle_cb);
	glutDisplayFunc(display);
	
	glutKeyboardFunc(keyboard_cb);
	glutKeyboardUpFunc(keyboard_up_cb);
	glutSpecialFunc(special_key_cb);
	glutSpecialUpFunc(special_key_up_cb);
	
	//----------------------
	
	ofSeedRandom();	
	
	// 		seed the random generator 
	// 		(users can seed it to a value in setup 
	// 		if they want it fixed);
	
	ofSetWindowTitle("openframeworks");
	
	OFSA->setup();
	glutMainLoop();
}

//--------------------------------------
float ofGetFrameRate(){
	return ofFrameRate;
}	

//--------------------------------------
void ofSetFrameRate(int targetRate){
	// given this FPS, what is the amount of millis per frame
	// that should elapse?
	
	// --- > f / s
	
	if (targetRate == 0){
		bFrameRateSet = false; 
		return;
	}
	
	bFrameRateSet 			= true;
	float durationOfFrame 	= 1.0f / (float)targetRate;
	millisForFrame 			= (int)(1000.0f * durationOfFrame);
}

//--------------------------------------
void ofSleepMillis(int millis){
	#ifdef TARGET_WIN32
		Sleep(millis);			//windows sleep in milliseconds
	#else
		usleep(millis * 1000);	//mac sleep in microseconds - cooler :)
	#endif 
}

//--------------------------------------
void ofBeginCustomFullscreen(int x, int y, int width, int height){

	if (windowMode == OF_GAME_MODE) return;

	#ifdef TARGET_WIN32
	   
	    HWND vWnd  = FindWindow(NULL, windowTitle.c_str());
	    
		if(!bCustomFullscreen){
			
			RECT r;
			
			if(GetWindowRect(vWnd, &r)){ 
				//more accurate as it takes windows elements into account
				storedWindowX = r.left;
				storedWindowY = r.top;
				storedWindowW = r.right - r.left;
				storedWindowH = r.bottom - r.top;
			}else{	
				//fallback
				storedWindowX = 0;
				storedWindowY = 0;
				storedWindowW = ofGetWidth();
				storedWindowH = ofGetHeight();
			}

		}
		    
	    long windowStyle = GetWindowLong(vWnd, GWL_STYLE);
	    
	    windowStyle &= ~WS_OVERLAPPEDWINDOW;
	    windowStyle |= WS_POPUP;
	    
	   	SetWindowLong(vWnd, GWL_STYLE, windowStyle);

		SetWindowPos(vWnd, HWND_TOP, x, y, width, height, SWP_FRAMECHANGED);
		bCustomFullscreen = true;
		
	#endif
}

//--------------------------------------
void ofEndCustomFullscreen(){
	
	if (windowMode == OF_GAME_MODE) return;
	
	#ifdef TARGET_WIN32
	
		if(bCustomFullscreen){
			HWND vWnd  = FindWindow(NULL, windowTitle.c_str());
			
		    long windowStyle = GetWindowLong(vWnd, GWL_STYLE);
			windowStyle  |= WS_OVERLAPPEDWINDOW;
		    windowStyle  &= ~WS_POPUP;
		    
			SetWindowLong(vWnd, GWL_STYLE, windowStyle);
			SetWindowPos(vWnd, HWND_TOP,storedWindowX, storedWindowY, storedWindowW, storedWindowH, SWP_FRAMECHANGED);
			bCustomFullscreen = false;
		}
		
	#endif
}
 

//--------------------------------------
void ofHideCursor(){
	glutSetCursor(GLUT_CURSOR_NONE);
}

//--------------------------------------
void ofShowCursor(){
	glutSetCursor(GLUT_CURSOR_RIGHT_ARROW);
}


//--------------------------------------
void ofPositionWindow(int x, int y){
	glutPositionWindow(x,y);
}

//--------------------------------------
void ofShapeWindow(int width, int height){
	glutReshapeWindow(width, height);
}

//--------------------------------------
void ofSetWindowTitle(string title){
	windowTitle = title;
	glutSetWindowTitle(windowTitle.c_str());
}

//--------------------------------------
void ofToggleFullscreen(){
	
	if (windowMode == OF_GAME_MODE) return;
	
	newScreenMode = true;
	if (windowMode == OF_WINDOW){
		windowMode = OF_FULLSCREEN;
	} else {
		windowMode = OF_WINDOW;
	}
}

//--------------------------------------
void ofSetFullscreen(bool fullscreen){

	if (windowMode == OF_GAME_MODE) return;

	if(fullscreen && windowMode==OF_WINDOW){ 
		windowMode    = OF_FULLSCREEN; 	
		newScreenMode = true; 
	}
	else if(!fullscreen && windowMode==OF_FULLSCREEN){
		windowMode    = OF_WINDOW;
		newScreenMode = true; 		
	}
}

//--------------------------------------
int ofGetWindowMode(){
	return windowMode;
}

//--------------------------------------
void ofSetVerticalSync(bool bSync){
	//----------------------------
	#ifdef TARGET_WIN32
	//----------------------------
		if (bSync) {
			if (GLEE_WGL_EXT_swap_control) wglSwapIntervalEXT (1);
		} else {
			if (GLEE_WGL_EXT_swap_control) wglSwapIntervalEXT (0);
		}
	//----------------------------
	#endif
	//----------------------------
	
	//--------------------------------------
	#ifdef TARGET_OSX
	//--------------------------------------
		long sync = bSync == true ? 1 : 0;
		CGLSetParameter (CGLGetCurrentContext(), kCGLCPSwapInterval, &sync); 
	//--------------------------------------
	#endif
	//--------------------------------------


	// linux ofSetVerticalSync needed
}


