#include "cParticleSystem.h"

cParticleSystem::cParticleSystem()
{
    
    dropletImage_.loadTGA("waterdrop.tga", false);
    cloudPuffImage_.loadTGA("cloudpuff.tga", false);
    holeArrowImage_.loadTGA("arrow.tga", false);
    smileyImage_.loadTGA("smiley.tga", false);
}

void cParticleSystem::clearNonText()
{
    // clear out any leftover particles
    list<cSplashParticle*>::iterator j;
    for(j = splashes_.begin(); j != splashes_.end(); ++j)
        delete (*j);

    list<cSmokeRingParticle*>::iterator s;
    for(s = smokeRings_.begin(); s != smokeRings_.end(); ++s)
        delete (*s);
        
    list<cHoleArrowParticle*>::iterator h;
    for(h = holeArrows_.begin(); h != holeArrows_.end(); ++h)
        delete (*h);

	list<cSnowParticle*>::iterator x;
    for(x = snow_.begin(); x != snow_.end(); ++x)
        delete (*x);
    
    splashes_.clear(); 
    smokeRings_.clear();
    holeArrows_.clear(); 
	snow_.clear();
}

void cParticleSystem::setLevel(int level)
{
    level_ = level;
    age_ = 0;
    
    cHoleArrowParticle* p = addHoleArrow();
    switch(level)
    {
    case 1: p->position_ = cVector(28.6923, 15, 39.114); break;
    case 2: p->position_ = cVector(60.5945, .9109, 159.748); break;
	case 3: p->position_ = cVector(88.9361, 14.57943, -44.1391); break;
	case 4: p->position_ = cVector(127.707, 23.72946, -132.746); break;
    }
    
    killText();
}

void cParticleSystem::addSmiley()
{
    float a = ((float)(rand()%100))/100.0f;
    float b = ((float)(rand()%100))/100.0f;
    addSmokeText(smileyImage_, 0, 0 );
}

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)); 
        p->r_ = 1; p->g_ =1; p->b_ = 1;
    	p->size_ = .2;
        p->maxAge_ = 10;
    }
}

void cParticleSystem::killText()
{
    list<cSmokeTextParticle*>::iterator t;
    for(t = smokeText_.begin(); t != smokeText_.end(); ++t)
        (*t)->maxAge_ = (*t)->age_ + 3;
}

void cParticleSystem::addSmokeText(cTextureImage& image, float centerX, float centerY)
{
    float scale = 6 * 1 / (float)image.height;
    
    for(int j = 0; j < image.height; ++j)
    {
        for(int i = 0; i < image.width; ++i)
        {
            int b = image.getPixelB(i,j);

            if( b>5 && rand()%5 == 1) 
            {	
                float a = ((float)(rand()%100))/100.0f;
                float b = ((float)(rand()%100))/100.0f;
                float c = ((float)(rand()%100))/100.0f;
    
                cSmokeTextParticle *p = addSmokeTextParticle();
                p->position_ = .1 * cVector(b-.5, c-.5, a-.5);
                p->goal_ = cVector(((float)i - (float)image.width/2.0 ) * scale  + centerX, ((float)j - (float)image.width/2.0) * scale + centerY, 0);
                p->velocity_ = .1 * cVector(a-.5,b-.5,c-.5); 
                p->r_ = 1; p->g_ =1; p->b_ = 1;
                p->size_ = .1;
                p->maxAge_ = 1000000;
            }
        }
    }
}



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

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

cHoleArrowParticle* cParticleSystem::addHoleArrow()
{
    cHoleArrowParticle* s = new cHoleArrowParticle(this);
    holeArrows_.push_back(s);
    return s;
}

cSmokeTextParticle* cParticleSystem::addSmokeTextParticle()
{
    cSmokeTextParticle* s = new cSmokeTextParticle(this);
    smokeText_.push_back(s);
    return s;
}

cSnowParticle* cParticleSystem::addSnowParticle()
{
    cSnowParticle* s = new cSnowParticle(this);
    snow_.push_back(s);
    return s;
}




list<cSplashParticle*>::iterator cParticleSystem::removeSplash(list<cSplashParticle*>::iterator& i)
{
    cSplashParticle* p = *i;
    list<cSplashParticle*>::iterator newI = splashes_.erase(i);
    delete p;
    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;
}

