#include "main.h"

GLuint gravityTexture;
GLuint antigravityTexture;

planet::planet() {
	this->ticks = SDL_GetTicks();
	this->width = PLANETMINDIMENSION + 
			rand()%(PLANETMAXDIMENSION - PLANETMINDIMENSION);
	this->height = this->width;
	this->x = this->width/2 + rand()%(SCREENWIDTH - (int)this->width);
	this->y = this->height/2 + rand()%(SCREENHEIGHT - (int)this->height);
	this->speedx = 0;
	this->speedy = 0;
	this->mass = pow((this->width/2),2) * PLANETMASSSIZERATIO;
	this->rotFreq = (float) (rand() % PLANETMAXROTFREQ) / 1000;
	this->stability = 1.0f;
	if (rand()%2 == 1) {
		this->gravity = GRAVITY;
	} else {
		this->gravity = ANTIGRAVITY;
	}
}

planet::~planet() {
}

void planet::move(vector<planet*> &planetlist, screen *scr) {
	GLuint tmp = SDL_GetTicks();
	float theta;
	float distance;
	for (unsigned int i = 0; i < planetlist.size(); i++) {
		if (this->mass == 0) {
			return;
		}
		if (planetlist[i] == this)
			continue;
		if (planetlist[i]->mass == 0)
			continue;
		theta = atan2(this->y - planetlist[i]->y, 
			      this->x - planetlist[i]->x);
		distance = sqrt(pow(this->x - planetlist[i]->x, 2) +
			   pow(this->y - planetlist[i]->y, 2));
		if (distance < planetlist[i]->width/2 + this->width/2) {
			if (planetlist[i]->gravity == this->gravity) {
				this->x += (planetlist[i]->x - this->x) * 
						planetlist[i]->mass/(this->mass +
						planetlist[i]->mass);
				this->y += (planetlist[i]->y - this->y) * 
						planetlist[i]->mass/(this->mass + 
						planetlist[i]->mass);
				this->speedx = (this->speedx * this->mass + planetlist[i]->speedx * 
						planetlist[i]->mass) / (this->mass + planetlist[i]->mass);
				this->speedy = (this->speedy * this->mass + planetlist[i]->speedy * 
						planetlist[i]->mass) / (this->mass + planetlist[i]->mass);
				this->mass += planetlist[i]->mass;
				planetlist[i]->mass = 0;
			} else {
				this->x += (planetlist[i]->x - this->x) * 
						planetlist[i]->mass /
						(planetlist[i]->mass + this->mass);
				this->y += (planetlist[i]->y - this->y) *
						planetlist[i]->mass / 
						(planetlist[i]->mass + this->mass);
				this->speedx = (this->speedx * this->mass + planetlist[i]->speedx * 
						planetlist[i]->mass) / (this->mass + planetlist[i]->mass);
				this->speedy = (this->speedy * this->mass + planetlist[i]->speedy * 
						planetlist[i]->mass) / (this->mass + planetlist[i]->mass);		
				this->mass -= planetlist[i]->mass;
				planetlist[i]->mass = 0;
			}
			planetlist[i]->calculateNewSize();
			this->calculateNewSize();
			return;
		}
		if (planetlist[i]->gravity == this->gravity) {
			this->speedx -= (planetlist[i]->mass/(this->mass*distance)) * 
					GRAVITYCONSTANT * cos(theta) * 
					(TIMESTEP)/1000;
			this->speedy -= (planetlist[i]->mass/(this->mass*distance)) *
					GRAVITYCONSTANT * sin(theta) * 
					(TIMESTEP)/1000;
		} else {
			this->speedx += (planetlist[i]->mass/(this->mass*distance)) * 
					GRAVITYCONSTANT * cos(theta) * 
					(TIMESTEP)/1000;
			this->speedy += (planetlist[i]->mass/(this->mass*distance)) *
					GRAVITYCONSTANT * sin(theta) * 
					(TIMESTEP)/1000;
		}
	}
	this->speedx -= (SIDEMASS/(this->mass*(scr->right -this->x))) * GRAVITYCONSTANT * 
			(TIMESTEP)/1000;
	this->speedy -= (SIDEMASS/(this->mass*(scr->bottom - this->y))) * GRAVITYCONSTANT * 
			(TIMESTEP)/1000;
	this->speedx += (SIDEMASS/(this->mass*(this->x - scr->left))) * GRAVITYCONSTANT * 
			(TIMESTEP)/1000;
	this->speedy += (SIDEMASS/(this->mass*(this->y - scr->top))) * GRAVITYCONSTANT * 
			(TIMESTEP)/1000;
	
	this->x += this->speedx * (TIMESTEP)/1000;
	this->y += this->speedy * (TIMESTEP)/1000;
	
	this->angle = this->angle + 360*this->rotFreq*(TIMESTEP)/1000;
	while (this->angle > 360) 
		this->angle -= 360;
	while (this->angle < 0) 
		this->angle += 360;
	
	if (this->x + this->width/2 > scr->right) {
		if (!scr->setright(this->x + this->width/2)) {
			this->x = scr->right - this->width/2;
			this->speedx = 0;
		}
	}
	if (this->y + this->height/2 > scr->bottom) {
		if (!scr->setbottom(this->y + this->height/2)) {
			this->y = scr->bottom - this->height/2;
			this->speedy = 0;
		}
	}
	if (this->x - this->width/2 < scr->left) { 
		if (!scr->setleft(this->x - this->width/2)) {
			this->x = scr->left + this->width/2;
			this->speedx = 0;
		}
	}
	if (this->y - this->height/2 < scr->top) {
		if (!scr->settop(this->y - this->height/2)) {
			this->y = scr->top + this->height/2;
			this->speedy = 0;
		}
	}
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(scr->left, scr->right, scr->bottom, scr->top, -1.0f, 1.0f);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	
	this->ticks = tmp;
}

