#ifdef _DEBUG
	#include <stdlib.h>
	#include "../mmgr.h"
#endif

#include <math.h>


#include "Jytky.hpp"
#include "../mathematics.hpp"
#include "../primitives.hpp"
#include "../matrix4.hpp"

void Jytky::draw()
{
	const float pos = (time - startTime) / (endTime - startTime);
	float alpha = 1.0f;

	const float fadeinstart = 0.0f;
	const float fadeinstop = 0.1f;
	const float fadeoutstart = 0.90f;
	const float fadeoutstop = 1.0f;

	if (pos >= fadeinstart && pos <= fadeinstop)
		alpha *= (pos-fadeinstart) / (fadeinstop-fadeinstart);
	if (pos >= fadeoutstart && pos <= fadeoutstop)
		alpha *= 1-(pos-fadeoutstart) / (fadeoutstop-fadeoutstart);


	renderScene(pos, alpha);
}

void Jytky::renderScene(float pos, float alpha)
{

/*
    Vector3 cam = Vector3(0, 6, -20);
    Vector3 tgt = Vector3(0, 0, 0);
    Vector3 upw = Vector3(0, 1, 0);

    glLoadIdentity();
    gluLookAt(cam.x, cam.y, cam.z, tgt.x, tgt.y, tgt.z, upw.x, upw.y, upw.z);
*/
	int i;

	//cam->useCamera(4);

	glColor3f(1,1,1);
	glEnable(GL_TEXTURE_2D);


	// -----------------
	// Common stuff
	// -----------------

	//Vector lightDirection = Mathematics::sphereToCartesian(5.50f+pos*0.1f, 24+pos*0.20f, 2.50f+pos*0.6f).normalize();
	Vector lightDirection = Mathematics::sphereToCartesian(5.50f+pos*0.1f, 24+pos*0.20f, 5.50f+pos*0.6f).normalize();

   
	// ------------------
	// Caustic
	// ------------------

	// Caustic numero
	int n = int(pos*32*20)%32 + 1;
	
	// Haetaan vastaava tekstuuri
	char buf[75];
	sprintf(buf, "cau_0%02d.jpg", n);
	Texture *t = dmsGetTexture(buf);


	// ------------------
	// 3ds + shader 
	// ------------------
	

	// Draw shadowmap

glExt.bindDepthFBO();	
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);		

	// Do not draw to colorbuf
	glColorMask( 0, 0, 0, 0 );

	glPolygonOffset(2.0f, 2.0f);
	glEnable(GL_POLYGON_OFFSET_FILL);


		Vector3 ca = Vector3() + Vector3(lightDirection.x*25.0f, lightDirection.y*25.0f, lightDirection.z*25.0f);
		Vector3 tgt = Vector3(0, 0, 0);
		Vector3 upw = Vector3(0, 1, 0);

		glLoadIdentity();
		gluLookAt(ca.x, ca.y, ca.z, tgt.x, tgt.y, tgt.z, upw.x, upw.y, upw.z);

		Matrix4 light_mat_proj;
		glGetFloatv(GL_PROJECTION_MATRIX, light_mat_proj);

		Matrix4 light_mat_modelview;
		glGetFloatv(GL_MODELVIEW_MATRIX, light_mat_modelview);

	
			glPushMatrix();
				
				//glScalef(0.53f,0.53f,0.53f);
				glScalef(0.053f,0.053f,0.053f);

				glRotatef(21+sinf((0.1+pos)*1.87f)*105, -0.64f, -0.34f, 0.7f);

				glDisable(GL_TEXTURE_2D);
				glEnable(GL_DEPTH_TEST);
				glDisable(GL_BLEND);

					// piirtää
					// * normaalit
					// * uv:t
					// * facet
					model->renderVBO();

			glPopMatrix();

	glDisable(GL_POLYGON_OFFSET_FILL);

	// Draw to colorb
	glColorMask( 1, 1, 1, 1 );


glExt.unbindFBO();

			
	cam->useCamera(4);

