/* 
	A Space Game version 0.1(ASGv0_1)

	Main program
	

*/
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <iomanip>
#include <fstream>
#include <iostream>
#include <cstring>
//audio includes
#include "al.h"
#include "alc.h"
#include "alu.h"
#include "alut.h"

//graphic includes
#include <GL/glut.h>
#include "..\ASGcommon\UDPClient.h"
#include "..\ASGcommon\MessageHandler.h"
#include "..\ASGcommon\Player.h"
#include "..\ASGcommon\Game.h"

#define MAX_MSG_LENGTH 32768
#define RTD 180/3.14159
#define DTR 3.14159/180
#define PILOT 1
#define GUNNER1 2

#define NUM_BUFFERS 4
#define NUM_SOURCES 4
#define AMBIENT_NOISE 0
#define BACKGROUND_MUSIC 1
#define LASER 2
#define EXPLOSION 3

using namespace std;

//input function declarations
void keyboardHandler(unsigned char, int, int);
void specialkeyHandler(int, int, int);
void mouseButton(int, int, int, int);
void mouseMotion(int, int);
void joystickHandler(GLuint , int , int , int);

//game function declarations
void initializeGameBoard();
void initialGameSettings();
void startGame();
void setFrustum();

bool gameDone = false;
bool weLost = false;
bool detecthit = false;

float nnear = 1.0;
float nfar = 1E8;
float zoom = 1.0;
float zoom_factor = 0.1;
float left_x = -512;
float right_x = 512;
float bottom_y = -384;
float top_y = 384;

Player player;
Game game;
UDPClient ucGame;
/////////////////////////////////
/////////////////////////////////

ALuint Buffers[NUM_BUFFERS];
ALuint Sources[NUM_SOURCES];

// Position of the source sounds.
ALfloat SourcesPos[NUM_SOURCES][3];

// Velocity of the source sounds.
ALfloat SourcesVel[NUM_SOURCES][3];


// Position of the listener.
ALfloat ListenerPos[] = { 0.0, 0.0, 0.0 };

// Velocity of the listener.
ALfloat ListenerVel[] = { 0.0, 0.0, 0.0 };

// Orientation of the listener. (first 3 elements are "at", second 3 are "up")
ALfloat ListenerOri[] = { 0.0, 0.0, -1.0, 0.0, 1.0, 0.0 };

/////////////////////////////////////
/////////////////////////////////////