void planet::draw() {
	if (this->mass == 0)
		return;
	glPushMatrix(); //begin drawing the planet

	/* Rotate. */
	glTranslatef(this->x, this->y, 0.0); 
	glRotatef(this->angle, 0.0, 0.0, 1.0);

	glBindTexture(GL_TEXTURE_2D, this->texture);

	glEnable(GL_BLEND);
	glBegin(GL_QUADS);
	glColor4f(1, 1, 1, 1);
	glTexCoord2i(0, 0);
	glVertex3f((-1)*this->width/2, (-1)*this->height/2, 0);

	glTexCoord2i(1, 0);
	glVertex3f(this->width/2, (-1)*this->height/2, 0);

	glTexCoord2i(1, 1);
	glVertex3f(this->width/2, this->height/2, 0);

	glTexCoord2i(0, 1);
	glVertex3f((-1)*this->width/2, this->height/2, 0);
	glEnd();

	glPopMatrix();
}

void planet::calculateNewSize() {
	if (this->mass < 0) {
		this->mass = (-1) * this->mass;
		if (this->gravity == GRAVITY) {
			this->gravity = GRAVITY;
			this->texture = gravityTexture;
		} else {
			this->gravity = ANTIGRAVITY;
			this->texture = antigravityTexture;
		}
	}
			
	
	this->width = 2*sqrt(this->mass / PLANETMASSSIZERATIO);
	this->height = this->width;
}

void planet::setTexture(GLuint gravtex, GLuint antigravtex) {
	gravityTexture = gravtex;
	antigravityTexture = antigravtex;
	if (this->gravity == GRAVITY)
		this->texture = gravtex;
	else
		this->texture = antigravtex;
}

planet* getFreePlanet(vector<planet*> &planetlist) {
	for (unsigned int i = 0; i < planetlist.size(); i++) {
		if (planetlist[i]->mass == 0) {
			return planetlist[i];
		}
	}

	return NULL;
}

void planet::split(vector<planet*> &planetlist) {
	if (this->mass == 0)
		return;
// 	float diceroll = ((float) (rand() % 1000)) /1000;
// 	if (diceroll > this->stability) {
// 		float averagenewmass = this->mass / (((1.0f - this->stability)*20) * 
// 				((float) 2 / (float) 3));
// 		for (int i = 0; i < (1.0f - this->stability)*10; i++) {
// 			planet *p;
// 			p = getFreePlanet(planetlist);
// 			if (p == NULL)
// 				break;
// 			p->mass = averagenewmass - rand()%PLANETMINDIMENSION;
// 			if (p->gravity == this->gravity) {
// 				this->mass -= p->mass;
// 			} else {
// 				this->mass += p->mass;
// 			}
// 			p->calculateNewSize();
// 		}
// 		if (this->mass < 0) {
// 			this->mass = this->mass * (-1);
// 			if (this->gravity == GRAVITY) {
// 				this->gravity = ANTIGRAVITY;
// 				this->texture = antigravityTexture;
// 			} else {
// 				this->gravity = GRAVITY;
// 				this->texture = gravityTexture;
// 			}
// 		}
// 		this->calculateNewSize();
// 	}
}



