#include "main.h"

#include "gravityparticle.h"

#define EIYLI2 if (y1 >= 0 && x1 >= 0 && y1 < HEIGHT && x1 < WIDTH)

#define WIDTH 512
#define HEIGHT 512

#define GPARTICLES 1500

#define PITUUS 5
short int viiva[(PITUUS+1)*2] = {
	0, 0,
	50, -100,
	100, -50, 
 	200, 10,
  	300, 70,
	400, -30 };

class intro
{
	private:

		
	
		int now, now1;
		GLuint texture;
		SDL_Surface *temp;

		void razer();
		void rotator(SDL_Surface *surface, float rot);
		
		SDL_Surface* pics[1];
		
		int vari;
		int monestiko;
		
		void draw_line(int startx, int starty, int endx, int endy);
		
		SDL_Surface *screen;
		
		void box();
		
		void create_scene1();
		
		GLuint boxi;

		void create_scene2();

		
		void create_scene3();
		
		void create_scene4();
		
	public:
		intro();
		void run();
		
		
			int beginning;
		Mix_Chunk *music;
		
		
		
				
		
		vector <GravityParticle> gravity_particles;
		vector <GravityParticle> gravity_particles2;
		vector <GravityParticle> gravity_particles3;
		vector <GravityParticle> gravity_particles4;
};

intro::intro()
{		
	pics[0] = IMG_Load("data/Devil-goat.png");
	screen=SDL_CreateRGBSurface(SDL_SWSURFACE,WIDTH,HEIGHT,32,0,0,0,0);
	monestiko = 0;
	
	glClearColor(0.00f, 0.00f, 0.00f, 0.0f);
	

	glGenTextures(1,&texture);
	glBindTexture(GL_TEXTURE_2D,texture);
 
 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);


	glBindTexture(GL_TEXTURE_2D,texture);
	
	GLfloat LightAmbient[]= { 0.3f, 0.3f, 0.3f, 1.0f };
	GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };
	GLfloat LightPosition[]= { 5.0f, 2.0f, -10.0f, 1.0f };
	
	glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);
	glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);	
	glLightfv(GL_LIGHT1, GL_POSITION,LightPosition);
	
	glLightfv(GL_LIGHT2, GL_AMBIENT, LightAmbient);
	
	glEnable(GL_LIGHT1);
	glEnable(GL_LIGHT2);
	
	glNewList(boxi,GL_COMPILE);
	
	glBegin(GL_TRIANGLE_STRIP);
	for (int i = 0; i < 10; i++)
	{
		for (int j = 0; j < 10; j++)
		{
			glTexCoord2d((0.1*j)+0.1,(0.1*i)); glVertex3f( -1+(0.2*j)+0.2, -1+(0.2*i), 0); // Bottom left
			glTexCoord2d((0.1*j)+0.1,(0.1*i)+0.1); glVertex3f( -1+(0.2*j)+0.2, -1+(0.2*i)+0.2, 0);
		}
	}
	glEnd();
		
	glEndList();
	
	GravityParticle grav;
	for (int i = 0; i < GPARTICLES; i++)
	{
		gravity_particles.push_back(grav);
		gravity_particles2.push_back(grav);
		gravity_particles3.push_back(grav);
		gravity_particles4.push_back(grav);
	}
	
	music = Mix_LoadWAV("data/organ.ogg");
	Mix_Volume(Mix_PlayChannel(-1, music, 0),MIX_MAX_VOLUME/4);
	beginning = SDL_GetTicks();
}