typedef struct _js{
	float xAxis;
	float yAxis;
	float zAngle;
}jsState;
jsState js;
//////////////////////////////////////////////////////////////
//  GAME FUNCTIONS											//
//////////////////////////////////////////////////////////////
bool checkForDestruction(){
	cout<<game.team[player.getPlayerTeamID()].theShip.health<<endl;
	if (game.team[player.getPlayerTeamID()].theShip.health < 1){
		return true;
	}
	else
		return false;
}
void endGame(int winningteam){
	if (winningteam == player.getPlayerTeamID()){  //we won
		//do we won stuff
	}
	else {  // we lost
		//do we lost stuff

	}
	//wait for keystroke
	exit(0);
}
void stepShipMovement(){
	int tid = player.getPlayerTeamID();
	if (player.getPlayerPosition() == PILOT){
		Spacecraft *theShip = &game.team[tid].theShip;
		theShip->vPosition[0] += theShip->vVelocity[0]*game.dt;
		theShip->vPosition[1] += theShip->vVelocity[1]*game.dt;
		theShip->vPosition[2] += theShip->vVelocity[2]*game.dt;
	}
}
void gameIdle(int i){
	glutPostRedisplay();
	stepShipMovement();
	glutTimerFunc(10, gameIdle, 0);
}
//////////////////////////////////////////////////////////////
//  AUDIO FUNCTIONS											//
//////////////////////////////////////////////////////////////
ALboolean  LoadSoundData(){
    // Variables to load into.

    ALenum format;
    ALsizei size;
    ALvoid* data;
    ALsizei freq;
    ALboolean loop;

    // Load wav data into buffers.
    alGenBuffers(NUM_BUFFERS, Buffers);

    if (alGetError() != AL_NO_ERROR)
        return AL_FALSE;

    alutLoadWAVFile("audio\\background.wav", &format, &data, &size, &freq, &loop);
    alBufferData(Buffers[AMBIENT_NOISE], format, data, size, freq);
    alutUnloadWAV(format, data, size, freq);

    alutLoadWAVFile("audio\\UrbanDarkness19.wav", &format, &data, &size, &freq, &loop);
    alBufferData(Buffers[BACKGROUND_MUSIC], format, data, size, freq);
    alutUnloadWAV(format, data, size, freq);
	
    alutLoadWAVFile("audio\\LASER.wav", &format, &data, &size, &freq, &loop);
    alBufferData(Buffers[LASER], format, data, size, freq);
    alutUnloadWAV(format, data, size, freq);
	
    alutLoadWAVFile("audio\\EXPLODE.wav", &format, &data, &size, &freq, &loop);
    alBufferData(Buffers[EXPLOSION], format, data, size, freq);
    alutUnloadWAV(format, data, size, freq);

    // Bind buffers into audio sources.
    alGenSources(NUM_SOURCES, Sources);

    if (alGetError() != AL_NO_ERROR)
        return AL_FALSE;

    alSourcei (Sources[AMBIENT_NOISE], AL_BUFFER,   Buffers[AMBIENT_NOISE]);
    alSourcef (Sources[AMBIENT_NOISE], AL_PITCH,    1.0);
    alSourcef (Sources[AMBIENT_NOISE], AL_GAIN,     0.1);
    alSourcefv(Sources[AMBIENT_NOISE], AL_POSITION, SourcesPos[AMBIENT_NOISE]);
    alSourcefv(Sources[AMBIENT_NOISE], AL_VELOCITY, SourcesVel[AMBIENT_NOISE]);
    alSourcei (Sources[AMBIENT_NOISE], AL_LOOPING,  AL_TRUE);

    alSourcei (Sources[BACKGROUND_MUSIC], AL_BUFFER,   Buffers[BACKGROUND_MUSIC]);
    alSourcef (Sources[BACKGROUND_MUSIC], AL_PITCH,    1.0);
    alSourcef (Sources[BACKGROUND_MUSIC], AL_GAIN,     0.4);
    alSourcefv(Sources[BACKGROUND_MUSIC], AL_POSITION, SourcesPos[BACKGROUND_MUSIC]);
    alSourcefv(Sources[BACKGROUND_MUSIC], AL_VELOCITY, SourcesVel[BACKGROUND_MUSIC]);
    alSourcei (Sources[BACKGROUND_MUSIC], AL_LOOPING,  AL_TRUE);

    alSourcei (Sources[LASER], AL_BUFFER,   Buffers[LASER]);
    alSourcef (Sources[LASER], AL_PITCH,    1.0);
    alSourcef (Sources[LASER], AL_GAIN,     0.1);
    alSourcefv(Sources[LASER], AL_POSITION, SourcesPos[LASER]);
    alSourcefv(Sources[LASER], AL_VELOCITY, SourcesVel[LASER]);
    alSourcei (Sources[LASER], AL_LOOPING,  AL_FALSE);

    alSourcei (Sources[EXPLOSION], AL_BUFFER,   Buffers[EXPLOSION]);
    alSourcef (Sources[EXPLOSION], AL_PITCH,    1.0);
    alSourcef (Sources[EXPLOSION], AL_GAIN,     1.0);
    alSourcefv(Sources[EXPLOSION], AL_POSITION, SourcesPos[EXPLOSION]);
    alSourcefv(Sources[EXPLOSION], AL_VELOCITY, SourcesVel[EXPLOSION]);
    alSourcei (Sources[EXPLOSION], AL_LOOPING,  AL_FALSE);
    // Do another error check and return.

    if( alGetError() != AL_NO_ERROR){
		cout<<"Error code: "<<alGetError<<endl;
        return AL_FALSE;
	}

    return AL_TRUE;
}

