package j3deditor.bin.hierarchy;

import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;


/**
 * Represents a vertex that contains its own
 * vertex data.
 * 
 * @author Risto Seene
 */
public class VirtualVertex extends Vertex{

	/** positional coordinates */
	private Point3f loc = null;

	/** texture coordinates */
	private float[][] texCoords;

	/** normal vector */
	private Vector3f normal = null;

	/** vertex volor */
	private float[] color;


	/**
	 * Creates an instance of <code>VirtualVertex</code> and
	 * initializes its components which are required by <code>J3DeGeometryArray</code>.
	 * 
	 * @param g
	 * 	<code>J3DeGeometryArray</code>
	 * @param index
	 * 	the index of this vertex
	 */
	protected VirtualVertex(J3DeGeometryArray g, int index){
		super(g, index);
		loc = new Point3f();
		texCoords = new float[g.getTexCoordSetCount()][g.getTexCoordType()];
		for(int i=0; i<g.getTexCoordSetCount(); i++){
			for(int j=0; j<g.getTexCoordType(); j++){
				texCoords[i][j] = 0;
			}
		}
	          if(g.hasNormals()){
	                    this.normal = new Vector3f();
	          }
		if(g.hasColor()){
			this.color = new float[g.getColorType()];
			for(int i=0; i<color.length; i++){
				this.color[i] = 0;
			}
		}
	}

	/**
	 * Creates an instance of <code>VirtualVertex</code> with the specified coordinates and
	 * initializes its components which are required by <code>J3DeGeometryArray</code>.
	 * 
	 * @param g
	 * 	<code>J3DeGeometryArray</code>
	 * @param loc
	 * 	positional coordinates
	 * @param index
	 * 	the index of this vertex
	 */
	protected VirtualVertex(J3DeGeometryArray g, Point3f loc, int index){
		this(g, index);
		this.loc = new Point3f(loc);
	}

	/**
	 * Creates an instance of <code>VirtualVertex</code> with the specified coordinates and
	 * initializes its components which are required by <code>J3DeGeometryArray</code>.
	 * 
	 * @param g
	 * 	<code>J3DeGeometryArray</code>
	 * @param x
	 * 	X coordiante
	 * @param y
	 * 	Y coordiante
	 * @param z
	 * 	Z coordiante
	 * @param index
	 * 	the index of this vertex
	 */
	protected VirtualVertex(J3DeGeometryArray g, float x, float y, float z, int index){
		this(g, index);
		this.loc = new Point3f(x, y, z);
	}

	/**
	 * Creates an instance of <code>VirtualVertex</code> and copies
	 * all vertex data from the specified vertex to this vertex.
	 * 
	 * @param vertex
	 * 	vertex which data will be copied to this vertex
	 */
	protected VirtualVertex(Vertex vertex){
	          super(vertex.getGeometry(), vertex.getIndex());
		this.setState(vertex.getState(Vertex.COORDINATE_VERTEX_STATE), Vertex.COORDINATE_VERTEX_STATE);
	          this.setState(vertex.getState(Vertex.TEXTURE_VERTEX_STATE), Vertex.TEXTURE_VERTEX_STATE);
		J3DeGeometryArray g = vertex.getGeometry();
	          loc = new Point3f(vertex.getCoordinate());
	          texCoords = new float[g.getTexCoordSetCount()][g.getTexCoordType()];
	          for(int i=0; i<g.getTexCoordSetCount(); i++){
	                    for(int j=0; j<g.getTexCoordType(); j++){
	                              texCoords[i][j] = vertex.getTex(j, i);
	                    }
	          }
		if(g.hasNormals()){
			this.normal = new Vector3f(vertex.getNormal());
		}
	          if(g.hasColor()){
			this.color = new float[g.getColorType()];
			this.setColor(vertex.getColor());
	          }
	}
	

	/**
	 * Returns the positional coordinates of this vertex (X, Y, Z).
	 * 
	 * @return the positional coordinates of this vertex
	 */
	@Override
	public float[] getCoordinates(){
		return new float[]{loc.getX(), loc.getY(), loc.getZ()};
	}

	/**
	 * Returns texture coordinates of this vertex in the specified texture coordinate set.
	 * Number of coordinate axes depends on the type of texture coordinates.
	 * 
	 * @param texCoordSet
	 *        texture coordinate set
	 * @return texture coordinates of this vertex in the specified texture coordinate set
	 */
	@Override
	public float[] getTexCoordinates(int texCoordSet){
		float[] coords = new float[getGeometry().getTexCoordType()];
		for(int i=0; i<coords.length; i++){
			coords[i] = this.texCoords[texCoordSet][i];
		}
		return coords;
	}

	/**
	 * Returns a texture coordinate of this vertex in the specified texture coordinate set.
	 * 
	 * @param axis
	 *        coordinate axis: S, T, R or Q
	 * @param texCoordSet
	 *        texture coordinate set
	 * @return a texture coordinate of this vertex in the specified texture coordinate set
	 */
	@Override
	public float getTex(int axis, int texCoordSet){
		return this.texCoords[texCoordSet][axis];
	}