void intro::run()
{	
	now = SDL_GetTicks() - beginning + 500;

	
	if (now - monestiko > 1000)
	{
		SDL_FillRect(screen, NULL, 0);
		monestiko = now;
	}
	
	if (now > 2000 && now < 13000)
		glTranslatef(0,0,(now-2000)/200.);
	
	if (now < 13000)
		create_scene1();
	else if (now < 19000)
		create_scene2();
	else if (now < 28500)
	{
		glRotatef((now-19000)/15.,0,1,0);
		create_scene2();
		glTranslatef(0,0,0);
		glTranslatef(1,0,0);
		glRotatef(180,0,1,0);
		create_scene3();
	}
	else if (now < 47000)
	{
		
		GLfloat LightAmbient[]= { 0.5f, 0.3f, 0.3f, 1.0f };
		GLfloat LightDiffuse[]= { 1.0f, 0.8f, 0.8f, 1.0f };
	
		glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);
		glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);	
				glLightfv(GL_LIGHT2, GL_AMBIENT, LightAmbient);
		glLightfv(GL_LIGHT2, GL_DIFFUSE, LightDiffuse);	
		
		glDisable(GL_BLEND);
		glEnable(GL_TEXTURE_2D);
		
		create_scene3();
		
		
		glDisable(GL_DEPTH_TEST);
		glEnable(GL_BLEND);
		glDisable(GL_TEXTURE_2D);
		
		glTranslatef(0,0.5,0);
		for (int i = 0; i < GPARTICLES; i++)
		{
			glTranslatef(-3,0,0);
			gravity_particles[i].Run();
			glTranslatef( 1,0,0);
			gravity_particles2[i].Run();
			glTranslatef( 1,0,0);
			gravity_particles3[i].Run();
			glTranslatef( 1,0,0);
			gravity_particles4[i].Run();
		}

	}
	else if (now < 59000)
	{
		create_scene4();
	}
	else
	{
		
	}
}

void intro::create_scene4()
{
	
		glDisable(GL_BLEND);
	glShadeModel(GL_SMOOTH);
	glEnable(GL_LIGHTING);
	glBindTexture(GL_TEXTURE_2D,texture);
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_TEXTURE_2D);
	glDisable(GL_LIGHTING);
	glDisable(GL_BLEND);
	glEnable(GL_TEXTURE_2D);
	rotator(pics[0],(now/100)/5.);
	now1 = now%2000;
 	razer();
	
	glTranslatef(0,0,-1);
	
	gluBuild2DMipmaps(GL_TEXTURE_2D,4,screen->w,screen->h,GL_RGB,GL_UNSIGNED_BYTE,screen->pixels);
	
	
			glPushMatrix();
// 			glTranslatef(1,0,-2);
			glRotatef(180,0,0,1);
			glNormal3f( 0.0f, 0.0f, 1.0f);
			box();
			glPopMatrix();
			/*
			glPushMatrix();
			glTranslatef(-1,0,-2);
			glRotatef(180,0,1,0);
			glRotatef(180,0,0,1);
			glNormal3f( 0.0f, 0.0f,-1.0f);
			box();
			glPopMatrix();
			*/
}

void intro::create_scene3()
{
	rotator(pics[0],(now/100)/5.);
	now1 = now%2000;
 	razer();
	
	gluBuild2DMipmaps(GL_TEXTURE_2D,4,screen->w,screen->h,GL_RGBA,GL_UNSIGNED_BYTE,screen->pixels);
	
	
	
	if ((now-13000)/50. - 100 < 0)
		glTranslatef(0,0,(now-13000)/50. - 100);
	
	
			glPushMatrix();
			glTranslatef(1,0,-2);
			glRotatef(180,0,0,1);
			glNormal3f( 0.0f, 0.0f, 1.0f);
			box();
			glPopMatrix();
			
			glPushMatrix();
			glTranslatef(-1,0,-2);
			glRotatef(180,0,1,0);
			glRotatef(180,0,0,1);
			glNormal3f( 0.0f, 0.0f,-1.0f);
			box();
			glPopMatrix();
}