void SetListenerValues()
{
    alListenerfv(AL_POSITION,    ListenerPos);
    alListenerfv(AL_VELOCITY,    ListenerVel);
    alListenerfv(AL_ORIENTATION, ListenerOri);
}

void KillALData()
{
    alDeleteBuffers(NUM_BUFFERS, &Buffers[0]);
    alDeleteSources(NUM_SOURCES, &Sources[0]);
    alutExit();
}
bool initializeSound(){

    // Initialize OpenAL and clear the error bit.
    alutInit(0, NULL);
    alGetError();
    // Load the wav data.
    if (LoadSoundData() == AL_FALSE)
        return false;

    SetListenerValues();

    // Setup an exit procedure.
    atexit(KillALData);

	if(game.backgroundmusicon) 
		alSourcePlay(Sources[BACKGROUND_MUSIC]);
	if(game.soundeffectson) 
		alSourcePlay(Sources[AMBIENT_NOISE]);

	return true;
}
//////////////////////////////////////////////////////////////
//  COMM FUNCTIONS											//
//////////////////////////////////////////////////////////////
void commLoop(int i){
	int tid = player.getPlayerTeamID();
	Spacecraft* myShip = &game.team[tid].theShip;
	char *msg;
	MessageHandler mh;
	//if we are the pilot we need to send the server
	// our orientation and position every time
	if (player.getPlayerPosition() == PILOT){
		msg = mh.createOPMessage(	player.getClientID(),
									player.getPlayerTeamID(),
									myShip->mOrientation, 
									myShip->vPosition);
		ucGame.sendtoserver(msg);
	}
	//we need to send the server state changes
	//and if we have fired only when they happen
	if (myShip->laser.isbeingfired){
		msg = mh.createSCMessage(player.getClientID(),player.getPlayerTeamID(),0);
		cout<<"sending fire to server"<<endl;
		ucGame.sendtoserver(msg);
	}
	if (detecthit){
		msg = mh.createSCMessage(player.getClientID(),player.getPlayerTeamID(),1);
		cout<<"sending hit to server"<<endl;
		ucGame.sendtoserver(msg);
		detecthit = false;
	}
	if (weLost) {
		msg = mh.createEndGameMessage(player.getClientID(),player.getPlayerTeamID(),1);
		cout<<"sending lost to server"<<endl;
		ucGame.sendtoserver(msg);
	}
	glutTimerFunc(5, commLoop, 0);
}

DWORD WINAPI CommReceiverThread(void* n){ 
	int tid = player.getPlayerTeamID();
	float *oandp;
	int state;
	Message m;
	MessageHandler mh;
	int type, senderid, teamid;

	while (!gameDone){
		if(ucGame.receivefromserver()){
			mh.parseMessage(ucGame.buffer, m);
			type = m.getType();
			senderid = m.getClientID();
			teamid = m.getPacketID();
			switch (type){
			case 6:		//position/orientation
				oandp = mh.parseOrientationAndPosition(m.getTheData());
				game.team[teamid].theShip.mOrientation[0][0] = oandp[0];
				game.team[teamid].theShip.mOrientation[0][1] = oandp[1];
				game.team[teamid].theShip.mOrientation[0][2] = oandp[2];
				game.team[teamid].theShip.mOrientation[1][0] = oandp[3];
				game.team[teamid].theShip.mOrientation[1][1] = oandp[4];
				game.team[teamid].theShip.mOrientation[1][2] = oandp[5];
				game.team[teamid].theShip.mOrientation[2][0] = oandp[6];
				game.team[teamid].theShip.mOrientation[2][1] = oandp[7];
				game.team[teamid].theShip.mOrientation[2][2] = oandp[8];
				
				game.team[teamid].theShip.vPosition[0] = oandp[9];
				game.team[teamid].theShip.vPosition[1] = oandp[10];
				game.team[teamid].theShip.vPosition[2] = oandp[11];
				break;
			case 7:		
				state = mh.parseState(m.getTheData());
				switch (state){
				case 0:		//weapon fire from enemy
					game.team[teamid].theShip.laser.isbeingfired = true;
					break;
				case 1:		//enemy fire hit me
					//cout<<"got a hit from the server"<<endl;
					alSourcePlay(Sources[EXPLOSION]);
					game.team[player.getPlayerTeamID()].theShip.health -= 10;
					if(checkForDestruction()) {
						weLost = true;
						alSourcePlay(Sources[EXPLOSION]);
					}
					break;
				default:
					break;
				}
				break;
			case 8:
				//cout<<"got an end game message from the server"<<endl;
				gameDone = true;
				if (player.getPlayerTeamID() == teamid){ //we lost
					game.endgame(teamid, true);
				}
				else {									//we won
					game.endgame(teamid, false);
				}
				break;
			default:
				break;
			}
		}
	}
	return 0;
}
//////////////////////////////////////////////////////////////
//  GLUT REQUIRED FUNCTIONS									//
//////////////////////////////////////////////////////////////
void windowReshape(int w, int h){
    glViewport(0, 0, w, h);
	/*
		this will only be used if we allow
		glutFullScreen() to be disabled
	*/
	left_x = -((float)w/2)/1000;
	right_x = ((float)w/2)/1000;
	bottom_y = -((float)h/2)/1000;
	top_y = ((float)h/2)/1000;
}
void setFrustum(){
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
	/*glFrustum(	left_x/zoom, right_x/zoom,
				bottom_y/zoom, top_y/zoom, 
				nnear, nfar  );//*/
	glFrustum(-0.0512/zoom, 0.0512/zoom, -0.0384/zoom, 0.0384/zoom, 0.1, 1E6);
}

