package simogl.effect.particle;

import javax.media.opengl.GL;

import com.sun.opengl.util.texture.Texture;

import simogl.geometry.Face;
import simogl.geometry.Point3D;
import simogl.geometry.Triangle;

/**
 * This class represents an abstract particle
 * @author Frank Bruns
 *
 */
public abstract class AbstractParticle
{
	private Triangle trig1 = null;
	private Triangle trig2 = null;
	private Point3D t1point1 = null;
	private Point3D t1point2 = null;
	private Point3D t1point3 = null;
	private Point3D t2point1 = null;
	private Point3D t2point2 = null;
	private Point3D t2point3 = null;
	protected Face face = null;
	
	
	protected Point3D position = null;
	protected Point3D velocity = null;
	
	protected long currentAge = 0L;
	protected long maximumAge = 0L;	
	protected float mass = 0.0f;
	protected float size = 0.0f;
	protected float[] color = {0f,0f,0f,1f};
	
	/**
	 * Creates a new particle
	 * @param size size of the particle
	 * @param position particle's position
	 * @param velocity particle's velocity 
	 * @param maxAge maximum age the particle can reach (in miliseconds)
	 */
	public AbstractParticle(float size, Point3D position, Point3D velocity, long maxAge)
	{
		this.size = size;
		this.position = position;
		this.velocity = velocity;
		this.maximumAge = maxAge;
		
		this.createFace();
	}
	
	/**
	 * Creates a new particle
	 * @param posX x-coordinate
	 * @param posY y-coordinate
	 * @param posZ z-coordinate
	 * @param velX x-velocity
	 * @param velY y-velocity
	 * @param velZ z-velocity
	 * @param maxAge maximum age the particle can reach (in miliseconds)
	 */
	public AbstractParticle(float posX, float posY, float posZ, float velX, float velY, float velZ, long maxAge)
	{
		this.position.setTo(posX,posY,posZ);
		this.velocity.setTo(velX,velY,velZ);
		this.maximumAge = maxAge;
		
		this.createFace();
	}

	/**
	 * Sets the RGBA color of the particle to the specified values
	 * @param red amount of red
	 * @param green amount of green
	 * @param blue amount of blue
	 * @param alpha alpha value
	 */
	public void setColor(float red, float green, float blue, float alpha)
	{
		this.color[0] = red;
		this.color[1] = green;
		this.color[2] = blue;
		this.color[3] = alpha;
	}
	
	/**
	 * Returns the RGBA color of the fog as an array of four values
	 * @return RGBA color of the fog
	 */
	public float[] getColor()
	{
		return this.color;
	}
	
	/**
	 * Set the alpha value of the particle to the specified parameter.
	 * @param alpha new alpha value
	 */
	public void setAlpha(float alpha)
	{
		this.color[3] = alpha;
	}
	
	/**
	 * Returns the alpha value of the particle
	 * @return particle's alpha value
	 */
	public float getAplha()
	{
		return this.color[3];
	}
	
	/**
	 * Returns the designated size of the particle
	 * @return particle's size
	 */
	public float getSize()
	{
		return this.size;
	}
	
	/**
	 * Sets the particle size to the specified value
	 * @param size particle's size
	 */
	public void setSize(float size)
	{
		this.size = size;
	}
	
	/**
	 * Returns the face that represents this particle in the scene
	 * @return face that represents the particle in the scene
	 */
	public Face getFace()
	{
		return this.face;
	}
	
	/**
	 * Returns the current age of the particle
	 * @return current particle age
	 */
	public long getCurrentAge()
	{
		return this.currentAge;
	}
	
	/**
	 * Sets the current particle age to the specified value
	 * @param age the new current particle age
	 */
	public void setCurrentAge(long age)
	{
		this.currentAge = age;
	}
	
	/**
	 * Returns the mass value for the particle
	 * @return mass of the particle
	 */
	public float getMass()
	{
		return this.mass;
	}
	
	/**
	 * Sets the particle's mass to the specified value
	 * @param mass new particle mass
	 */
	public void setMass(float mass)
	{
		this.mass = mass;
	}
	
	/**
	 * Returns the maximum age of the particle
	 * @return particle's maximum age
	 */
	public long getMaximumAge()
	{
		return this.maximumAge;
	}
	
	/**
	 * Sets the maximum age of the particle to the specified value
	 * @param maxAge new maximum age of the particle
	 */
	public void setMaximumAge(long maxAge)
	{
		this.maximumAge = maxAge;
	}
	
	/**
	 * Returns the current position of the particle
	 * @return particle's current position
	 */
	public Point3D getPosition()
	{
		return position;
	}
	
	/**
	 * Sets the particle to the specified coordinates
	 * @param position new particle position
	 */
	public void setPosition(Point3D position)
	{
		this.position.setTo(position);
	}
	
	/**
	 * Sets the particle to the specified coordinates
	 * @param x x-coordinate
	 * @param y y-coordinate
	 * @param z z-coordinate
	 */
	public void setPosition(float x, float y, float z)
	{
		this.position.setTo(x,y,z);
	}
	
	/**
	 * Returns the velocity of the particle as a directional vector
	 * @return particle's velocity
	 */
	public Point3D getVelocity()
	{
		return velocity;
	}
	
	/**
	 * Sets the particle's velocity to the specified values
	 * @param velocity new particle velocity
	 */
	public void setVelocity(Point3D velocity)
	{
		this.velocity.setTo(velocity);
	} 
	
	/**
	 * Sets the particle's velocity to the specified values
	 * @param x x-velocity
	 * @param y y-velocity
	 * @param z z-velocity
	 */
	public void setVelocity(float x, float y, float z)
	{
		this.velocity.setTo(x,y,z);
	}
	
	private void createFace()
	{
		// create face, that is the particle
		this.t1point1 = new Point3D(this.position.getX(), this.position.getY(), this.position.getZ());
		this.t1point2 = new Point3D(this.position.getX()+size, this.position.getY(), this.position.getZ());
		this.t1point3 = new Point3D(this.position.getX()+size, this.position.getY()+size, this.position.getZ());
		this.trig1 = new Triangle(t1point1,t1point2,t1point3);
		
		this.t2point1 = new Point3D(this.position.getX()+size, this.position.getY()+size, this.position.getZ());
		this.t2point2 = new Point3D(this.position.getX(), this.position.getY()+size, this.position.getZ());
		this.t2point3 = new Point3D(this.position.getX(), this.position.getY(), this.position.getZ());
		this.trig2 = new Triangle(t2point1,t2point2,t2point3);
		
		this.face = new Face(trig1,trig2);
	}
	
	/**
	 * Draws the particle to the scene
	 * @param gl
	 * @param x x-coordinate
	 * @param y y-coordinate
	 * @param z z-coordinate
	 * @param texture texture to assign to the particle
	 */
	public abstract void draw(GL gl, float x, float y, float z, Texture texture);
}
