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

#include <math.h>

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

void Henget::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.98f;
	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.init(true);
	renderScene(pos, alpha);
    filter.glow(4, 0.005f, 0.005f, 0.93f, -1.0f, 1.0f);
}

Henki::Henki()
{
    int i;
    const int maxpoints = 10;
    this->spline = new CatmullRom(maxpoints);

    this->shade = Mathematics::randBetween(0.3f, 0.8f);

    this->st = Mathematics::randBetween(0.1f, 0.8f);
    this->et = this->st + Mathematics::randBetween(0.08f, 0.15f);

    float r = Mathematics::randBetween(4.0f, 8.0f);
    float a = Mathematics::randBetween(0, 2*3.141592f);
    float y = Mathematics::randBetween(1, 4);

    float power = Mathematics::randBetween(0.3f, 1.8f);

    bool dir = ((rand()%2)==0)?true:false;
    float startkulma = Mathematics::randBetween(0, 2*3.141592f);
    float kulmadelta = Mathematics::randBetween(0.3f, 3.6f);
    float endkulma = startkulma + dir?kulmadelta:-kulmadelta;
    float kulmapower = Mathematics::randBetween(0.6f, 1.6f);

    for (i = 0; i < maxpoints; i++)
    {
        float it = i / (float)maxpoints;
        float rhere = r*it;

        float kulma = startkulma + (endkulma - startkulma)*powf(it, kulmapower);
        Vector displace = Vector(cosf(kulma), 0, sinf(kulma))*rhere;
        Vector p = Vector(cosf(a), 0, sinf(a))*rhere + Vector(0, y, 0)*powf(it, power);

          this->spline->addPoint(p + displace);
    }

    this->curpos = Vector(0, 0, 0);
    this->active = false;
    this->prevpos = Vector(0, 0, 0);
}

Henki::~Henki()
{
    delete this->spline;
}

void Henki::render(float pos, float alpha)
{
    //TODO
    glDisable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE);
    glDisable(GL_DEPTH_TEST);

    const int linestrips = 50;
    float poshere = Mathematics::calcPosFloat(pos, this->st, this->et);

    if (poshere > 0.00001f && poshere < 0.99999f)
    {

        float start_t = 0.0f;
        float end_t = 0.0f;

        if (poshere < 0.5f)
        {
            start_t = 0.0f;
            end_t = poshere * 2;
        }
        else
        {
            start_t = (poshere-0.5f)*2;
            end_t = 1.0f;
        }
    
        float t_width = end_t - start_t;

        glLineWidth(2.0f);
        glBegin(GL_LINE_STRIP);
        for (float t = start_t; t < end_t; t+= 1.0f / linestrips)
        {
            glColor4f(0.7f,0.5f,0.2f,alpha*(poshere-t));
            glVertex3fv((float *)&this->spline->getValue(t));
        }
        glEnd();
        this->prevpos = this->curpos;
        this->curpos = this->spline->getValue(poshere);//poshere;
        this->active = true;
    }
    else
    {
        this->active = false;
    }



}

void Henget::renderScene(float pos, float alpha)
{
    int i;
    cam->useCamera(0);


    for (i = 0; i < hcount; i++)
    {
        henget[i]->render(pos, alpha);

    }
    
    static int prevtime = 0;
    static int particlecumultime = 0;
    static int particleindex = 0;

    int currenttime = dmsGetModulePosition();
    int dt = currenttime - prevtime;
    prevtime = currenttime;

    if (dt < 0)
        dt = -dt; 

    particlecumultime += dt;
    const int maxcycles = 20;

    const int particleupdatelimit = 1000/300; //100 fps = 2-3 krt/frame
    if (particlecumultime > maxcycles*particleupdatelimit)
        particlecumultime = maxcycles*particleupdatelimit;

    while (particlecumultime > particleupdatelimit)
    {
        //lisätään particlet
        for (i = 0; i < hcount; i++)
        {
            if (henget[i]->active)
            {
                for (int j = 0; j < 8; j++)
                {
                    if (!particles[particleindex].active)
                    {
                        particles[particleindex].active = true;

                        float t = Mathematics::randFloat();
                        particles[particleindex].pos = henget[i]->curpos + (henget[i]->prevpos-henget[i]->curpos)*t 
                            + Mathematics::randVectSphere()*0.05f;
                        particles[particleindex].energy = Mathematics::randBetween(0.05f, 0.2f);
                        particles[particleindex].maxenergy = particles[particleindex].energy;
                        particles[particleindex].shade = henget[i]->shade;
                    }
                    particleindex++;
                    particleindex %= pcount;

                }
            }
        }

        //päivitetään particleja
        for (int j = 0; j < pcount; j++)
        {
            if (particles[j].active)
            {
                particles[j].energy -= 0.0005f;
                particles[j].pos.y -= (j%2)?0.001f:0.0007f;
                if (particles[j].energy < 0.0f)
                {
                    particles[j].active = false;
                }
            }
        }
        particlecumultime -= particleupdatelimit;
    }
    glEnable(GL_TEXTURE_2D);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE);
	glDisable(GL_DEPTH_TEST);
    //glBindTexture(GL_TEXTURE_2D, dmsGetTexture("greenparticle.jpg")->getID());
	glBindTexture(GL_TEXTURE_2D, dmsGetTexture("redparticle.jpg")->getID());

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

    glBegin(GL_QUADS);
    for (int j = 0; j < pcount; j++)
    {
        if (particles[j].active)
        {
            const float maxsize = 0.04f;
            float size = maxsize*(particles[j].energy / particles[j].maxenergy);
	        Vector v1 = particles[j].pos - x*size - y*size;
	        Vector v2 = particles[j].pos + x*size - y*size;
	        Vector v3 = particles[j].pos + x*size + y*size;
	        Vector v4 = particles[j].pos - x*size + y*size;
            glColor4f(1,1,1,alpha*0.7f*particles[j].shade);

            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();







}




Henget::Henget()
{	
    int i;
    hcount = 800;
    henget = new Henki*[hcount];

    for (i = 0; i < hcount; i++)
    {
        henget[i] = new Henki();
    }
    //pcount = 2000;
	pcount = 750;
    particles = new HenkiParticle[pcount];

    for (i = 0; i < pcount; i++)
    {
        particles[i].active = false;
    }

}

Henget::~Henget()
{
}


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

