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

#include <math.h>

#include "Revolution.hpp"
#include "../mathematics.hpp"
#include "../primitives.hpp"

//splinet xz-tasoon 
RevolutionObject::RevolutionObject(int count, CatmullRom *spline)
{
    int i;
    const int splinepoints = 10;
    this->count = count;

    splines = new CatmullRom*[count];
    splinelengths = new float[count];
    splinelengthphases = new float[count];
    splinelengthspeeds = new float[count];
    splinecolors = new Vector[count];

    //etsitään splinen matalin kohta
    float lowest = 50.0f;
    for (i = 0; i < spline->pcount; i++)
    {
        if (spline->points[i].y < lowest)
            lowest = spline->points[i].y;
    }

    this->st = Mathematics::randBetween(0.0f, 0.1f);
    this->et = 1.0f;//this->st + Mathematics::randBetween(0.05f, 0.1f);

    this->pos = Mathematics::randVectPlane()*2.7f*Mathematics::randFloat();

    for (i = 0; i < count; i++)
    {
        float it = i / (float)count;
        Matrix rotate;

        rotate.makeRotation(Mathematics::randBetween(-0.15f, 0.15f), it*2*3.141592f, Mathematics::randBetween(-0.15f, 0.15f));

        splinelengths[i] = 0.27f + 0.73f * Mathematics::randFloat(); //täytyy olla < 1.0f        
        splinelengthphases[i] = Mathematics::randFloat(); 
        splinelengthspeeds[i] = 0.2f + 0.2f*Mathematics::randFloat(); 
        splines[i] = new CatmullRom(splinepoints);

        for (int j = 0; j < splinepoints; j++)
        {
            float jt = j / (float)splinepoints;
            Vector splinepoint = (spline->getValue(jt) * rotate);
            splines[i]->addPoint(splinepoint-Vector(0, lowest, 0));
        }

        Vector c1, c2;
        switch(rand()%4)
        {
            case 0:
            {
                //vihreä
    //           c1 = Vector(0.15f, 0.5f, 0.25f);
    //            c2 = Vector(0.14f, 0.8f, 0.24f);
                c1 = Vector(0.15f, 0.7f, 0.9f);
                c2 = Vector(0.14f, 0.9f, 1.0f);
            } break;
            case 1:
            {
                //keltainen
                c1 = Vector(0.9f, 0.7f, 0.3f);
                c2 = Vector(1.0f, 0.8f, 0.3f);

            } break;
            case 2:
            {
                //oranssi
                c1 = Vector(0.8f, 0.4f, 0.1f);
                c2 = Vector(1.0f, 0.5f, 0.1f);
            } break;

            case 3:
            {
                //punainen
                c1 = Vector(0.8f, 0.2f, 0.1f);
                c2 = Vector(1.0f, 0.3f, 0.1f);
            } break;
        }


        float coloralpha = 0.9f;
        float colort = Mathematics::randFloat();
        splinecolors[i] = (c1 * (1-colort) + c2*colort)*coloralpha;


    }
/*
    this->rotatemulx = 0.1f;
    this->rotatemulz = 0.3f;
    this->speed1 = 11;
    this->speed2 = 41;
    this->speed3 = 36;
*/
    this->rotatemulx = Mathematics::randBetween(0.05f, 0.35f);
    this->rotatemulz = Mathematics::randBetween(0.2f, 0.5f);//0.3f;
    this->speed1 = Mathematics::randBetween(6, 9);//11;
    this->speed2 = Mathematics::randBetween(10, 25);//41;
    this->speed3 = Mathematics::randBetween(10, 17);//36;

    Vector color1 = Vector(0.4f, 0.7f, 0.54f);
    Vector color2 = Vector(0.2f, 0.8f, 0.14f);

    float colort = Mathematics::randFloat();
    this->color = color1*(1-colort) + color2*colort;

}