list<cSmokeTextParticle*>::iterator cParticleSystem::removeSmokeTextParticle(list<cSmokeTextParticle*>::iterator& i)
{
    cSmokeTextParticle* s = *i;
    list<cSmokeTextParticle*>::iterator newI = smokeText_.erase(i);
    delete s;
    return newI;
}

list<cSnowParticle*>::iterator cParticleSystem::removeSnowParticle(list<cSnowParticle*>::iterator& i)
{
    cSnowParticle* s = *i;
    list<cSnowParticle*>::iterator newI = snow_.erase(i);
    delete s;
    return newI;
}




cParticleSystem::~cParticleSystem()
{
    
    list<cSplashParticle*>::iterator j;
    for(j = splashes_.begin(); j != splashes_.end(); ++j)
        delete (*j);

    list<cSmokeRingParticle*>::iterator s;
    for(s = smokeRings_.begin(); s != smokeRings_.end(); ++s)
        delete (*s);
        
    list<cHoleArrowParticle*>::iterator h;
    for(h = holeArrows_.begin(); h != holeArrows_.end(); ++h)
        delete (*h);
        
    list<cSmokeTextParticle*>::iterator t;
    for(t = smokeText_.begin(); t != smokeText_.end(); ++t)
        delete (*t);

	list<cSnowParticle*>::iterator x;
    for(x = snow_.begin(); x != snow_.end(); ++x)
        delete (*x);
}

void cParticleSystem::update(float dt)
{

    age_ += dt * .8;
    
    vector<cTriangle*> tlist;
    
    list<cSplashParticle*>::iterator j;
    for(j = splashes_.begin(); j != splashes_.end(); ++j)
    {
        if( (*j)->dead_) j = removeSplash(j);
        else (*j)->update(dt);
    }

    
    if(level_ == 1 && rand()%50 == 1)
        addSmokeRing(cVector(-33.244373, 45.455059, 1.978926));
    
	if(level_ == 4)
	{
		addSnowParticle();
		addSnowParticle();
		addSnowParticle();
	}
    
    list<cSmokeRingParticle*>::iterator s;
    for(s = smokeRings_.begin(); s != smokeRings_.end(); ++s)
    {
        if( (*s)->dead_) s = removeSmokeRingParticle(s);
        else (*s)->update(dt);
    }
    
    list<cSmokeTextParticle*>::iterator t;
    for(t = smokeText_.begin(); t != smokeText_.end(); ++t)
    {
        if( (*t)->dead_) t = removeSmokeTextParticle(t);
        else (*t)->update(dt);
    }

	list<cSnowParticle*>::iterator x;
    for(x = snow_.begin(); x != snow_.end(); ++x)
	{
		if( (*x)->dead_) x = removeSnowParticle(x);
        else (*x)->update(dt);
    }

    
    list<cHoleArrowParticle*>::iterator h;
    for(h = holeArrows_.begin(); h != holeArrows_.end(); ++h)
        (*h)->update(dt);
    
}

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

    glEnable(GL_BLEND);									// Enable Blending
    glBlendFunc(GL_SRC_ALPHA, GL_ONE);	
    glDepthMask(GL_FALSE);
    
    dropletImage_.bindGLTexture();
    
    
    list<cSplashParticle*>::iterator j;
    for(j = splashes_.begin(); j != splashes_.end(); ++j)
        (*j)->draw();
        
    cloudPuffImage_.bindGLTexture();
        
    list<cSmokeRingParticle*>::iterator s;
    for(s = smokeRings_.begin(); s != smokeRings_.end(); ++s)
        (*s)->draw();
    
	list<cSnowParticle*>::iterator x;
    for(x = snow_.begin(); x != snow_.end(); ++x)
		(*x)->draw();

    glPushMatrix();
    glLoadIdentity(); // clear the last transformation
    gluLookAt(	0, 0, 10,
                0, 0, 0,
                0, 1, 0);
        
    list<cSmokeTextParticle*>::iterator t;
    for(t = smokeText_.begin(); t != smokeText_.end(); ++t)
        (*t)->draw();
        
    glPopMatrix();

    holeArrowImage_.bindGLTexture();
    list<cHoleArrowParticle*>::iterator h;
    for(h = holeArrows_.begin(); h != holeArrows_.end(); ++h)
        (*h)->draw();
        
    glDisable(GL_BLEND);	
    glDepthMask(GL_TRUE);
}