void renderScene(){
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
	if (!gameDone){
		game.renderGame(player.getPlayerTeamID(),player.getPlayerPosition());
		setFrustum();
	}
	else {
		game.endgame(player.getPlayerTeamID(), weLost);
	}

	glutSwapBuffers();
}

void joystickListener(int i){
	int tid = player.getPlayerTeamID();
	Spacecraft *ourShip = &game.team[tid].theShip;
	glutForceJoystickFunc();
	float deadzone = 0.005;
	float r, p, y;
	r = js.xAxis;
	p = js.yAxis;
	y = js.zAngle;
	if (r > deadzone) {
		ourShip->roll -= r;
		ourShip->r_right = true;
	}
	if (r < -deadzone) {
		ourShip->roll -= r;
		ourShip->r_left = true;
	}
	if (p > deadzone) {
		ourShip->pitch += p;
		ourShip->p_up = true;
	}
	if (p < -deadzone){
		ourShip->pitch += p;
		ourShip->p_down = true;
	}
	if (y > deadzone) {
		ourShip->yaw += y;
		ourShip->y_right = true;
	}
	if (y < -deadzone){
		ourShip->yaw += y;
		ourShip->y_left = true;
	}

	if (ourShip->roll < deadzone && ourShip->roll > -deadzone) ourShip->roll = 0;
	if (ourShip->pitch < deadzone && ourShip->pitch > -deadzone) ourShip->pitch = 0;
	if (ourShip->yaw < deadzone && ourShip->yaw > -deadzone) ourShip->yaw = 0;

	glutPostRedisplay();
	glutTimerFunc(66, joystickListener, 0);
}
void initializeGameBoard(){
	int players = 4;
	int teams = 2;
	int arena = 1;
	char name[] = "Test Game";
	int teamID = player.getPlayerTeamID();
	game.InitializeNewGame(teamID, teams, players, arena, name);
	
	js.xAxis = 0.0;
	js.yAxis = 0.0;
	js.zAngle = 0.0;
}
void initialGameSettings(){
	/////////////////
	//opengl settings
	/////////////////

	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);
	glCullFace(GL_BACK);
	//texture enabled
	glEnable(GL_TEXTURE_2D);
	//set texture mode
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
	//fast texturing
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
	//mipmap enabled
	glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST_MIPMAP_NEAREST);
	//line antialiasing setup
	//glEnable(GL_BLEND);
	//glEnable(GL_POINT_SMOOTH);

	//uncomment the following to turn on transparency
	//glEnable(GL_LINE_SMOOTH);
	//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);//*/

	glutFullScreen();
	setFrustum();
	
	/////////////////////////////////////////////////
	//setup the game according to the game settings
	//from the server
	/////////////////////////////////////////////////
	//setup all players
	cout<<"we are player "<<player.getClientID()<<", in position "<<player.getPlayerPosition();
	cout<<" on team "<<player.getPlayerTeamID();
	//setup the ships
	initializeGameBoard();

	//start the listener loop for the joystick
	//joystickListener(0);
	gameIdle(0);
	commLoop(0);
	CreateThread(NULL, 0, CommReceiverThread,  0, 0, 0);
	initializeSound();

}
void startGame(){
	//set up glut and call main game loop
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	glutInitWindowSize(800,600);
	glutInitWindowPosition(200,30);
    glutCreateWindow("A Space Game v1.0");
    glutReshapeFunc(windowReshape);
    glutDisplayFunc(renderScene);
    glutKeyboardFunc(keyboardHandler);
	glutSpecialFunc(specialkeyHandler);
    glutMouseFunc(mouseButton);
    glutMotionFunc(mouseMotion);
	glutJoystickFunc(joystickHandler, 0);
    initialGameSettings();
    glutMainLoop();
}

