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

#include <math.h>

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

void Pylvaikko::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.74f;
	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 Pylvaikko::renderScene(float pos, float alpha)
{
    int i;
    int j;

    static float prevpos = 0.0f;
    float dt = pos - prevpos;
    prevpos = pos;

	glLoadIdentity();

    cam->useCamera(0);


	glEnable(GL_BLEND);
    glEnable(GL_LINE_SMOOTH);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE);
	glDisable(GL_DEPTH_TEST);
    glDisable(GL_TEXTURE_2D);
    glLineWidth(1.0f);

    glColor4f(1,1,1,alpha*0.1f);
    glBegin(GL_LINES);
    const int slices = 50;
    const float planesize = 4.0f;
    for (i = 0; i < slices; i++)
    {
        const float t = i / (float)slices;
        float x = -planesize*(1-t) + planesize*t;

        Vector v1 = Vector(x, 0, -planesize);
        Vector v2 = Vector(x, 0, planesize);
        glVertex3fv((float *)&v1);
        glVertex3fv((float *)&v2);
    }
    for (i = 0; i < slices; i++)
    {
        const float t = i / (float)slices;
        float x = -planesize*(1-t) + planesize*t;

        Vector v1 = Vector(-planesize, 0, x);
        Vector v2 = Vector(planesize, 0, x);
        glVertex3fv((float *)&v1);
        glVertex3fv((float *)&v2);
    }
    
    glEnd();


    glDisable(GL_DEPTH_TEST);
    Matrix test;
    test.data[0][0] = 0.2f;
    test.data[1][1] = 1.0f;
    test.data[2][2] = 0.2f;

    glEnable(GL_TEXTURE_2D);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE);
    glBindTexture(GL_TEXTURE_2D, dmsGetTexture("purpleparticle.jpg")->getID());
	Vector x, y, z;
	Mathematics::antiRotate(&x, &y, &z);

    glBegin(GL_QUADS);
    for (i=0;i<pcount;i++)
    {
        particles[i].energy -= dt;
        if (particles[i].energy < 0)
        {
            createParticle(i);
        }
        else
        {
            particles[i].pos += Vector(-254, 0, 0)*dt;

            for (j=0;j<count;j++)
            {
                const float range = 0.7f*3;// + particles[i].pos.y*2.0f;
                const float ranges = range*range;
                float dx = keilat[j].pos.x - particles[i].pos.x;
                float dz = keilat[j].pos.z - particles[i].pos.z;
                float d = dx*dx+dz*dz;
                if (d < ranges)
                {
                    float scale = 1 - d/ranges;
                    glColor4f(1,1,1, alpha*scale*2*sinf((particles[i].energy / particles[i].maxenergy)*3.141592f));
                    Vector n = keilat[j].pos + Vector(dx, 0, dz)*test;
                    n.y = particles[i].pos.y;

                    const float size = 0.08f*scale;
	                Vector v1 = n - x*size - y*size;
	                Vector v2 = n + x*size - y*size;
	                Vector v3 = n + x*size + y*size;
	                Vector v4 = n - 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);
                    
                    break;
                }
            }
        }
    }
    glEnd();
    glDisable(GL_POINT_SMOOTH);
}

void Pylvaikko::createParticle(int index)
{
    const float maxlife = 0.4f;
    const float minlife = 0.1f;

    particles[index].energy = minlife + Mathematics::randFloat()*(maxlife-minlife);
    particles[index].maxenergy = particles[index].energy;
    const float r = Mathematics::randFloat()*15;
    const float a = Mathematics::randFloat()*2*3.141592f;
    const float y = Mathematics::randFloat()*7;
    particles[index].pos = Vector(cosf(a), 0, sinf(a))*r;
    particles[index].pos.y = y;
}

Pylvaikko::Pylvaikko()
{
    int i;
    count = 30;
    pcount = 20000;
    keilat = new Keila[count];

    particles = new PylvaikkoParticle[pcount];
    srand(16019);

    for (i=0;i<count;i++)
    {
        const float r = powf(Mathematics::randFloat(), 0.6f)*3;
        const float a = Mathematics::randFloat()*2*3.141592f;
        keilat[i].pos = Vector(cosf(a), 0, sinf(a))*r;
    }

    for (i=0;i<pcount;i++)
    {
        createParticle(i);
    }
}

Pylvaikko::~Pylvaikko()
{
    delete [] keilat;
    delete [] particles;
}

bool Pylvaikko::init(unsigned long s, unsigned long e)
{
	startTime = s;
	endTime = e;
	return true;
}

