// This code is licensed under the MIKE IS AWESOME license - Which means
// if you are to use any of this code, you have to put in huge text
// "MIKE IS AWESOME" in a commonly used part of your program (such as the
// introduction menu) (and the MIKE in this example, is obviously referring
// to the original creator, who is the only person free to ignore this license)

#include "main.h"
SDL_Surface *scren;
int counter = 0;
GLuint antigravshiptexture;
GLuint gravshiptexture;
GLuint antigravbullettexture;
GLuint gravbullettexture;
GLuint antigravplanettexture;
GLuint gravplanettexture;
TTF_Font * font;
Mix_Chunk *ts1;
Mix_Chunk *ts2;
Mix_Chunk *ss;
Mix_Chunk *hs;
Mix_Chunk *es;



int main (int argc, char* argv[]) {
	int audio_rate = 22050;
	Uint16 audio_format = AUDIO_S16;
	int audio_channels = 2;
	int audio_buffers = 4096;
		
	if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) != 0) {
		printf ("Unable to initialize SDL: %s\n", SDL_GetError());
		return 1;
	}
		
	if (Mix_OpenAudio(audio_rate, audio_format, audio_channels, audio_buffers)) {
		printf("Unable to open audio\n");
		exit(1);
	}

	if (!(ts1 = Mix_LoadWAV("thrust1.wav"))) {
		printf("like whatever..\n");
		exit(2);
	}
	if (!(ts2 = Mix_LoadWAV("thrust2.wav"))) {
		printf("like whatever..\n");
		exit(2);
	}
	if (!(ss = Mix_LoadWAV("shoot.wav"))) {
		printf("like whatever..\n");
		exit(2);
	}
	if (!(hs = Mix_LoadWAV("hit.wav"))) {
		printf("like whatever..\n");
		exit(2);
	}
	if (!(es = Mix_LoadWAV("explode.wav"))) {
		printf("like whatever..\n");
		exit(2);
	}
	
	setSounds(ts1, ts2, ss, hs, es);

	if(TTF_Init()==-1) {
		printf("TTF_Init: %s\n", TTF_GetError());
		exit(2);
	}
	
	font=TTF_OpenFont("font.ttf", 32);
	if(!font) {
		printf("TTF_OpenFont: %s\n", TTF_GetError());
    		exit(2);
	}

	
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); //new

	scren = SDL_SetVideoMode(SCREENWIDTH, SCREENHEIGHT, SCREENBPP, SDL_OPENGL);

	SDL_WM_SetCaption("Mike Is Awesome", "Mike Rules!");

	setupGL();

	return 0;

}

void setupGL() {
	glEnable(GL_TEXTURE_2D);

	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

	glViewport(0, 0, SCREENWIDTH, SCREENHEIGHT);

	glClear(GL_COLOR_BUFFER_BIT);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	glOrtho(0, SCREENWIDTH, SCREENHEIGHT, 0, -1.0f, 1.0f);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	startGame();
}

void startGame() {
	srand(SDL_GetTicks());
	
	GLuint particleTexture;
	
	particle particles[NUMPARTICLES];
	
	imageToTexture("particle.png", &particleTexture);
	
	vector<spaceship> spaceshiplist;
	for (int i = 0; i < NUMSHIPS; i++) {
		spaceshiplist.push_back(*(new spaceship));
	}
	vector<planet*> planetlist;
	for (int i = 0; i < 1000; i++) {
		planetlist.push_back(new planet);
		if (i > MAXPLANETS) {
			planetlist[i]->mass = 0;
			planetlist[i]->calculateNewSize();
		}
	}
	screen scr;
	
	spaceshiplist[0].setkeys(SDLK_UP, SDLK_DOWN, SDLK_LEFT, SDLK_RIGHT, SDLK_RETURN);
	spaceshiplist[0].setgravity(GRAVITY);
	spaceshiplist[1].setkeys(SDLK_w, SDLK_s, SDLK_a, SDLK_d, SDLK_q);
	spaceshiplist[1].setgravity(ANTIGRAVITY);
	
	setupTextures();
	
	for (int i = 0; i < NUMSHIPS; i++) {
		spaceshiplist[i].setTextures(gravshiptexture, 
					antigravshiptexture, 
					gravbullettexture, 
					antigravbullettexture);
	}
	for (unsigned int i = 0; i < planetlist.size(); i++) {
		planetlist[i]->setTexture(gravplanettexture, 
					  antigravplanettexture);
	}

	// Enable alpha support for our png images.
	glColor4f(1.0f,1.0f,1.0f,1.0f);
	glEnable(GL_TEXTURE_2D);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
	glAlphaFunc(GL_GREATER,0.1f);

	while (1) {
		process_events(spaceshiplist);
		for (int i = 0; i < NUMSHIPS; i++) {
			if (spaceshiplist[i].AIenabled == true) {
				AImove(spaceshiplist[i], spaceshiplist[i==0?1:0], planetlist, &scr);
			}
			spaceshiplist[i].move(planetlist, spaceshiplist, &scr);
		}
		for (unsigned int i = 0; i < planetlist.size(); i++) {
			//planetlist[i]->move(planetlist, &scr);
		}
		for (int i = 0; i < NUMPARTICLES; i++) {
			particles[i].move(planetlist, &scr);
		}
		draw(spaceshiplist, planetlist, particles, particleTexture, &scr);
	}
}

