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

#include <math.h>

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

void Pensas::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.init(true);
	renderScene(pos, alpha);
//    filter.glow(8, 0.005f, 0.005f, 0.92f, -1.0f, 1.0f);
}

void Pensas::renderScene(float pos, float alpha)
{
    int i = 0;

    Vector cam = Vector(0.2f, 0.4f, -2.5f);
    Vector tgt = Vector(0, 0.5f, 0);
    Vector upw = Vector(0, 1, 0);

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

    glRotatef(pos*460, 0, 1, 0);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA,GL_ONE);
    glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
    glEnable(GL_LINE_SMOOTH);
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_TEXTURE_2D);

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

    float kasvi_t = 1.0f;//fmodf(pos*6, 1);
    for (i = 0; i < kasvi->oksacount; i++)
    {
        float it = i / (float)kasvi->oksacount;
        glColor4f(kasvi->oksat[i]->color.x,
                  kasvi->oksat[i]->color.y,
                  kasvi->oksat[i]->color.z,
				  alpha);
                  //kasvi->oksat[i]->color.a*alpha);

        float oksa_t = 1.0f;//Mathematics::calcPosFloat(pos, kasvi->oksat[i]->st, kasvi->oksat[i]->et);

        if (oksa_t > 0.00001f)
        {
            glBegin(GL_LINE_STRIP);
            for (float t = 0.0f; t < oksa_t; t += 0.01f)
            {
                Vector point = kasvi->oksat[i]->polku->getValue(t);
                glVertex3fv((float *)&point);
            }
            glEnd();
        }
    }
}



Pensas::Pensas()
{	
    int i;
    int j;
    kcount = 1;
    srand(17);

    kasvi = new PensasKasvi();

    kasvi->oksacount = 150;
    kasvi->oksat = new Oksa*[kasvi->oksacount];

    for (i = 0; i < kasvi->oksacount; i++)
    {
        const int splinepoints = 15;
        kasvi->oksat[i] = new Oksa();
        kasvi->oksat[i]->polku = new CatmullRom(splinepoints);
        kasvi->oksat[i]->st = 0.0f;
        kasvi->oksat[i]->et = 0.0f;
        
        Vector startPos = Vector(0, 0, 0);
        Vector endPos = Vector(0, 0, 0);

        const float lengthRatio = 0.4f;
        const float kasvuMin = 0.1f;
        const float kasvuMax = 0.25f;

        int generation = 1;
        if (i == 0)
        {
            startPos = Vector(0, 0, 0);
            endPos = Vector(0, 1.5f, 0);
            kasvi->oksat[i]->color = Vector(0.4f,0.8f,0.4f);
            //kasvi->oksat[i]->color.a = 1.0f;
            generation = 1;
        }
        else if (i == 1)
        {
            float start_t = Mathematics::randFloat();

            kasvi->oksat[0]->st = start_t;
            kasvi->oksat[0]->et = start_t + kasvuMin + (kasvuMax - kasvuMin) * Mathematics::randFloat();

            startPos = kasvi->oksat[0]->polku->getValue(start_t);
            Vector parentStart = kasvi->oksat[0]->polku->getValue(0);
            Vector parentEnd = kasvi->oksat[0]->polku->getValue(1);
            float parentLength = (parentEnd - parentStart).length();

            endPos = startPos + Mathematics::randVectSphere()*parentLength*lengthRatio;//kasvi->oksat[0]->polku->getValue(start_t);
            kasvi->oksat[i]->color = Vector(0.4f,0.8f,0.4f);
            //kasvi->oksat[i]->color.a = 1.0f;
            generation = 2;
        }
        else
        {
            int index = rand() % i;
            generation = index + 1;

            //mitä suurempi index, sitä kauempana ollaan emorungosta
            float start_t = Mathematics::randFloat();

            startPos = kasvi->oksat[index]->polku->getValue(start_t);
            float st = Mathematics::calcPosFloat(start_t, kasvi->oksat[index]->st, kasvi->oksat[index]->et);

            kasvi->oksat[index]->st = st;
            kasvi->oksat[index]->et = st + kasvuMin + (kasvuMax - kasvuMin) * Mathematics::randFloat();

            Vector parentStart = kasvi->oksat[index]->polku->getValue(0);
            Vector parentEnd = kasvi->oksat[index]->polku->getValue(1);
            float parentLength = (parentEnd - parentStart).length();

            endPos = startPos + Mathematics::randVectSphere()*parentLength*lengthRatio;//kasvi->oksat[0]->polku->getValue(start_t);
            kasvi->oksat[i]->color = Vector(0.4f,0.8f,0.4f);
            //kasvi->oksat[i]->color.a = 1.0f;
            
        }
        if (endPos.y < startPos.y)
        {
            endPos.y += fabsf(endPos.y - startPos.y) * 3.5f;

        }

        //eka piste,joka ei siis ole splinessä
        kasvi->oksat[i]->polku->addPoint(startPos);
        kasvi->oksat[i]->polku->addPoint(startPos);

        for (j=0;j<splinepoints-2;j++)
        {
            const float jt = j / (float)splinepoints;
            Vector currentpos = startPos*(1-jt) + endPos*jt;

            Vector d = Vector(Mathematics::randFloat()-0.5f, 0.0f, Mathematics::randFloat()-0.5f) * 0.2f * powf(lengthRatio, generation*1.0f);
            kasvi->oksat[i]->polku->addPoint(currentpos + d);
        }
    }
}

Pensas::~Pensas()
{
    int i;
    for (i = 0; i < kasvi->oksacount; i++)
    {
        delete kasvi->oksat[i]->polku;
        delete kasvi->oksat[i];
    }
    delete [] kasvi->oksat;
    delete kasvi;
}


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