void closeGame(){
	//tell the server we are leaving the game
	char *msg;	
	MessageHandler mh;
	msg = mh.createGameExitMessage(player.getClientID(), player.getPlayerTeamID(), player.getPlayerPosition()-1);
	ucGame.sendtoserver(msg);
	//wait for the server to reply
	/*
	ucGame.receivefromserver();
	*/
	exit(0);
}

//////////////////////////////////////////////////////////////////////
//  MAIN                                                      ////////
//////////////////////////////////////////////////////////////////////
int main(int argc, char **argv) {
	/*
		set parameters from those passed in 
	*/
	char msg[MAX_MSG_LENGTH];
	char ipAddress[16];
	int gameport;
	int clientid;
	int playerteam;
	int position;
	if (argc == 4){ //started from command line
		ZeroMemory(ipAddress, 16);
		strcpy(ipAddress, argv[1]);
		gameport = atoi(argv[2]);
		player.setClientID(atoi(argv[3]));
	}
	if (argc == 3){ //started from client
		ZeroMemory(ipAddress, 16);
		strcpy(ipAddress, argv[0]);
		gameport = atoi(argv[1]);
		player.setClientID(atoi(argv[2]));
		player.setPlayerPosition(1);
	}
	else {	//started from IDE or without the proper # args (used for testing)
		ZeroMemory(ipAddress, 16);
		cout<<"Enter the server's IP Address>";
		cin>>ipAddress;
		cout<<"Enter the game port>";
		cin>>gameport;
		cout<<"Enter a client ID>";
		cin>>clientid;
		player.setClientID(clientid);
	}
	ucGame.startClient(ipAddress, gameport);

	//send the 'game server' a message that we are here
	sprintf(msg, "4/%d/0/0", player.getClientID());
	ucGame.sendtoserver(msg);
	//wait for the list of teams and positions
	if (ucGame.receivefromserver()){
		cout<<endl<<"Please select from the following:"<<endl;
		cout<<ucGame.buffer<<endl<<endl;
		cout<<"Please enter the team you want to join>";
		cin>>playerteam;
		cout<<"Please enter the position you want>";
		cin>>position;
		player.setPlayerTeamID(playerteam-1);
		player.setPlayerPosition(position);
	}
	else {
		cout<<"Server unavailable"<<endl;
		cout<<"Press any key to exit..."<<endl;
		cin>>position;
		exit(0);
	}

	//we need to tell the server...team and position
	sprintf(msg, "5/%d/0/%d %d", player.getClientID(), playerteam-1, position-1);
	ucGame.sendtoserver(msg);
	//wait for start
	//ucGame.receivefromserver();
	cout<<"You are in POSITION: "<<position<<" on TEAM: "<<playerteam<<endl;
	startGame();
	return 0;
}