int imageToTexture(SDL_Surface *surface, GLuint *texture) {
	GLenum texture_format;
	GLint nOfColors;

	//Check that the image's width is a power of 2
	if ((surface->w & (surface->w - 1)) != 0) {
		printf("warning: image.bmp's width is not a power of 2\n");
	}
	//also check if the height is a power of 2
	if ((surface->h & (surface->h -1)) != 0) {
		printf("warning: image.bmp's height is not a power of 2\n");
	}

	//get the number of channel in the SDL surface
	nOfColors = surface->format->BytesPerPixel;
	if (nOfColors == 4) { //contains an alpha channel
		if (surface->format->Rmask == 0x000000ff) {
			texture_format = GL_RGBA;
		} else {
			texture_format = GL_BGRA;
		}
	} else if (nOfColors == 3) { //no alpha channel
		if (surface->format->Rmask == 0x000000ff)
			texture_format = GL_RGB;
		else
			texture_format = GL_BGR;
	} else {
		printf("warning: the image is not truecolor.. this will probably break\n");
		// This error should be checked	
		return -1;
	}
	// Have OpenGL generate a texture object handle for us.
	glGenTextures(1, texture);
	//Bind the texture object
	glBindTexture(GL_TEXTURE_2D, *texture);
	
	// Set the texture's stretching properties
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	// Edit the texture object's image data using the information SDL_Surface gives us
	glTexImage2D(GL_TEXTURE_2D, 0, nOfColors, surface->w, surface->h, 0, texture_format, GL_UNSIGNED_BYTE, surface->pixels);

	return 1;
}

int imageToTexture(const char *path, GLuint *texture) {
	SDL_Surface *surface;

	if ((surface = IMG_Load (path))) {	
		imageToTexture(surface, texture);
	} else {
		printf("SDL could not load %s: %s\n", path,  SDL_GetError());
		SDL_Quit();
		return -1;
	}
	// Free the SDL_Surface only if it was successfully created
	if (surface) {
		SDL_FreeSurface(surface);
	}

	return 1;
}

void process_events(vector<spaceship> &spaceshiplist) {
	SDL_Event event;

	while( SDL_PollEvent( &event ) ) {
		switch( event.type ) {
			case SDL_KEYDOWN:
				handle_key_down(&event.key.keysym, spaceshiplist);
				break;
			case SDL_KEYUP:
				handle_key_up(&event.key.keysym, spaceshiplist);
				break;
			case SDL_QUIT:
				quit_program(0);
				break;
		}
	}
}

void Screendump(char *destFile, short W, short H) {
	FILE   *out = fopen(destFile, "w");
	char   pixel_data[3*W*H];
	short  TGAhead[] = {0, 2, 0, 0, 0, 0, W, H, 24};
	glReadBuffer(GL_FRONT);
	glReadPixels(0, 0, W, H, GL_BGR, GL_UNSIGNED_BYTE, pixel_data);
	fwrite(&TGAhead, sizeof(TGAhead), 1, out);
	fwrite(pixel_data, 3*W*H, 1, out);
	fclose(out); 
}


void draw(vector<spaceship> &spaceshiplist, vector<planet*> &planetlist, particle particles[], GLuint particleTexture, screen *scr) {
		/* Clear the color and depth buffers. */
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

	/* We don't want to modify the projection matrix. */
	glMatrixMode( GL_MODELVIEW );
	glLoadIdentity( );
		
	for (int i = 0; i < NUMSHIPS; i++) {
		if (spaceshiplist[i].gravity == GRAVITY) {
			spaceshiplist[i].draw(gravshiptexture);
		} else {
			spaceshiplist[i].draw(antigravshiptexture);
		}
	}
	for (unsigned int i = 0; i < planetlist.size(); i++) {
		planetlist[i]->draw();
	}
	
	for (int i = 0; i < NUMPARTICLES; i++) {
		particles[i].draw(particleTexture);
	}

	for (int i = 0; i < NUMSHIPS; i++) {
		SDL_Color color = {0,0,0,255};
		GLuint texture;
		SDL_Surface *newsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, 64, 64, 24, 
				0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
		float x = (i == 1)?SCREENWIDTH-30:30;
		float y = 30;
		if (spaceshiplist[i].gravity == GRAVITY)
			color.g = 255;
		else
			color.b = 255;
		SDL_Surface *text_surface;
		char score[20];
		sprintf(score, "%d", spaceshiplist[i].score);
		if(!(text_surface=TTF_RenderText_Blended(font, score ,color))) {
			printf("error again :(\n");
			exit(2);
		} else {
			SDL_BlitSurface(text_surface, NULL, newsurf, NULL);
			SDL_Flip(newsurf);
			imageToTexture(newsurf, &texture);
			SDL_FreeSurface(text_surface);
			SDL_FreeSurface(newsurf);
			
			glPushMatrix(); //begin drawing the text

			/* Move. */
			glTranslatef(x, y, 0.0); 

			glBindTexture(GL_TEXTURE_2D, texture);
			glEnable(GL_BLEND);
			glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); 
			glBegin(GL_QUADS);
				glColor4f(1, 1, 1, 1);
				glTexCoord2i(0, 0);
				glVertex3f(-20, -20, 0);

				glTexCoord2i(1, 0);
				glVertex3f(20, -20, 0);

				glTexCoord2i(1, 1);
				glVertex3f(20, 20, 0);

				glTexCoord2i(0, 1);
				glVertex3f(-20, 20, 0);
			glEnd();
			glPopMatrix();
			glDeleteTextures( 1, &texture );
		}
	}
	
	SDL_GL_SwapBuffers();