filter.init(true);

	// -----------------
	// Tausta 
	// -----------------

	// Tyhjennetään depth buffer 
	glClear(GL_DEPTH_BUFFER_BIT);

    glEnable(GL_BLEND);
	glEnable(GL_DEPTH_TEST);
	glBlendFunc(GL_ONE, GL_ONE);
    glEnable(GL_TEXTURE_2D);

	glPushMatrix();

		 glBindTexture(GL_TEXTURE_2D, t->getID());
			glRotatef(310, 1,1,1);
		  Vector ld = lightDirection * -1;
		  //taustaMesh->drawTexturedWithLight(ld, Vector(0.0710153f,0.1162381153f,0.230521153f), 0.231932f);
		  glColor3f(0.0710153f,0.1162381153f,0.17230);
		  
		  glScalef(4,4,4);

		  taustaMesh->drawTextured();

	glPopMatrix();
	glClear(GL_DEPTH_BUFFER_BIT);


	// -----------------
	// Fix texture settings 
	// -----------------

		glMatrixMode(GL_TEXTURE);
		glLoadIdentity();  // clear things up
		glTranslatef(0.5, 0.5, 0.5); // we have to clamp values in the [0.0, 1.0] range, not [-1.0, 1.0]
		glScalef(0.5, 0.5, 0.5);
		glMultMatrixf(light_mat_proj); // now multiply by the matrices we have retrieved before
		glMultMatrixf(light_mat_modelview);
 
		// finally, multiply by the *inverse* of the *current* modelview matrix
		Matrix4 s_mat_m;
		glGetFloatv(GL_MODELVIEW_MATRIX, s_mat_m);

		// Invert [hacky shit]
		s_mat_m = s_mat_m.makeInverseTranspose();
		s_mat_m = s_mat_m.makeTranspose();

		glMultMatrixf(s_mat_m);
		glMatrixMode(GL_MODELVIEW);


				glEnable(GL_TEXTURE_2D);
				glEnable(GL_DEPTH_TEST);
				glDisable(GL_BLEND);



				glPushMatrix();
					
					//glScalef(0.53f,0.53f,0.53f);
					glScalef(0.053f,0.053f,0.053f);

					glRotatef(21+sinf(pos*1.87f)*105, -0.64f, -0.34f, 0.7f);


					glEnable(GL_DEPTH_TEST);
					glDisable(GL_BLEND);

					// Shaderoitu jytky
					shaders.jytky->bind();

					shaders.jytky->setUniform1f("pos", pos);

					shaders.jytky->setUniform1f("alpha", alpha);

					shaders.jytky->setUniform3f("lightDir", lightDirection.x, lightDirection.y, lightDirection.z);
 
					glActiveTextureARB(GL_TEXTURE0_ARB);
					 glEnable(GL_TEXTURE_2D);
					 glBindTexture(GL_TEXTURE_2D, t->getID());
					 shaders.jytky->setUniform1i("texunit0", 0);  

					glActiveTextureARB(GL_TEXTURE1_ARB);
					 glEnable(GL_TEXTURE_2D);
					 //glBindTexture(GL_TEXTURE_2D, dmsGetTexture("fastmusicpart-mood.jpg")->getID());
					 //glBindTexture(GL_TEXTURE_2D, dmsGetTexture("organic01.jpg")->getID());
					 glBindTexture(GL_TEXTURE_2D, dmsGetTexture("dirt2.jpg")->getID());
					 shaders.jytky->setUniform1i("texunit1", 1);  

					glActiveTextureARB(GL_TEXTURE2_ARB);
					 glEnable(GL_TEXTURE_2D);
					 glBindTexture(GL_TEXTURE_2D, glExt.depthTex);
					 shaders.jytky->setUniform1i("shadowMap", 2);  
 

						// piirtää
						// * normaalit
						// * uv:t
						// * facet
						model->renderVBO();

						glActiveTextureARB(GL_TEXTURE2);
						glDisable(GL_TEXTURE_2D);
						glBindTexture(GL_TEXTURE_2D, 0);						

						glActiveTextureARB(GL_TEXTURE1);
						glDisable(GL_TEXTURE_2D);
						glBindTexture(GL_TEXTURE_2D, 0);
					
					glActiveTextureARB(GL_TEXTURE0);
					glDisable(GL_TEXTURE_2D);

					shaders.unbind();
					
				glPopMatrix();

	    glMatrixMode(GL_TEXTURE);
	    glLoadIdentity();
        glEnable(GL_TEXTURE_2D);
        glMatrixMode(GL_MODELVIEW);


	Vector x,y,z;
	Mathematics::antiRotate(&x, &y, &z);

	glColor3f(alpha*0.6f, alpha*0.6f, alpha*0.6f);

	glEnable(GL_BLEND);
	glBlendFunc(GL_ONE, GL_ONE);
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, dmsGetTexture("purpleparticle.jpg")->getID());
	const int COUNT_MAX = pcount/7 * 5;
	for(i=0; i<pcount; i++)
	{
		if(i==COUNT_MAX) 
			glBindTexture(GL_TEXTURE_2D, dmsGetTexture("redparticle.jpg")->getID());

		float size = 0.15f;
		
		// Add some small adjust..
		Vector point = effut[i] + Vector(sinf((i%10)*pos*3.14f), cosf((i%10+4)*pos*3.14f), sinf((i%10+6)*pos*3.14f))*0.4f;

		glBegin(GL_QUADS);

		Vector v1 = point - x*size - y*size;
		Vector v2 = point + x*size - y*size;
		Vector v3 = point + x*size + y*size;
		Vector v4 = point - x*size + y*size;

		glTexCoord2f(0, 0);
		glVertex3fv((float *)&v1);
		glTexCoord2f(1, 0);
		glVertex3fv((float *)&v2);
		glTexCoord2f(1, 1);
		glVertex3fv((float *)&v3);
		glTexCoord2f(0, 1);
		glVertex3fv((float *)&v4);

		glEnd();
	}

	
	glDisable(GL_DEPTH_TEST);
	glDisable(GL_BLEND);