void RevolutionObject::draw(float time, float alpha)
{
    int i;
    glDisable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_LINE_SMOOTH);

    glPushMatrix();
    glTranslatef(pos.x, pos.y,pos.z);

    glLineWidth(2.0f);

    float pos = time;//Mathematics::calcPosFloat(time, this->st, this->et);

    Vector *flarepositions = new Vector[count];

    Matrix oksarotate;
    for (i = 0; i < count; i++)
    {
        float it = i / (float)count;
        const int splinedrawpieces = 30;
        const float maxalpha = 0.25f;

        float temp = 0.8f+0.2f*sinf(fmodf(pos*splinelengthspeeds[i] + splinelengthphases[i],1)*3.141592f);
        float maxt = splinelengths[i]*temp*sinf(pos*3.141592f);// * (1-temp) + 1.0f*temp;
        glBegin(GL_LINE_STRIP);

        for (float t = 0.0f; t < maxt; t += 1.0f / splinedrawpieces)
        {
            oksarotate.makeRotation(rotatemulx*cosf(t*3*3.141592f+it*2*2*3.141592f*cosf(pos*speed1) + pos*speed2)*t,
                                    0,
                                    rotatemulz*cosf(t*2*3.141592f+it*2*3.141592f + pos*speed3)*t);

            Vector p = splines[i]->getValue(t) * oksarotate;
            const float himmea = 1-(maxt-t)/maxt;
            glColor4f(splinecolors[i].x, splinecolors[i].y, splinecolors[i].z, alpha*maxalpha*1.5f*himmea);
//            glColor4f(color.x,color.y,color.z ,alpha*maxalpha*1.5f*himmea);
            glVertex3fv((float *)&p);
        }
        flarepositions[i] = splines[i]->getValue(maxt) * oksarotate;
        glEnd();
    }


    glEnable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA,GL_ONE);
    glColor4f(1,1,1,alpha*0.5f);
    glBindTexture(GL_TEXTURE_2D,dmsGetTexture("fireparticle.jpg")->getID());

    for (i = 0; i < count; i++)
    {
        Primitives::drawBillboard(flarepositions[i], 0.05f);

    }

    delete [] flarepositions;

    glPopMatrix();
    glDisable(GL_LINE_SMOOTH);
}

void Revolution::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);


//	filter.initDOF();

//    filter.init();
	renderScene(pos, alpha);
//    filter.glow(7, 0.006f, 0.006f, 0.909f, -1.0f, 1.0f);
	 
	//filter.dof(201, 250, 300, 2);
    
//	filter.dof();
	//filter.dof(1, 3, 15, 2);

}

void Revolution::renderScene(float pos, float alpha)
{
    //dmsMsg("revolution::renderScene()\n");
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	//gluPerspective(fov, (float)width/(float)height, 0.5f, 14000.0f);
	gluPerspective(45, 800/600.0f, 0.1f, 14000.0f);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

    int i;
    cam->useCamera(0);
     
	//gluPerspective( 60, 1.33f , 1, 2  );
	//dmsSetPerspective(45, 0.1f, 100.0f);

	glEnable(GL_BLEND);
    glEnable(GL_LINE_SMOOTH);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE);
	glEnable(GL_DEPTH_TEST);

	glEnable(GL_TEXTURE_2D);

/*
	T3D *object1 = dmsGetObject("sp.t3d");
	int objectvertexcount = object1->getVertexCount();
	int objectfacecount = object1->getFaceCount();
	T3DFace *objectfaces = object1->getFaceArray();
	T3DVertex *objectvertices = object1->getVertexArray();

	glColor4f(1,1,1,1.0f*alpha);
	
	glPushMatrix();
		glScalef(25,25,7.5f);	
		glRotatef(20,1,0,0); 
		glBindTexture(GL_TEXTURE_2D, dmsGetTexture("hmap.jpg")->getID());
		glBegin(GL_TRIANGLES);
		for (i=0;i<objectfacecount;i++)
		{
			glNormal3fv((float *)&objectfaces[i].normal);
			glTexCoord2f(objectvertices[objectfaces[i].a].u, objectvertices[objectfaces[i].a].v);
			 glVertex3fv((float *)&objectvertices[objectfaces[i].a].position);
			glNormal3fv((float *)&objectfaces[i].normal);
			glTexCoord2f(objectvertices[objectfaces[i].b].u, objectvertices[objectfaces[i].b].v);
			 glVertex3fv((float *)&objectvertices[objectfaces[i].b].position);
			glNormal3fv((float *)&objectfaces[i].normal);
			glTexCoord2f(objectvertices[objectfaces[i].c].u, objectvertices[objectfaces[i].c].v);
			 glVertex3fv((float *)&objectvertices[objectfaces[i].c].position);
		}
		glEnd();
	glPopMatrix();
*/
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	//glColor4f(0.9f*alpha,0.9f*alpha,0.9f*alpha,1*alpha);
/*
    glColor4f(0.9f,0.9f,0.9f,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, dmsGetTexture("dirt2.jpg")->getID());
	Primitives::renderTexturedPlaneWithFadeOut(p1,p2,p3,p4, 25, 40, Vector(1,1,1), Vector(), 5.0f, 12.0f, alpha);
*/
    glDisable(GL_TEXTURE_2D);

    glColor4f(1,1,1,alpha*0.1f);

    filter.init();