// 	char filename[200];
// 	sprintf(filename, "screenshots/screenshots %d .tga", counter);
// 	printf("capturing %s\n", filename);
// 	Screendump(filename, SCREENWIDTH, SCREENHEIGHT);
// 	counter++;
}

void handle_key_up(SDL_keysym *keysym, vector<spaceship> &spaceshiplist) {
	for (int i = 0; i < NUMSHIPS; i++) {
		if (keysym->sym == spaceshiplist[i].getLeftKey() && 
				  spaceshiplist[i].getRotFreq() == -ROTFREQ) {
			spaceshiplist[i].AIenabled = false;
			spaceshiplist[i].setRotFreq(0);
		}
		if (keysym->sym == spaceshiplist[i].getRightKey() && 
				  spaceshiplist[i].getRotFreq() == ROTFREQ) {
			spaceshiplist[i].AIenabled = false;
			spaceshiplist[i].setRotFreq(0);
		}
		if (keysym->sym == spaceshiplist[i].getUpKey() && 
				  spaceshiplist[i].getAcceleration() == ACCELERATION) {
			spaceshiplist[i].AIenabled = false;
			spaceshiplist[i].setAcceleration(0);
	//		if (thrustsoundchannel >= 0) {
	//			Mix_HaltChannel(thrustsoundchannel);
	//			thrustsoundchannel = -1;
	//		}
		}
		if (keysym->sym == spaceshiplist[i].getDownKey() && 
				  spaceshiplist[i].getAcceleration() == -ACCELERATION) {
			spaceshiplist[i].AIenabled = false;
			spaceshiplist[i].setAcceleration(0);
	//		if (thrustsoundchannel >= 0) {
	//			Mix_HaltChannel(thrustsoundchannel);
	//			thrustsoundchannel = -1;
	//		}
		}
	}
}

void handle_key_down(SDL_keysym *keysym, vector<spaceship> &spaceshiplist) {
	for (int i = 0; i < NUMSHIPS; i++) {
		if (keysym->sym == SDLK_ESCAPE) {
			quit_program(0);
		}
		if (keysym->sym == spaceshiplist[i].getLeftKey()) {
			spaceshiplist[i].AIenabled = false;
			spaceshiplist[i].setRotFreq(-ROTFREQ);
		}
		if (keysym->sym == spaceshiplist[i].getRightKey()) {
			spaceshiplist[i].AIenabled = false;
			spaceshiplist[i].setRotFreq(ROTFREQ);
		}
		if (keysym->sym == spaceshiplist[i].getDownKey()) {
			spaceshiplist[i].AIenabled = false;
	//		if (thrustsoundchannel < 0) {
	//			thrustsoundchannel = Mix_PlayChannel(-1, thrustsound, -1);
	//		}	
			spaceshiplist[i].setAcceleration(-ACCELERATION);
		}
		if (keysym->sym == spaceshiplist[i].getUpKey()) {
			spaceshiplist[i].AIenabled = false;
	//		if (thrustsoundchannel < 0) {
	//			thrustsoundchannel = Mix_PlayChannel(-1, thrustsound, -1);
	//		}
			spaceshiplist[i].setAcceleration(ACCELERATION);
		}
		if (keysym->sym == spaceshiplist[i].getShootKey()) {
			spaceshiplist[i].AIenabled = false;
			spaceshiplist[i].shoot();
		}
	}
}

void quit_program(int code) {
	SDL_Quit();
	exit(code);
}

void setupTextures() {
	imageToTexture("antigravship.png", &antigravshiptexture);
	imageToTexture("gravship.png", &gravshiptexture);
	imageToTexture("antigravbullet.png", &antigravbullettexture);
	imageToTexture("gravbullet.png", &gravbullettexture);
	imageToTexture("antigravplanet.png", &antigravplanettexture);
	imageToTexture("gravplanet.png", &gravplanettexture);
}
	