void intro::create_scene2()
{
	rotator(pics[0],(now/100)/5.);
	now1 = now%2000;
 	razer();
	
	gluBuild2DMipmaps(GL_TEXTURE_2D,4,screen->w,screen->h,GL_RGBA,GL_UNSIGNED_BYTE,screen->pixels);
	
	
	
	if ((now-13000)/50. - 100 < 0)
		glTranslatef(0,0,(now-13000)/50. - 100);
	
	
				glPushMatrix();
			glTranslatef(1,0,-2);
			glRotatef(180,0,0,1);
			glNormal3f( 0.0f, 0.0f, 1.0f);
			box();
			glPopMatrix();
			
			glPushMatrix();
			glTranslatef(-1,0,-2);
			glRotatef(180,0,1,0);
			glRotatef(180,0,0,1);
			glNormal3f( 0.0f, 0.0f,-1.0f);
			box();
			glPopMatrix();
}

void intro::create_scene1()
{
	
	glDisable(GL_BLEND);
	glShadeModel(GL_SMOOTH);
	glEnable(GL_LIGHTING);
	glBindTexture(GL_TEXTURE_2D,texture);
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_TEXTURE_2D);

	
	rotator(pics[0],(now/100)/5.);
	now1 = now%2000;
 	razer();
	
	gluBuild2DMipmaps(GL_TEXTURE_2D,4,screen->w,screen->h,GL_RGBA,GL_UNSIGNED_BYTE,screen->pixels);

	glTranslatef(0,0,-50);
	
	glTranslatef(-60, 0, 0);
	glTranslatef(0, -30, 0);
	for (int i = 0; i < 30; i++)
	{
		glTranslatef(4, 0, 0);
		for (int j = 0; j < 30; j++)
		{
			glTranslatef(0,2,0);
			
			glPushMatrix();
			glTranslatef(1,0,-2);
			glRotatef(180,0,0,1);
			glNormal3f( 0.0f, 0.0f, 1.0f);
			box();
			glPopMatrix();
			
			glPushMatrix();
			glTranslatef(-1,0,-2);
			glRotatef(180,0,1,0);
			glRotatef(180,0,0,1);
			glNormal3f( 0.0f, 0.0f,-1.0f);
			box();
			glPopMatrix();
		}
		
		glTranslatef(0, -60.0, 0);
	}
	glTranslatef(-15,0,0);
	glTranslatef( 0,-15,0);
	
		
		
	GLfloat LightPosition[]= { sin(now/400.)*60,cos(now/400.)*60,0, 1.0f };
	GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };
	glLightfv(GL_LIGHT1, GL_POSITION,LightPosition);
	glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);	
	
	GLfloat LightPosition2[]= { 0,0, 1.0f };
	GLfloat LightDiffuse2[]= { 0.2f, 0.1f, 0.1f, 1.0f };
	glLightfv(GL_LIGHT2, GL_POSITION,LightPosition2);
	glLightfv(GL_LIGHT2, GL_DIFFUSE, LightDiffuse2);

}

void intro::box()
{
	glCallList(boxi);
}

void intro::razer()
{
	int ykerroin = 100;
	
	int yseuraava[2];
	
	int xseuraava[2];
	
	for (int i = 0; i < PITUUS; i++)
	{
		if (now1/3 <= 400)
		{
			xseuraava[0] = viiva[(i*2)];
			xseuraava[1] = viiva[(i*2)+2];
			
			yseuraava[0] = viiva[(i*2)+1]+ykerroin;
			yseuraava[1] = viiva[(i*2)+3]+ykerroin;
		}
		else
		{
			xseuraava[0] = WIDTH - viiva[((i)*2)+2];
			xseuraava[1] = WIDTH - viiva[((i)*2)];
			
			yseuraava[0] = viiva[((i)*2)+3]+ykerroin;
			yseuraava[1] = viiva[((i)*2)+1]+ykerroin;
		}
		
		
		for (int j = -18; j < 19; j++)
		{
			if (j < 0)
				vari = (int)(((255/2)*(3/(float(-j)))) + ((int)((255/8)*(3/(float(-j))))<<8) + ((255/100)<<16));
			else
				vari = (int)(((255/2)*(3/(float(j)))) + ((int)((255/8)*(3/(float(j))))<<8) + ((255/100)<<16));
			draw_line(xseuraava[0],
					  yseuraava[0]+j,
				      xseuraava[1],
					  yseuraava[1]+j);
			if (j == 0)
				j++;
		}
		vari = 255 + ((255/8)<<8) + ((255/8)<<16);
		draw_line(xseuraava[0],
					  yseuraava[0],
				      xseuraava[1],
					  yseuraava[1]);
	}
}