	/**
	 * Returns the X-coordinate of this vertex.
	 * 
	 * @return the X-coordinate of this vertex
	 */
	@Override
	public float getX(){
		return loc.getX();
	}

	/**
	 * Returns the Y-coordinate of this vertex.
	 * 
	 * @return the Y-coordinate of this vertex
	 */
	@Override
	public float getY(){
		return loc.getY();
	}

	/**
	 * Returns the Z-coordinate of this vertex.
	 * 
	 * @return the Z-coordinate of this vertex
	 */
	@Override
	public float getZ(){
		return loc.getZ();
	}

	/**
	 * Sets the positional coordinates of this vertex.
	 * 
	 * @param coordinates
	 *        new position of this vertex
	 */
	@Override
	public void setCoordinates(float[] coordinates){
		this.loc.set(coordinates);
	}

	/**
	 * Sets the texture coordinates of this vertex.
	 * 
	 * @param coordinates
	 *        new texture coordinates
	 * @param texCoordSet
	 *        texture coordinate set
	 */
	@Override
	public void setTexCoordinates(float[] coordinates, int texCoordSet){
		for(int i=0; i<Math.min(getGeometry().getTexCoordType(), coordinates.length); i++){
			this.texCoords[texCoordSet][i] = coordinates[i];
		}
	}

	/**
	 * Sets the X coordinate of this vertex.
	 * 
	 * @param x
	 *        new X coordinate
	 */
	@Override
	public void setX(float x){
		loc.setX(x);
	}

	/**
	 * Sets the Y coordinate of this vertex.
	 * 
	 * @param y
	 *        new Y coordinate
	 */
	@Override
	public void setY(float y){
		loc.setY(y);
	}

	/**
	 * Sets the Z coordinate of this vertex.
	 * 
	 * @param z
	 *        new Z coordinate
	 */
	@Override
	public void setZ(float z){
		loc.setZ(z);
	}

	/**
	 * Translates this vertex.
	 * 
	 * @param xyz
	 *        change of position on each axis
	 */
	@Override
	public void translate(float[] xyz){
		loc.set(loc.getX() + xyz[0], loc.getY() + xyz[1], loc.getZ() + xyz[2]);
	}

	/**
	 * Changes texture coordinates of this vertex.
	 * 
	 * @param trans
	 *        change of coordinates on S and T axis
	 * @param texCoordSet
	 *        texture coordinate set
	 */
	@Override
	public void translateTex(float[] trans, int texCoordSet){
		for(int i=0; i<trans.length; i++){
			this.texCoords[texCoordSet][i] += trans[i];
		}
	}

	/**
	 * Changes the X coordinate of this vertex.
	 * 
	 * @param x
	 *        change of position on X axis
	 */
	@Override
	public void translateX(float x){
		this.loc.setX(this.loc.getX() + x);
	}

	/**
	 * Changes the Y coordinate of this vertex.
	 * 
	 * @param y
	 *        change of position on Y axis
	 */
	@Override
	public void translateY(float y){
	          this.loc.setY(this.loc.getY() + y);
	}

	/**
	 * Changes the Z coordinate of this vertex.
	 * 
	 * @param z
	 *        change of position on Z axis
	 */
	@Override
	public void translateZ(float z){
	          this.loc.setZ(this.loc.getZ() + z);
	}

	/**
	 * Returns the positional coordinates of this vertex.
	 * 
	 * @return the positional coordinates of this vertex
	 */
	@Override
	public Point3f getCoordinate(){
		return new Point3f(this.loc);
	}

	/**
	 * Returns the normal vector of this vertex.
	 * 
	 * @return the normal vector of this vertex
	 */
	@Override
	public Vector3f getNormal(){
		return new Vector3f(this.normal);
	}

	/**
	 * Sets the normal vector of this vertex.
	 * 
	 * @param normal
	 *        normal vector
	 */
	@Override
	public void setNormal(Vector3f normal){
		normal.normalize();
		this.normal.set(normal);
	}

	/**
	 * Sets the positional coordinates of this vertex.
	 * 
	 * @param coordinates
	 *        new position of this vertex
	 */
	@Override
	public void setCoordinate(Point3f coordinates){
		this.loc.set(coordinates);
	}

	/**
	 * Returns the color of this vertex.
	 * 
	 * @return the color of this vertex
	 */
	@Override
	public float[] getColor(){
		float[] color = new float[this.color.length];
		for(int i=0; i<this.color.length; i++){
			color[i] = this.color[i];
		}
		return color;
	}

	/**
	 * Sets the color of this vertex.
	 * 
	 * @param color
	 *        R, G and B if <code>COLOR_3</code><br/>
	 *        R, G, B and A if <code>COLOR_3</code>
	 */
	@Override
	public void setColor(float[] color){
		for(int i=0; i<color.length; i++){
			this.color[i] = color[i];
		}
	}

	/**
	 * Sets a texture coordinate of this vertex.
	 * 
	 * @param coordinate
	 *        new texture coordinate
	 * @param axis
	 *        coordinate axis: S, T, R or Q
	 * @param texCoordSet
	 *        texture coordinate set
	 */
	@Override
	public void setTex(float coordinate, int axis, int texCoordSet){
		this.texCoords[texCoordSet][axis] = coordinate;
	}
	
}