//	renderScene(pos, alpha);

	glDisable(GL_TEXTURE_2D);
    glDisable(GL_DEPTH_TEST);
    float kukkaalku = 0.12f;
    float kukkaloppu = 1.0f;

    float kukkapos = Mathematics::calcPosFloat(pos, kukkaalku, kukkaloppu);
    float kukkafade = sinf(Mathematics::calcPosFloat(pos, kukkaalku, kukkaalku+0.1f)*3.141592f*0.5f);

    for (i = 0; i < ocount; i++)
    {
        objects[i]->draw(kukkapos,alpha*kukkafade);
    }

    glBindTexture(GL_TEXTURE_2D, dmsGetTexture("fireparticle.jpg")->getID());
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE);
    for (i = 0; i < tilpecount; i++)
    {
        Vector p = tilpet[i];
        float t = sinf(Mathematics::calcPosFloat(pos, tilpestart[i], tilpeend[i])*3.141592f*0.5f);
        glColor4f(1,1,1,alpha*0.4f*t);
        float s = t*tilpesizes[i] * sinf(fmodf(tilpespeeds[i]*pos, 1)*3.141592f + tilpephases[i]);
        Primitives::drawBillboard(p, s);
    }
    filter.glow(7, 0.006f, 0.006f, 0.909f, -1.0f, 1.0f);
	
}




Revolution::Revolution()
{	
    int j;
    int i;

    ocount = 50;
    objects = new RevolutionObject*[ocount];

    int scount = 50;

    srand(619);
    for (j = 0; j < ocount; j++)
    {
        CatmullRom *spline = new CatmullRom(scount);

        float length = Mathematics::randBetween(1.8f, 3.5f);
        float maxradius = 0.73f;
        float power = 0.4f+Mathematics::randBetween(0.6f, 1.5f);

        for (i = 0; i < scount; i++)
        {
            float it = i / (float)scount;
            float y = it * length;
            float x = Mathematics::randFloat()*maxradius*powf(it, power);
            float z = 0.0f;


            spline->addPoint(Vector(x, y, z));
        }
    

        objects[j] = new RevolutionObject(16, spline);
        delete spline;
    }

    tilpecount = 250;
    tilpet = new Vector[tilpecount];
    tilpephases = new float[tilpecount];
    tilpesizes = new float[tilpecount];
    tilpespeeds = new float[tilpecount];
    tilpestart = new float[tilpecount];
    tilpeend = new float[tilpecount];

    for (i = 0; i < tilpecount; i++)
    {
        float a = Mathematics::randBetween(0, 2*3.141592f);
        float r = Mathematics::randBetween(3.8f, 4.0f);

        tilpestart[i] = (a / (2*3.141592f))*0.2f;
        tilpeend[i] = tilpestart[i] + Mathematics::randBetween(0.03f, 0.06f);//(a / (2*3.141592f))*0.1f;

        Vector p = Vector(cosf(a), 0, sinf(a))*r;
        tilpet[i] = p;

        tilpephases[i] = Mathematics::randBetween(0, 1);
        tilpespeeds[i] = Mathematics::randBetween(8, 17);
        tilpesizes[i] = Mathematics::randBetween(0.1f, 0.2f);

    }

}

Revolution::~Revolution()
{
}


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

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