filter.glow(4, 0.0035f, 0.0035f, 0.950f, -0.999970f, 1.0f);	



filter.init();
	// ------------------
	// light rays
	// ------------------

	glColor3f(1,1,1);

	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

	glLoadIdentity();
	
	Vector cam = Vector(0, 0, 30);
	Vector tar = Vector(0, 0, 0);
	Vector upwards = Vector(0, 1, 0);

	gluLookAt(cam.x, cam.y, cam.z, 
			  tar.x, tar.y, tar.z, 
			  upwards.x, upwards.y, upwards.z);

//filter.init();
	
	// -----------------
	// Fix texture settings 
	// -----------------

	glMatrixMode(GL_TEXTURE);
	glLoadIdentity();  // clear things up
	glTranslatef(0.5, 0.5, 0.5); // we have to clamp values in the [0.0, 1.0] range, not [-1.0, 1.0]
	glScalef(0.5, 0.5, 0.5);
	glMultMatrixf(light_mat_proj); // now multiply by the matrices we have retrieved before
	glMultMatrixf(light_mat_modelview);

	// finally, multiply by the *inverse* of the *current* modelview matrix
	Matrix4 s_mat_m2;
	glGetFloatv(GL_MODELVIEW_MATRIX, s_mat_m2);

	// Invert [hacky shit]
	s_mat_m2 = s_mat_m2.makeInverseTranspose();
	s_mat_m2 = s_mat_m2.makeTranspose();

	glMultMatrixf(s_mat_m2);
	glMatrixMode(GL_MODELVIEW);


	glEnable(GL_BLEND);
	glBlendFunc(GL_ONE, GL_ONE);

	Mathematics::antiRotate(&x,&y,&z);


	glColor4f(1,1,1,1);
	shaders.lightray->bind();
	
	glActiveTextureARB(GL_TEXTURE0_ARB);
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, t->getID());
	shaders.lightray->setUniform1i("caustic", 0);

		glActiveTextureARB(GL_TEXTURE1_ARB);
		 glEnable(GL_TEXTURE_2D);
		 glBindTexture(GL_TEXTURE_2D, glExt.depthTex);
		 shaders.lightray->setUniform1i("shadowMap", 1);  
 

	Vector kohta = Vector(0,0,-10);

	const int amount = 15;

		float size = 15.0f;
		for(i=0; i<amount; i++)
		{
			
			kohta.z += 1.33f;
			
			const float scale = 15.0f;

			// Optimize me beautiful	
				glBegin(GL_QUADS);
				Vector v1 = kohta - x*scale - y*scale;
				Vector v2 = kohta + x*scale - y*scale;
				Vector v3 = kohta + x*scale + y*scale;
				Vector v4 = kohta - x*scale + y*scale;

				glTexCoord2f(0, 0);
				glVertex3fv((float *)&v1);
				glTexCoord2f(1, 0);
				glVertex3fv((float *)&v2);
				glTexCoord2f(1, 1);
				glVertex3fv((float *)&v3);
				glTexCoord2f(0, 1);
				glVertex3fv((float *)&v4);
				glEnd();

		}

		glActiveTextureARB(GL_TEXTURE1);
		glBindTexture(GL_TEXTURE_2D, 0);
		glDisable(GL_TEXTURE_2D);
		

	glActiveTextureARB(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, 0);
	glDisable(GL_TEXTURE_2D);
	
					
	shaders.lightray->unbind();

	glMatrixMode(GL_TEXTURE);
	glLoadIdentity();
    glEnable(GL_TEXTURE_2D);
    glMatrixMode(GL_MODELVIEW);

filter.blur(2);

