#include <stdlib.h>
#include <stdio.h>
#include <dms/dms.h>
#include "fountainParticles.h"

#define MAX_LIFETIME 1

struct _particle
    {
     dms::Vector3 position;
     dms::Vector3 tailPosition;
     dms::Vector3 velocity;
     dms::Vector3 color;
     float removeTime;
    };


fountainParticles::fountainParticles(int numParticles,dms::Vector3 center,float radius)
    {
    posCenter_ = center;
    posRadius_ = radius;
    tailOffset_.set(0, -0.5, 0);
    colorMin_.set(0.05, 0.5, 0.75);
    colorMax_.set(0.15, 0.8, 0.8);
    numParticles_ = numParticles;
    particles_ = new struct _particle[numParticles_];
    gravity_.set(0, -32, 0);
    wind_.set(0, 0, 0);
    }


void fountainParticles::setGravity(dms::Vector3 gravity)
    {
    gravity_ = gravity;
    }


void fountainParticles::setWind(dms::Vector3 wind)
    {
    wind_ = wind;
    }


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


void fountainParticles::initParticle(int n)
    {
    float radius = dms::randomFloat(0, posRadius_);
    dms::Vector2 pos = dms::randomUnitVector2() * radius;
    dms::Vector2 vel = dms::randomUnitVector2() * dms::randomFloat(0, 3);
    particles_[n].velocity.set(vel[0], 16, vel[1]);
    particles_[n].position[0] = pos[0] + posCenter_[0];
    particles_[n].position[1] = posCenter_[1];
    particles_[n].position[2] = pos[1] + posCenter_[2];
    particles_[n].position += particles_[n].velocity
                              * dms::randomFloat(0, dms::deltaTime());
    particles_[n].tailPosition = particles_[n].position + tailOffset_;
    particles_[n].color = dms::randomPoint3(colorMin_, colorMax_);
    particles_[n].removeTime = dms::frameTime() 
                               + MAX_LIFETIME * (1.0 - radius/posRadius_)
                               + dms::randomFloat(-0.1, 0.1);
    }


void fountainParticles::update(void)
    {
    float dt = dms::deltaTime();
    float now = dms::frameTime();
    dms::Vector3 gravityAccel = gravity_ * dt;
    dms::Vector3 windAccel = wind_ * dt;
    for (int i=0; i < numParticles_; i++)
        {
        if (particles_[i].removeTime <= now)
            initParticle(i);
        particles_[i].velocity += gravityAccel;
        particles_[i].velocity += windAccel;
        particles_[i].tailPosition = particles_[i].position;
        particles_[i].position += particles_[i].velocity * dt;
        }
    }


void fountainParticles::draw(void)
    {
    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE, GL_ONE);
    glDepthMask(GL_FALSE);
    glBegin(GL_LINES);
    for (int i=0; i < numParticles_; i++)
        {
        glColor3fv(particles_[i].color.vec);
        glVertex3fv(particles_[i].tailPosition.vec);
        glVertex3fv(particles_[i].position.vec);
        }
    glEnd();
    glDepthMask(GL_TRUE);
    glBlendFunc(GL_ONE, GL_ZERO);
    glDisable(GL_BLEND);
    }