//////////////////////////////////////////////////////////////////////
//  END MAIN                                                  ////////
//////////////////////////////////////////////////////////////////////


/*////////////////////////////////////////////////////////////////////
	Begin Input funcitons
	Keyboard, mouse, and joystick functions
	defined here.  These are needed by glut
		keyboardHandler()
		specialkeyHandler()
		mouseMotion()
		mouseButton()
		joystickHandler()
////////////////////////////////////////////////////////////////////*/

void keyboardHandler(unsigned char key, int x, int y){
	int tid = player.getPlayerTeamID();
	int position = player.getPlayerPosition();
	int modifier = glutGetModifiers();
	Spacecraft *theShip;
	theShip = &game.team[tid].theShip;
	if(!gameDone){
		if (position == PILOT) {
			switch(key) {
			case 'a':
				break;
			case 'A':		//all stop
				theShip->roll  = 0;
				theShip->yaw   = 0;
				theShip->pitch = 0;
				theShip->vVelocity[0] = 0;
				theShip->vVelocity[1] = 0;
				theShip->vVelocity[2] = 0;
				break;
			case 'b':
				theShip->display.decrease_hud_intensity();
				break;
			case 'B':
				theShip->display.increase_hud_intensity();
				break;
			case 'c':
				break;
			case 'C':
				break;
			case 'd':
				break;
			case 'D':
				break;
			case 'e':
				if(game.soundeffectson) 
					alSourcePlay(Sources[EXPLOSION]);
				break;
			case 'E':
				break;
			case 'f':
				break;
			case 'F':
				break;
			case 'g':
				break;
			case 'G':
				break;
			case 'h':
				break;
			case 'H':
				break;
			case 'i':
				break;
			case 'I':
				break;
			case 'j':
				break;
			case 'J':
				break;
			case 'k':
				break;
			case 'K':
				break;
			case 'l':
				break;
			case 'L':
				break;
			case 'm':
				break;
			case 'M':
				break;
			case 'n':
				break;
			case 'N':
				break;
			case 'o':
				break;
			case 'O':
				break;
			case 'p':
				break;
			case 'P':
				break;
			case 'q':
				break;
			case 'Q':
				break;
			case 'r':
				break;
			case 'R':
				break;
			case 's':
				break;
			case 'S':
				break;
			case 't':
				break;
			case 'T':
				break;
			case 'u':
				break;
			case 'U':
				break;
			case 'v':
				break;
			case 'w':
				break;
			case 'W':
				break;
			case 'x':
				break;
			case 'X':
				break;
			case 'y':
				break;
			case 'Y':
				break;
			case 'z':
				break;
			case 'Z':
				break;
			case ' ':	//weapon fire temp
				theShip->laser.isbeingfired = true;
				if (game.soundeffectson)
					alSourcePlay(Sources[LASER]);
				if (game.checkforweaponstrike(player.getPlayerTeamID()) > 0){
					//cout<<"Keyboard handler message: hit a ship"<<endl;
					alSourcePlay(Sources[EXPLOSION]);
					detecthit = true;
				}
				break;
			case '-':	//negative velocity change
				theShip->vVelocity[0] -= theShip->mCamera[0][0];
				theShip->vVelocity[1] -= theShip->mCamera[1][0];
				theShip->vVelocity[2] -= theShip->mCamera[2][0];
				break;
			case '+':	//positive velocity change
				theShip->vVelocity[0] += theShip->mCamera[0][0];
				theShip->vVelocity[1] += theShip->mCamera[1][0];
				theShip->vVelocity[2] += theShip->mCamera[2][0];
				break;
			case '<':
				break;
			case '>':
				break;
			case '[':
				break;
			case ']':
				break;
			case '{':
				break;
			case '}':
				break;
			case ',':
				theShip->yaw += 0.1;
				theShip->y_left = true;
				break;
			case '.':
				theShip->yaw -= 0.1;
				theShip->y_right = true;
				break;
			case 27:
				closeGame();
				break;
			default:
				break;
			}
		}
		else if (position == GUNNER1) {
			switch(key) {
			case 'a':
				break;
			case 'A':
				break;
			case 'b':
				break;
			case 'B':
				break;
			case 'c':
				break;
			case 'C':
				break;
			case 'd':
				break;
			case 'D':
				break;
			case 'e':
				break;
			case 'E':
				break;
			case 'f':
				break;
			case 'F':
				break;
			case 'g':
				break;
			case 'G':
				break;
			case 'h':
				break;
			case 'H':
				break;
			case 'i':
				break;
			case 'I':
				break;
			case 'j':
				break;
			case 'J':
				break;
			case 'k':
				break;
			case 'K':
				break;
			case 'l':
				break;
			case 'L':
				break;
			case 'm':
				break;
			case 'M':
				break;
			case 'n':
				break;
			case 'N':
				break;
			case 'o':
				break;
			case 'O':
				break;
			case 'p':
				break;
			case 'P':
				break;
			case 'q':
				break;
			case 'Q':
				break;
			case 'r':
				break;
			case 'R':
				break;
			case 's':
				break;
			case 'S':
				break;
			case 't':
				break;
			case 'T':
				break;
			case 'u':
				break;
			case 'U':
				break;
			case 'v':
				break;
			case 'w':
				break;
			case 'W':
				break;
			case 'x':
				break;
			case 'X':
				break;
			case 'y':
				break;
			case 'Y':
				break;
			case 'z':
				zoom += 0.1;
				break;
			case 'Z':
				zoom -= 0.1;
				break;
			case ' ':
				break;
			case '-':
				break;
			case '+':
				break;
			case '<':
				break;
			case '>':
				break;
			case '[':
				break;
			case ']':
				break;
			case '{':
				break;
			case '}':
				break;
			case ',':
				break;
			case '.':
				break;
			case 27:
				closeGame();
				break;
			default:
				break;
			}
		}
		else {
			if (key == 27) closeGame();
		}
	}
	else {
		if (key == 27) closeGame();
	}
	glutPostRedisplay();
}
void specialkeyHandler(int key, int x, int y){
	int tid = player.getPlayerTeamID();
	int modifier = glutGetModifiers();
	Spacecraft *theShip;
	theShip = &game.team[tid].theShip;	
	if(!gameDone){
		switch (player.getPlayerPosition()){
		case PILOT:
			switch(key) {
			case GLUT_KEY_LEFT:
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else {
					game.team[tid].theShip.roll -= 0.1;
					game.team[tid].theShip.r_left = true;
				}
				break;
			case GLUT_KEY_RIGHT:		
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else {
					game.team[tid].theShip.roll += 0.1;
					game.team[tid].theShip.r_right = true;
				}
				break;
			case GLUT_KEY_UP:		
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else {
					game.team[tid].theShip.pitch += 0.1;
					game.team[tid].theShip.p_down = true;
				}
				break;
			case GLUT_KEY_DOWN:		
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else {
					game.team[tid].theShip.pitch -= 0.1;
					game.team[tid].theShip.p_up = true;
				}
				break;
			case GLUT_KEY_F1:
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else{
				}
				break;
			case GLUT_KEY_F2:
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else{
					game.team[tid].theShip.insideShip = !game.team[tid].theShip.insideShip;
				}
				break;
			case GLUT_KEY_F3:
				if (modifier == GLUT_ACTIVE_CTRL){
					game.arena.starson = !game.arena.starson;
				}
				else{
				}
				break;
			case GLUT_KEY_F4:
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else{
				}
				break;
			case GLUT_KEY_F5:
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else{
				}
				break;
			case GLUT_KEY_F6:
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else{
				}
				break;
			case GLUT_KEY_F7:
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else{
				}
				break;
			case GLUT_KEY_F8:
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else{
				}
				break;
			case GLUT_KEY_F9:
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else{
					game.backgroundmusicon = !game.backgroundmusicon;
					if (game.backgroundmusicon)
						alSourcePlay(Sources[BACKGROUND_MUSIC]);
					else 
						alSourcePause(Sources[BACKGROUND_MUSIC]);
				}
				break;
			case GLUT_KEY_F10:
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else{
					game.soundeffectson = !game.soundeffectson;
					if(game.soundeffectson) 
						alSourcePlay(Sources[AMBIENT_NOISE]);
					else 
						alSourcePause(Sources[AMBIENT_NOISE]);
				}
				break;
			case GLUT_KEY_F11:
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else{
				}
				break;
			case GLUT_KEY_F12:
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else{
				}
				break;
			default:
				break;
			}
			break;
		case GUNNER1:
			switch(key) {
			case GLUT_KEY_LEFT:
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else {
				}
				break;
			case GLUT_KEY_RIGHT:		
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else {
				}
				break;
			case GLUT_KEY_UP:		
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else {
				}
				break;
			case GLUT_KEY_DOWN:		
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else {
				}
				break;
			case GLUT_KEY_F1:
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else{
				}
				break;
			case GLUT_KEY_F2:
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else{
					game.team[tid].theShip.insideShip = !game.team[tid].theShip.insideShip;
				}
				break;
			case GLUT_KEY_F3:
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else{
				}
				break;
			case GLUT_KEY_F4:
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else{
				}
				break;
			case GLUT_KEY_F5:
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else{
				}
				break;
			case GLUT_KEY_F6:
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else{
				}
				break;
			case GLUT_KEY_F7:
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else{
				}
				break;
			case GLUT_KEY_F8:
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else{
				}
				break;
			case GLUT_KEY_F9:
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else{
				}
				break;
			case GLUT_KEY_F10:
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else{
				}
				break;
			case GLUT_KEY_F11:
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else{
				}
				break;
			case GLUT_KEY_F12:
				if (modifier == GLUT_ACTIVE_CTRL){
				}
				else{
				}
				break;
			default:
				break;
			}
			break;
		default:
			break;
		}
	}
    glutPostRedisplay();
}
void mouseButton(int button, int state, int x, int y){
	
}

