#include "cParticleSystem.h"

cParticleSystem::cParticleSystem(cStaticTriangleMesh* objects)
: objects_(objects)
{
    age_ = 0;
    
    //dropletImage_.loadTGA("waterdrop.tga");
    cloudPuffImage_.loadTGA("cloudpuff.tga", false);
    fireflyImage_.loadTGA("firefly.tga", false);
    
    cloudCenter_ = cVector(0,15,0);
    
    //for(int i = 0; i < 10; ++i)
    //    addCloud();
        
    for(int i = 0; i < 50; ++i)
        addFirefly();
}

void cParticleSystem::addSmokeRing(cVector origin)
{
    int numParticles = 50;
    float a = ((float)(rand()%100))/100.0f; 
    for(int i = 0; i < numParticles; ++i)
    {
        cSmokeRingParticle *p = addSmokeRingParticle();
        p->position_ = origin;
        
        float theta = 2 * 3.1415926 * (float)i / (float)numParticles;
        
        p->velocity_ = cVector(.07*a + .05, .008*sin(theta),.008*cos(theta)); 
    }
}

cRaindrop* cParticleSystem::addRaindrop()
{
    cRaindrop* r = new cRaindrop(this);
    raindrops_.push_back(r);
    return r;
}

cSplashParticle* cParticleSystem::addSplash()
{
    cSplashParticle* p = new cSplashParticle(this);
    splashes_.push_back(p);
    return p;
}

cCloudParticle* cParticleSystem::addCloud()
{
    cCloudParticle* c = new cCloudParticle(this);
    clouds_.push_back(c);
    return c;
}

cFireflyParticle* cParticleSystem::addFirefly()
{
    cFireflyParticle* f = new cFireflyParticle(this);
    fireflies_.push_back(f);
    return f;
}

cSmokeRingParticle* cParticleSystem::addSmokeRingParticle()
{
    cSmokeRingParticle* s = new cSmokeRingParticle(this);
    smokeRings_.push_back(s);
    return s;
}



list<cRaindrop*>::iterator cParticleSystem::removeRaindrop(list<cRaindrop*>::iterator& i)
{
    cRaindrop* r = *i;
    list<cRaindrop*>::iterator newI = raindrops_.erase(i);
    delete r;
    return newI;
}

list<cSplashParticle*>::iterator cParticleSystem::removeSplash(list<cSplashParticle*>::iterator& i)
{
    cSplashParticle* p = *i;
    list<cSplashParticle*>::iterator newI = splashes_.erase(i);
    delete p;
    return newI;
}

list<cCloudParticle*>::iterator cParticleSystem::removeCloud(list<cCloudParticle*>::iterator& i)
{
    cCloudParticle* c = *i;
    list<cCloudParticle*>::iterator newI = clouds_.erase(i);
    delete c;
    return newI;
}


list<cSmokeRingParticle*>::iterator cParticleSystem::removeSmokeRingParticle(list<cSmokeRingParticle*>::iterator& i)
{
    cSmokeRingParticle* s = *i;
    list<cSmokeRingParticle*>::iterator newI = smokeRings_.erase(i);
    delete s;
    return newI;
}



cParticleSystem::~cParticleSystem()
{
    list<cRaindrop*>::iterator i;
    for(i = raindrops_.begin(); i != raindrops_.end(); ++i)
        delete (*i);
    
    list<cSplashParticle*>::iterator j;
    for(j = splashes_.begin(); j != splashes_.end(); ++j)
        delete (*j);
        
    list<cCloudParticle*>::iterator k;
    for(k = clouds_.begin(); k != clouds_.end(); ++k)
        delete (*k);
        
         
    list<cFireflyParticle*>::iterator l;
    for(l = fireflies_.begin(); l != fireflies_.end(); ++l)
        delete (*l);
        
    list<cSmokeRingParticle*>::iterator s;
    for(s = smokeRings_.begin(); s != smokeRings_.end(); ++s)
        delete (*s);
}

void cParticleSystem::update(float dt)
{
    /*
    age_ += dt * .8;
    cloudCenter_ = cVector(60 * cos(age_*.123152352) + 3 * sin(age_ *.32 + 3), 50 + 10 * cos(age_*.2), 60 * sin(age_*.13123 + cos(age_*.4)));
    cloudRadius_ = 3 + 1 * cos(age_ * .4);
    
    float r = 4 * cloudRadius_;
    box_.xmin_ = cloudCenter_.x_ - r;
    box_.xmax_ = cloudCenter_.x_ + r;
    box_.ymin_ = -50;
    box_.ymax_ = cloudCenter_.y_ + 10;
    box_.zmin_ = cloudCenter_.z_ - r;
    box_.zmax_ = cloudCenter_.z_ + r;
    
    
    objects_->octree_.buildCollisionList(tlist, box_); 
    // reset flags, note that triangle flags were set by octree
    for(unsigned int i = 0; i < tlist.size(); ++i)
        tlist[i]->hasBeenAddedToCollisionList_ = false;
     
    list<cRaindrop*>::iterator i;
    for(i = raindrops_.begin(); i != raindrops_.end(); ++i)
    {
        if( (*i)->dead_) i = removeRaindrop(i);
        else (*i)->update(dt, tlist);
    }
    
    list<cSplashParticle*>::iterator j;
    for(j = splashes_.begin(); j != splashes_.end(); ++j)
    {
        if( (*j)->dead_) j = removeSplash(j);
        else (*j)->update(dt, tlist);
    }
    
    list<cCloudParticle*>::iterator k;
    for(k = clouds_.begin(); k != clouds_.end(); ++k)
    {
        if( (*k)->dead_) k = removeCloud(k);
        else (*k)->update(dt, tlist);
    }
    */
    
    vector<cTriangle*> tlist;
    
    if(rand()%50 == 1)
        addSmokeRing(cVector(-33.244373, 45.455059, 1.978926));
    
    
    list<cFireflyParticle*>::iterator l;
    for(l = fireflies_.begin(); l != fireflies_.end(); ++l)
        (*l)->update(dt, tlist);
        
    list<cSmokeRingParticle*>::iterator s;
    for(s = smokeRings_.begin(); s != smokeRings_.end(); ++s)
    {
        if( (*s)->dead_) s = removeSmokeRingParticle(s);
        else (*s)->update(dt, tlist);
    }
    
}

void cParticleSystem::draw()
{
    //box_.draw();

    glEnable(GL_BLEND);									// Enable Blending
    glBlendFunc(GL_SRC_ALPHA, GL_ONE);	
    glDepthMask(GL_FALSE);
    
    //dropletImage_.bindGLTexture();
    
    //list<cRaindrop*>::iterator i;
    //for(i = raindrops_.begin(); i != raindrops_.end(); ++i)
    //    (*i)->draw();
    
    //list<cSplashParticle*>::iterator j;
    //for(j = splashes_.begin(); j != splashes_.end(); ++j)
    //    (*j)->draw();
        
    cloudPuffImage_.bindGLTexture();
        
    //list<cCloudParticle*>::iterator k;
    //for(k = clouds_.begin(); k != clouds_.end(); ++k)
    //    (*k)->draw();
        
    list<cSmokeRingParticle*>::iterator s;
    for(s = smokeRings_.begin(); s != smokeRings_.end(); ++s)
        (*s)->draw();
        
    fireflyImage_.bindGLTexture();
    
    list<cFireflyParticle*>::iterator l;
    for(l = fireflies_.begin(); l != fireflies_.end(); ++l)
        (*l)->draw();;
        
    glDisable(GL_BLEND);	
    glDepthMask(GL_TRUE);
}