package simogl.effect.particle;

import java.util.ArrayList;

import simogl.geometry.Point3D;

/**
 * This class is used to store and manage a set of similar particles
 * @author Frank Bruns
 *
 */
public class ParticleContainer
{
	private ArrayList<AbstractParticle> particles = null;
	private int maxNumberOfParticles = 0;
	
	/**
	 * Creates a new container for particles 
	 *
	 */
	public ParticleContainer(int maxNumberOfParticles)
	{
		this.maxNumberOfParticles = maxNumberOfParticles;
		this.particles = new ArrayList<AbstractParticle>();
	}
	
	/**
	 * Adds a particle to the particle container
	 * @param particle particle to add
	 */
	public synchronized void addParticle(AbstractParticle particle)
	{
		this.particles.add(particle);
	}
	
	/**
	 * Removes the specified particle from the container
	 * @param particle particle to remove
	 */
	public synchronized void deleteParticle(AbstractParticle particle)
	{
		this.particles.remove(particle);
	}
	

	/**
	 * Removes every particle from the container. The container will be
	 * empty after this operation.
	 *
	 */
	public synchronized void deleteAll()
	{
		this.particles.clear();
	}
	
	/**
	 * Updates the particles in the container according to the amount of
	 * time passed since the last update
	 * @param elapsedTime time between two frames
	 */
	public synchronized void update(long elapsedTime)
	{		
		for(AbstractParticle part : this.particles)
		{
			// update the particle's age
			part.setCurrentAge(part.getCurrentAge() + elapsedTime);			
			
			Point3D newPosition = part.getPosition().copy();
			Point3D curVel = part.getVelocity().copy();		
			
			// multiply the particles velocity with the elapsedTime
			// parameter to get framerate independent and then add
			// the velocity to the particle's position to get its
			// new position
			curVel.multiply(elapsedTime/1000f);
			newPosition.add(curVel);
			part.setPosition(newPosition);
			
			// change alpha value -> get it more transparent (total transparance at maxAge)
			part.setAlpha(1f - ((float)part.getCurrentAge()/(float)part.getMaximumAge()));
		}
		
		// delete dead particles
		this.clean();
	}
	
	/**
	 * This method removes all particles from the container that have
	 * already reached their maximum age and therefore shall not be
	 * used anymore.
	 *
	 */
	public synchronized void clean()
	{
		ArrayList<AbstractParticle> deadParticles = new ArrayList<AbstractParticle>();
		
		// loop through the list of particles and find the dead ones
		for(AbstractParticle part : this.particles)
		{
			if(part.getCurrentAge() >= part.getMaximumAge())
			{
				deadParticles.add(part);
			}
		}
		
		// remove the found dead particles from the list
		this.particles.removeAll(deadParticles);
	}
	
	/**
	 * Return a list with all the particles in the container
	 * @return all particles
	 */
	public ArrayList<AbstractParticle> getParticles()
	{
		return this.particles;
	}
	
	/**
	 * Returns the number of particles in the particle container
	 * @return number of particles
	 */
	public int getParticleCount()
	{
		return this.particles.size();
	}
	
	/**
	 * Returns the maximum possible number of particles in the 
	 * container
	 * @return maximum number of possible particles
	 */
	public int getMaximumParticles()
	{
		return this.maxNumberOfParticles;
	}
	
	/**
	 * Sets the maximum number of particles possible in the container
	 * @param number maximum number of possible particles
	 */
	public void setMaximumParticles(int number)
	{
		this.maxNumberOfParticles = number;
	}
	
	
}