void mouseMotion(int x, int y){

}

void joystickHandler(GLuint buttonMask, int x, int y, int z){
	int tid = player.getPlayerTeamID();
	Spacecraft *theShip;
	theShip = &game.team[tid].theShip;
	js.xAxis = (float)x/100000;
	js.yAxis = (float)y/100000;
	js.zAngle = (float)z/100000;
	if(!gameDone){
		switch (player.getPlayerPosition()){
		case PILOT:
			switch(buttonMask){
			case 1:
				//Button 1 (trigger)
				break;
			case 2:
				//Button 2 
				break;
			case 4:
				//Button 3
				break;
			case 8:
				//Button 4
				theShip->display.decrease_hud_intensity();
				break;
			case 16:
				//Button 5
				theShip->display.POSon = !theShip->display.POSon;
				theShip->display.RPYon = !theShip->display.RPYon;
				theShip->display.DIRon = !theShip->display.DIRon;
				break;
			case 32:
				//Button 6
				theShip->display.increase_hud_intensity();
				break;
			case 64:
				//Button 7
				break;
			case 128:
				//Button 8
				break;
			case 256:
				//Button 9
				break;
			case 512:
				//Button 10
				theShip->roll = 0;
				theShip->pitch = 0;
				theShip->yaw = 0;
				break;
			default:
				break;
			}
			break;
		case GUNNER1:
			switch(buttonMask){
			case 1:
				//Button 1 (trigger)
				break;
			case 2:
				//Button 2 
				break;
			case 4:
				//Button 3
				break;
			case 8:
				//Button 4
				break;
			case 16:
				//Button 5
				break;
			case 32:
				//Button 6
				break;
			case 64:
				//Button 7
				break;
			case 128:
				//Button 8
				break;
			case 256:
				//Button 9
				break;
			case 512:
				//Button 10
				break;
			default:
				break;
			}
			break;
		default:
			break;
		}
	}
}
/////////////////////////////////////////////////////
//   End input functions                    /////////
///////////////////////////////////////////////////// 
