#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include "SDL.h"
#include "vector.h"             // 2D Vector stuff used for screen coordinates
#include "draw.h"               // 2D Raster Graphics Library used for drawing
#include "blit.h"
#include "bullet.h"
#include "ship.h"               // Spaceship player class
#include "text.h"               // 2D Simple raster text output classes
#include "linklist.h"           // Used for enemy memory management
//#include "mouse.h"              // Mouse driver interface
#include "settings.h"
#include "game.h"               // Main game control
#include "bgfx.h"
using namespace std;

void game(byte_t *double_buffer, SDL_Surface *screen, Settings *sets){
	byte_t 
		RED=	SDL_MapRGB(screen->format,255,  0,  0),
		GREEN=	SDL_MapRGB(screen->format,  0,255,  0),
		BLUE=	SDL_MapRGB(screen->format,  0,  0,255),
		
		YELLOW=	SDL_MapRGB(screen->format,255,255,  0),
		MAGENTA=SDL_MapRGB(screen->format,255,  0,255),
		CYAN=	SDL_MapRGB(screen->format,  0,255,255),
		
		ORANGE=	SDL_MapRGB(screen->format,255,127,  0),
		PINK=	SDL_MapRGB(screen->format,255,  0,127),
		PURPLE=	SDL_MapRGB(screen->format,127,  0,255),
		POWDER=	SDL_MapRGB(screen->format,  0,127,255),
		MARINE=	SDL_MapRGB(screen->format,  0,255,127),
		LIME=	SDL_MapRGB(screen->format,127,255,  0),
		
		BLACK=	SDL_MapRGB(screen->format,  0,  0,  0),
		WHITE=	SDL_MapRGB(screen->format,255,255,255);
	SDL_Event event;
	Uint32 timer=SDL_GetTicks();
	Uint32 ticks=0;
	bool push=false, left=false, right=false, down=false, shoot=false;
	int shotclock=125;
	int frames=0;
	byte_t rockcolor=31;
        Line l1, l2, l3, l4, l5, l6;
	char charin=0;
	Ship s1;
	int invulnerable=0;
	LinkedList rocks;
	s1.score=0;
	int lastscore=0;
	int level=0;
	bool mouselook=sets->mouselook;
	Text pause("PAUSE",CENTER-Vector(12,5));
	Text levellabel("LEVEL", Vector(XMAX-80,5));
	Text disclaimer("THE BIG TRIANGLES ARE JUST DECORATION", Vector(XMAX/2-95,15));
	Text webad("WWW.EDLORD.COM", Vector(5,YMAX-15));
	Text scorelabel("SCORE:",Vector(XMAX/2-30,5));
	Text gameover("GAME OVER",Vector(XMAX/2-40,YMAX/2-20));
	Text pressanykey("PRESS ANY KEY",Vector(XMAX/2-60,YMAX/2));
	Vector scorepos(XMAX/2+5,5);
	Vector levelpos(XMAX-30,5);
	int turn=0;
	int lives=4;
	bool paused=false;
	Ship extra;
	//mousex();
	//SDL_Surface *tmpsfc=SDL_LoadBMP("bgfx.bmp");
	//SDL_Surface *bgfx=SDL_DisplayFormat(tmpsfc);
	//SDL_FreeSurface(tmpsfc);
	//	ofstream bgfxh;
	//	bgfxh.open("bgfx.h",ios::out | ios::binary);
	//	for(int j=0; j<YMAX; j++){
	//		for(int i=0; i<XMAX; i++){
	//			bgfxh<<int(((unsigned char*)(bgfx->pixels))[j*XMAX+i])<<", \n";
	//		}
	//	}
	//	bgfxh.close();
	int mousex=0,mousey=0;
	Vector mousepos(0,0);
	int mouseclick=0;
	SDL_GetRelativeMouseState(NULL,NULL);
	//leftclick();
	timer=SDL_GetTicks();
	for(double t=0; charin!='q'; t+=.002*ticks/5){ 
		if(rocks.cleared()){
			level++;
			invulnerable=2000;
			for (int i=0; i<level+4; i++)
				rocks.add(Circle(Prand(),Vrand(),20));
		}
		rockcolor=(int(t*256/(2*Pi)))%24+32;
		l1.set(CENTER+f(t), CENTER+g(t));
		l2.set(CENTER+g(t), CENTER+h(t));
		l3.set(CENTER+h(t), CENTER+f(t));
		l4.set(CENTER+f(.5*t)/2, CENTER+g(1.5*t));
		l5.set(CENTER+g(1.5*t), CENTER+h(.5*t));
		l6.set(CENTER+h(.5*t), CENTER+f(.5*t)/2);
		turn=0;
		while(SDL_PollEvent(&event)==1){
			switch(event.type){
				case SDL_KEYDOWN:
					if(event.key.keysym.sym==SDLK_q
					|| event.key.keysym.sym==SDLK_ESCAPE){
						charin='q';
					}
					if(event.key.keysym.sym==SDLK_w){
						push=true;
					}
					if(event.key.keysym.sym==SDLK_a){
						left=true;
					}
					if(event.key.keysym.sym==SDLK_d){
						right=true;
					}
					if(event.key.keysym.sym==SDLK_s){
						down=true;
					}
					if(event.key.keysym.sym==SDLK_SPACE){
						shoot=true;
					}
					if(event.key.keysym.sym==SDLK_p){
						paused=!paused;
					}
					if(event.key.keysym.sym==SDLK_F12){
						SDL_SaveBMP(screen,"asteroids.bmp");
					}
					break;
				case SDL_KEYUP:
					if(event.key.keysym.sym==SDLK_w){
						push=false;
					}
					if(event.key.keysym.sym==SDLK_a){
						left=false;
					}
					if(event.key.keysym.sym==SDLK_d){
						right=false;
					}
					if(event.key.keysym.sym==SDLK_s){
						down=false;
					}
			}
		}
		mouseclick=SDL_GetRelativeMouseState(&mousex,&mousey);
		if(left) s1.slideLeft(ticks);
		if(right) s1.slideRight(ticks);
		if(push) s1.slideUp(ticks);
		if(down) s1.slideDown(ticks);
		if(SDL_BUTTON(1)&mouseclick){
			if(!shoot){
				s1.shoot(int (1+sqrt(s1.score/1000)));
				shoot=true;
			} else {
				shotclock-=ticks;
				if(shotclock<0){
					shotclock+=125;
					shoot=false;
				}
			}
		} else {
			shotclock=125;
			shoot=false;
		}
//		if(shoot||(SDL_BUTTON(1)&mouseclick)) {
//			s1.shoot();
//			shoot=false;
//		}
		mousepos=mousepos+Vector(mousex,mousey);
		double xt;
		if(mag(mousepos)==0){
			xt=3*Pi/2.0;
		} else {
			if(mag(mousepos)>20){
				mousepos=20*(mousepos/mag(mousepos));
			}
			Vector unit(mousepos/mag(mousepos));
			xt=unit.x;
			xt=acos(xt);
			if(unit.y<0) xt=-xt;
		}
		s1.attitude(xt);
		
		//if (rightclick()) s1.push();
		//if (leftclick()) s1.shoot();
		if(paused){
					pause.draw(POWDER,double_buffer);
					blit0(double_buffer,screen);
		} else {
		s1.fly(ticks);
		rocks.fly(ticks,s1.getCenter());
		lastscore=s1.score;
		if (!invulnerable)
			rocks.collide(s1);
		else {
			invulnerable-=ticks;
			if(0==(ticks)) invulnerable--;
			if (invulnerable<0) invulnerable=0;
		}
		if(lastscore!=s1.score)
			if (!(s1.score%ONEUP))
				lives++;
		if (s1.dead()){
			lives--;
			if(lives>=0){
				s1.live();
				s1.set();
				invulnerable=2000;
			}
			else charin='q';
		}
		if(t>=32*Pi) t=0;
		l1.draw(GREEN,double_buffer);
		l2.draw(GREEN,double_buffer);
		l3.draw(GREEN,double_buffer);
		l4.draw(BLUE,double_buffer);
		l5.draw(BLUE,double_buffer);
		l6.draw(BLUE,double_buffer);
		draw(rocks,rockcolor,double_buffer);
		if (!((invulnerable/4)%2)) s1.draw(WHITE,YELLOW,double_buffer);
		scorelabel.draw(POWDER,double_buffer);
		disclaimer.draw(MARINE,double_buffer);
		webad.draw(MAGENTA,double_buffer);
		longout(s1.score,scorepos,WHITE,double_buffer);
		levellabel.draw(YELLOW,double_buffer);
		longout(level,levelpos,YELLOW,double_buffer);
		for (int i=0; i<lives; i++){
			extra.set(Vector(10*i+10,9));
			extra.draw(RED,RED,double_buffer);
			if(i>=11) i=lives;
		}
		Vector ret(s1.getCenter()+mousepos);
		hline(int(ret.x-2),int(ret.x+2),int(ret.y),LIME,double_buffer);
		vline(int(ret.x),int(ret.y-2),int(ret.y+2),LIME,double_buffer);
		pixel(int(ret.x),int(ret.y),WHITE,double_buffer);
		}
		blit0(double_buffer,screen);		//write buffer to the screen
		//memset(double_buffer,0,XMAX*YMAX);	//clear buffer for next frame
		memcpy(double_buffer,bgfxa,XMAX*YMAX);
		frames++;
		ticks=timer;
		ticks=((timer=SDL_GetTicks())-ticks);
	}
	scorelabel.draw(POWDER,double_buffer);
	webad.draw(LIME,double_buffer);
	longout(s1.score,scorepos,WHITE,double_buffer);
	levellabel.draw(YELLOW,double_buffer);
	longout(level,levelpos,YELLOW,double_buffer);
	gameover.drawx2(RED,double_buffer);
	pressanykey.drawx2(MAGENTA,double_buffer);
	blit0(double_buffer,screen);
	while((SDL_PollEvent(&event)!=1)||(event.type!=SDL_KEYDOWN));
	memset(double_buffer,0,XMAX*YMAX);
	//SDL_FreeSurface(bgfx);
}

Vector f(double t){
	return Vector(	int(2*cos(t+Pi)*XMAX/4.0),
			int(cos(t/2)*YMAX/2.5)
	);
}

Vector g(double t){
	return Vector(	int(cos(t)*XMAX/4.0),
			int(sin(t)*-YMAX/2.5)
	);
}

Vector h(double t){
	return Vector(	int(2*sin(t+Pi)*XMAX/4.0),
			int(YMAX/2.0*cos(2*t))
	);
}