/*
	for (i=0;i<effucount;i++)
	{
		float t = Mathematics::calcPosFloat(pos, effut[i].st, effut[i].et);

		if (t > 0.0001f && t < 1.0f)
		{
	
			glDisable(GL_TEXTURE_2D);
			glBegin(GL_LINE_STRIP);

			const float matka = 0.3f;

			for (float t2=0.0f;t2<matka;t2+=0.02f)
			{
				float t3 = t + t2;
				float a = effut[i].a1*(1-t3) + effut[i].a2*t3;
				float b = effut[i].b1*(1-t3) + effut[i].b2*t3;
				Vector p = effut[i].pos + Mathematics::sphereToCartesian(effut[i].r, a, b);
				glColor4f(1,1,1,alpha*(float)sin(t*3.141592f)*(t2)*2);
				glVertex3fv((float *)&p);
			}

			glEnd();
			glColor4f(1,1,1,(float)sin(t*3.141592f));
			glEnable(GL_TEXTURE_2D);
			Vector valopos = effut[i].pos + Mathematics::sphereToCartesian(effut[i].r, 
						effut[i].a1*(1-(t+matka)) + effut[i].a2*(t+matka),
						effut[i].b1*(1-(t+matka)) + effut[i].b2*(t+matka));

			//Primitives::drawFlare(&valopos, 0.15f);
			Primitives::drawBillboard(valopos, 0.15f);
		}
	}
*/
//	Vector x, y, z;


	// ------------------
	// vesi plane
	// ------------------
/*
    cam = Vector3(10, 6, 20);
    tgt = Vector3(0, 0, 0);
    upw = Vector3(0, 1, 0);

    glLoadIdentity();
    gluLookAt(cam.x, cam.y, cam.z, tgt.x, tgt.y, tgt.z, upw.x, upw.y, upw.z);


	glColor3f(1,1,1);

	shaders.shadow->bind();

		glActiveTextureARB(GL_TEXTURE0_ARB);
		glBindTexture(GL_TEXTURE_2D, dmsGetTexture("49.jpg")->getID());
		shaders.shadow->setUniform1i("tex0", 0);

		glActiveTextureARB(GL_TEXTURE1_ARB);
		glBindTexture(GL_TEXTURE_2D, glExt.depthTex);
		shaders.shadow->setUniform1i("ShadowMap", 1);

			glEnable(GL_BLEND);
			//glDisable(GL_DEPTH_TEST);
			glEnable(GL_TEXTURE_2D);

			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);


			//glColor4f(0.9f*alpha,0.9f*alpha,0.9f*alpha,1*alpha);
			//glColor4f(0.149f,0.1739f,0.39f,1);

			float multiplier = 68.0f;

			Vector p1 = Vector(-2, 0,-2)*multiplier;
			Vector p2 = Vector( 2, 0,-2)*multiplier;
			Vector p3 = Vector( 2, 0, 2)*multiplier;
			Vector p4 = Vector(-2, 0, 2)*multiplier;

			//glBindTexture(GL_TEXTURE_2D, t->getID());
			//Primitives::renderTexturedPlaneWithFadeOut(p1,p2,p3,p4, 25, 10, Vector(0.1949f,0.2739f,0.39f), Vector(), 5.0f, 120.0f, alpha*0.827f);
			Primitives::renderTexturedPlaneWithFadeOut(p1,p2,p3,p4, 25, 10, Vector(1,1,1), Vector(), 5.0f, 120.0f, alpha*0.827f);

			glDisable(GL_BLEND);

		glActiveTextureARB(GL_TEXTURE1);
		glDisable(GL_TEXTURE_2D);
		glActiveTextureARB(GL_TEXTURE0);	

	shaders.unbind();

*/
/*
glActiveTexture( GL_TEXTURE1 );
glBindTexture( GL_TEXTURE2D, fbo_tex_depth );
glActiveTexture( GL_TEXTURE0 );
	
glUseProgram(id);
glUniformi(glGetUniformLocation(id,"shadow_map"),1);
glUseProgram(0);

/*
glDisable(GL_BLEND);
glColor3f(1,1,1);
glBindTexture(GL_TEXTURE_2D, glExt.depthTex);
Primitives::textureTausta(0,0);
*/

}




Jytky::Jytky()
{	
}

Jytky::~Jytky()
{
	model->freeVBO();
	delete model;

	delete taustaMesh;
}


bool Jytky::init(unsigned long s, unsigned long e)
{

	model = new T3DVBO(dmsGetObject("3djytky.t3d"));
	model->createVBO();

	taustaMesh = new Mesh();
	const int xres = 6;
	const int yres = 6;
	const float size = 34.0f;
	const float texturescale = 7.0f;
	taustaMesh->buildSphere(34, xres, yres, texturescale);

	srand(253);
	pcount = 50;
	effut = new Vector[pcount];
	for(int i=0; i<pcount; i++)
	{
		effut[i] = Mathematics::randVector(50, 50, 50);
	}

	startTime = s;
	endTime = e;
	return true;
}
