/** SGX

The   sss    gggg x   x   
     s      g      x x    Engine
      sss   g  gg   x
         s  g   g  x x          Copyright 1995-2009.
     ssss    gggg x   x         Steven Goodwin. All Rights Reserved.
    
This version has been released under the GNU Public License v2.0.

Please see the license files for details.

File: sgx/src/drivers/common/opengl/oglcallbacks.cpp

*/

#include "sgx/core/core.hpp"
#include "sgx/graphics/graphics.hpp"
#include "sgx/input/input.hpp"

#include "drivers/common/opengl/opengl.hpp"

void sgxDrawScene()
{
	CSGXGraphicsEngine::get()->renderScene();
	CSGXGraphicsEngine::get()->blit();
}

void sgxIdleScene()
{
	COpenGLEngine::getOpenGL()->idleScene();
}

CSGXInputManager::tKey translateKey(unsigned char key) {
	unsigned char nkey = (unsigned char)sgxToUpper(key);

	// (The function keys are only available in GLUT v2)
	if (nkey >= GLUT_KEY_F1 && nkey <= GLUT_KEY_F12) {
		nkey = (nkey-GLUT_KEY_F1) + SGX_KEY_F1;
	}

	switch(nkey) {
		case	27:			nkey = SGX_KEY_ESCAPE;	break;
		case	32:			nkey = SGX_KEY_SPACE;	break;
		case	13:			nkey = SGX_KEY_RETURN;	break;
	}
	return (CSGXInputManager::tKey)nkey;
}

CSGXInputManager::tKey translateKey2(int key) {
	switch(key) {
	case	GLUT_KEY_LEFT:			return SGX_KEY_LEFT;
	case	GLUT_KEY_RIGHT:			return SGX_KEY_RIGHT; 
	case	GLUT_KEY_UP:			return SGX_KEY_UP;	
	case	GLUT_KEY_DOWN:			return SGX_KEY_DOWN;
	case	GLUT_KEY_HOME:			return SGX_KEY_HOME;
	case	GLUT_KEY_END:			return SGX_KEY_END;	
	case	GLUT_KEY_PAGE_UP:		return SGX_KEY_PAGEUP;
	case	GLUT_KEY_PAGE_DOWN:		return SGX_KEY_PAGEDOWN;
	}
	sgxAssert(key<256);
	return (CSGXInputManager::tKey)key;
}

void sgxKeyboardHandlerUp(unsigned char key, int x, int y) {
	CSGXInputManager::get()->applyKeyboardReleased(translateKey(key));
}

void sgxKeyboardHandlerDown(unsigned char key, int x, int y)
{
	CSGXInputManager::get()->applyKeyboardPressed(translateKey(key));
}

void sgxKeyboardHandlerUp2(int key, int x, int y) {
	CSGXInputManager::get()->applyKeyboardReleased(translateKey2(key));
}

void sgxKeyboardHandlerDown2(int key, int x, int y)
{
	CSGXInputManager::get()->applyKeyboardPressed(translateKey2(key));
}

void sgxMouseHandler(int button, int state, int x, int y)
{
	CSGXInputManager::tMouseButton input_button;
	CSGXInputManager::get()->applyMousePosition(x, y);

	switch(button) {
	case	GLUT_LEFT_BUTTON:	input_button = CSGXInputManager::eMouseButtonLeft; break;
	case	GLUT_MIDDLE_BUTTON:	input_button = CSGXInputManager::eMouseButtonMiddle; break;
	case	GLUT_RIGHT_BUTTON:	input_button = CSGXInputManager::eMouseButtonRight; break;
	default:
		return;
	}

	CSGXInputManager::get()->applyMouseButton(input_button, state==GLUT_DOWN?TRUE:FALSE);
}

void sgxMouseMotionHandler(int x, int y)
{
	CSGXInputManager::get()->applyMousePosition(x, y);
}

void sgxReshapeHandler(int width, int height)
{
	CSGXGraphicsEngine::get()->setScreenSize(width, height);
	CSGXGraphicsEngine::get()->updateViewports();
	sgxDrawScene();
}


void COpenGLEngine::prepareCallbacks()
{
	glutDisplayFunc(sgxDrawScene);
	glutIdleFunc(sgxIdleScene);
	glutKeyboardFunc(sgxKeyboardHandlerDown);

#if (GLUT_API_VERSION >= 2)
	glutSpecialFunc(sgxKeyboardHandlerDown2);
#else
#pragma message("You need GLUT Version 2 or above to support the special key messages (i.e. cursors) and work properly.")
#endif

#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13)
	glutKeyboardUpFunc(sgxKeyboardHandlerUp);
	glutSpecialUpFunc(sgxKeyboardHandlerUp2);
#else
#pragma message("You need GLUT Version 4 or above to support the 'key up' messages and work properly.")
#endif
	glutMouseFunc(sgxMouseHandler);
	glutMotionFunc(sgxMouseMotionHandler);
	glutPassiveMotionFunc(sgxMouseMotionHandler);
	glutReshapeFunc(sgxReshapeHandler);
}
