#include <stdlib.h>
#include <math.h>
#include <dms/dms.h>
#include "gasParticles.h"

#define MAX_LIFETIME 15

struct _particle
    {
     dms::Vector3 position;
     dms::Vector3 offset;
     float removeTime;
    };


gasParticles::gasParticles(int numParticles,dms::Vector3 center,float radius)
    {
    posCenter_ = center;
    posRadius_ = radius;
    numParticles_ = numParticles;
    particles_ = new struct _particle[numParticles_];
    width_ = 0.2;
    height_ = 0.2;
    }


void gasParticles::initialize(void)
    {
    for (int i=0; i < numParticles_; i++)
        {
        initParticle(i);
        particles_[i].removeTime = dms::frameTime()
                                   + dms::randomFloat(0,MAX_LIFETIME);
        }
    }


void gasParticles::initParticle(int n)
    {
    float radius = dms::randomFloat(0, posRadius_);
    particles_[n].offset = dms::randomUnitVector3() * radius;
    particles_[n].position = posCenter_ + particles_[n].offset;
    particles_[n].removeTime = dms::frameTime() + MAX_LIFETIME; 
    }


void gasParticles::update(void)
    {
    float now = dms::frameTime();
    for (int i=0; i < numParticles_; i++)
        {
        if (particles_[i].removeTime <= now)
            initParticle(i);
        float t = particles_[i].removeTime - now + 3;
        if (t > MAX_LIFETIME)
            {
            particles_[i].position[0] = MAX_LIFETIME/3 * sin(MAX_LIFETIME*1.05)
                                        - (t-MAX_LIFETIME)*2;
            particles_[i].position[1] = 0;
            particles_[i].position[2] = MAX_LIFETIME/3 * cos(MAX_LIFETIME*1.05);
            particles_[i].position += particles_[i].offset * (t-MAX_LIFETIME);
            }
        else
            {
            particles_[i].position[0] = t/3 * sin(t*1.05);
            particles_[i].position[1] = 0;
            particles_[i].position[2] = t/3 * cos(t*1.05);
            particles_[i].position += particles_[i].offset;
            }
        }
    }


void gasParticles::draw(void)
    {
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE);
    glDepthMask(GL_FALSE);
    glBegin(GL_QUADS);
    glColor3fv(dms::Color::White.vec);
    for (int i=0; i < numParticles_; i++)
        {
        glTexCoord2f(0, 0);
        glVertex3f(particles_[i].position.vec[0] - width_,
                   particles_[i].position.vec[1] - height_,
                   particles_[i].position.vec[2]);
        glTexCoord2f(1, 0);
        glVertex3f(particles_[i].position.vec[0] + width_,
                   particles_[i].position.vec[1] - height_,
                   particles_[i].position.vec[2]);
        glTexCoord2f(1, 1);
        glVertex3f(particles_[i].position.vec[0] + width_,
                   particles_[i].position.vec[1] + height_,
                   particles_[i].position.vec[2]);
        glTexCoord2f(0, 1);
        glVertex3f(particles_[i].position.vec[0] - width_,
                   particles_[i].position.vec[1] + height_,
                   particles_[i].position.vec[2]);
        }
    glEnd();
    glDepthMask(GL_TRUE);
    glBlendFunc(GL_ONE, GL_ZERO);
    glDisable(GL_BLEND);
    
    glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
    glBegin(GL_QUADS);
    glColor3fv(dms::Color::White.vec);
    for (int i=0; i < numParticles_; i++)
        {
        glTexCoord2f(0, 0);
        glVertex3f(particles_[i].position.vec[0] - width_,
                   particles_[i].position.vec[1] - height_,
                   particles_[i].position.vec[2]);
        glTexCoord2f(1, 0);
        glVertex3f(particles_[i].position.vec[0] + width_,
                   particles_[i].position.vec[1] - height_,
                   particles_[i].position.vec[2]);
        glTexCoord2f(1, 1);
        glVertex3f(particles_[i].position.vec[0] + width_,
                   particles_[i].position.vec[1] + height_,
                   particles_[i].position.vec[2]);
        glTexCoord2f(0, 1);
        glVertex3f(particles_[i].position.vec[0] - width_,
                   particles_[i].position.vec[1] + height_,
                   particles_[i].position.vec[2]);
        }
    glEnd();
    glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
    }
