#include "particleSystem.h"
#include "control.h"
#include "input.h"

ParticleSystem::ParticleSystem(){
name="ParticleSystem";
shaderProgramName="textureAlpha";
//was: textureAlpha
vertexShaderFileName="shaders/textureAlpha.vert";
fragmentShaderFileName="shaders/textureAlpha.frag";

texture="base";

menuType.push_back("14MakeGridButton");

bTextured=true;
bAlphaBlend=true;
bUseShader=true;

drawType=DRAW_PARTICLES;
registerProperties();
}

void ParticleSystem::addParticles(int amount){
     for (int i=0;i<amount; i++)
       {
       Particle p;
       p.birth=0.0;
       p.color=Vector4f(1,1,1,1);       //last one for scale!
       particles.push_back(p);
       }
}

void ParticleSystem::addRandomParticles(int amount, float diameter){
 for (int i=0;i<amount;i++)
     {
     Particle p;
     p.location.x=((double)rand()/(double)RAND_MAX) * diameter;
     p.location.y=((double)rand()/(float)RAND_MAX) * diameter;
     p.location.z=((double)rand()/(float)RAND_MAX) * diameter;
     p.location.w=1.0; //scale!!!
     p.color=Vector4f((float)rand()/(float)RAND_MAX,(float)rand()/(float)RAND_MAX,(float)rand()/(float)RAND_MAX,1);
     p.birth=i;
     particles.push_back(p);
     }
}

void ParticleSystem::createSquare(float xStretch, float zStretch){
     int i=0;

     for (int rows=0;rows<sqrt((double)particles.size());rows++)
       {
       for (int columns=0;columns<sqrt((double)particles.size());columns++)
         {
         particles[i].location.x=xStretch*columns;
         particles[i].location.z=zStretch*rows;
         particles[i].color.r=0.01*columns;
         particles[i].color.g=0.001*rows;
         particles[i].color.b=1;
         particles[i].color.a=1;
         particles[i].birth=rows;
         i++;
         }
       }
}


void ParticleSystem::setup(){
     Actor::setup();
}

void ParticleSystem::linkShaderVariables(){

Actor::linkShaderVariables();
//glBindAttribLocation(
}


void ParticleSystem::update(double deltaTime){
     elapsedTime+=deltaTime;
}

void ParticleSystem::updateShaders(){
     Actor::updateShaders();
}


void ParticleSystem::drawParticles(){

if (!Control::bRunning)
  {
    glDisable(GL_TEXTURE_2D);
    glUseProgram(0);

    glColor4f(color.r,color.g,color.b,color.a);
    glutSolidCube(scale.x/10);

    glUseProgram(shaderProgram);
    glEnable(GL_TEXTURE_2D);
  }

  //Enable Point sprite textures, Vertex Shader point-size control and the point sprite extension
  glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE );
  glEnable( GL_VERTEX_PROGRAM_POINT_SIZE );
  glEnable( GL_POINT_SPRITE_ARB );

if (particles.size()>0)
  {
  GLfloat *verts=&particles[0].location.x;
  GLfloat *colors=&particles[0].color.r;

  glVertexPointer(4, GL_FLOAT,sizeof(particles[0]),verts);
  glColorPointer(4, GL_FLOAT,sizeof(particles[0]),colors);

  glEnableClientState(GL_VERTEX_ARRAY);
  glEnableClientState(GL_COLOR_ARRAY);

  glDrawArrays(GL_POINTS,0,particles.size());

  glDisableClientState(GL_VERTEX_ARRAY);
  glDisableClientState(GL_COLOR_ARRAY);
  }

  glDisable(GL_POINT_SPRITE_ARB);
}




void ParticleSystem::create(){

addActor(this);
std::cout << "created a ParticleSystem! \n";
}

TiXmlElement* ParticleSystem::save(TiXmlElement *root){

TiXmlElement * element = Actor::save(root);
for (int i=0;i<particles.size();i++)
    {
    TiXmlElement * pElement = new TiXmlElement("particle");

        TiXmlElement * mElement = new TiXmlElement("location");
        char loc[50];
        sprintf(loc,"vec4f %f %f %f %f", particles[i].location.x, particles[i].location.y, particles[i].location.z, particles[i].location.w);
        mElement->LinkEndChild(new TiXmlText(loc));
        pElement->LinkEndChild( mElement );

        mElement = new TiXmlElement("color");
        char col[50];
        sprintf(col,"vec4f %f %f %f %f", particles[i].color.r, particles[i].color.g, particles[i].color.b, particles[i].color.a);
        mElement->LinkEndChild(new TiXmlText(col));
        pElement->LinkEndChild( mElement );

        mElement = new TiXmlElement("birth");
        char bir[50];
        sprintf(bir,"float %f", particles[i].birth);
        mElement->LinkEndChild(new TiXmlText(bir));
        pElement->LinkEndChild( mElement );

    element->LinkEndChild( pElement );
    }
return element;
}

void ParticleSystem::load(TiXmlElement *myInfo){

Actor::load(myInfo);

TiXmlElement * element;
element=myInfo->FirstChildElement( "particle" );

    for( element; element!=NULL; element=element->NextSiblingElement())
	{
      addParticles(1);
      TiXmlElement * property=NULL;
      property=element->FirstChildElement("location");

      if (property)
        particles[particles.size()-1].location=readVector4f((char*)property->GetText());

      property=NULL;
      property=element->FirstChildElement("color");

      if (property)
        particles[particles.size()-1].color=readVector4f((char*)property->GetText());

      property=NULL;
      property=element->FirstChildElement("birth");

      if (property)
        particles[particles.size()-1].birth=readFloat((char*)property->GetText());
    }
}