void intro::rotator(SDL_Surface *surface, float rot)
{
	Uint8 r, g, b;
	
	float cosine = cos(rot);
	
	for (int y = 0; y < surface->h; y++)
	{
		Uint32 *p = ((Uint32*)surface->pixels) + ((surface->pitch * y) >> 2);
		
		for (int x = 0; x < surface->w; x++)
		{
			

				int x1 =(int)( x+((( ( y - surface->h/2 ) * cosine ))) + 300);
 				int y1 =(int) (y-((( ( x - surface->w/2 ) * cosine ))));
					
			SDL_GetRGB(*p, surface->format, &r, &g, &b);

			EIYLI2
				*(Uint32 *)((Uint8 *)screen->pixels + (y1) * screen->pitch + ((x1) << 2)) += SDL_MapRGB(screen->format, r, g, b);
			
			p++;
		}
	}
}

void intro::draw_line(int startx, int starty, int endx, int endy) 
{
	
	int x0 = starty;
	 int x1 = endy;
	 int y0 = startx;
	 int y1 = endx;
	
	int steep;
	if (abs(y1 - y0) > abs(x1 - x0))
		steep = 1;
	else
		steep = 0;
     if (steep)
	 {
        int tep = x0;
		x0 = y0;
		y0 = tep;

		tep = x1;
		x1 = y1;
		y1 = tep;
	 }
     if (x0 > x1)
	 {
		int tep = x0;
		x0 = x1;
		x1 = tep;

		tep = y0;
		y0 = y1;
		y1 = tep;
	 }
     int deltax = x1 - x0;
     int deltay = abs(y1 - y0);
     int error = deltax / 2;
     int ystep;
     int y = y0;
     if (y0 < y1)
	 	ystep = 1;
	 else 
		 ystep = -1;
	 
	 SDL_LockSurface(screen);
     for (int x = x0; x < x1; x++)
	 {

		 if (now1/3 <=400)
         if (!steep)
		 {
			 if (y < WIDTH && y > 0 && x <  HEIGHT && x > 0 && y < now1/3)
		 		*(Uint32 *)((Uint8 *)screen->pixels + x * screen->pitch + (y<< 2)) += vari;
			 
		 }
		else
		{
			if (y < HEIGHT && y > 0 && x < WIDTH && x > 0 && x < now1/3)
				*(Uint32 *)((Uint8 *)screen->pixels + y * screen->pitch + (x<< 2)) += vari;
		}
		else if (now1/3 <= 820)
			         if (!steep)
		 {
			 if (y < WIDTH && y > 0 && x <  HEIGHT && x > 0 && y > (WIDTH - now1/3)+400)
		 		*(Uint32 *)((Uint8 *)screen->pixels + x * screen->pitch + (y<< 2)) += vari;
			 
		 }
		else
		{
			if (y < HEIGHT && y > 0 && x < WIDTH && x > 0 && x > (WIDTH - now1/3)+400)
				*(Uint32 *)((Uint8 *)screen->pixels + y * screen->pitch + (x<< 2)) += vari;
		}
         error = error - deltay;
         if (error < 0)
		 {
             y = y + ystep;
             error = error + deltax;
		 }
	 }
	 SDL_UnlockSurface(screen);
}

