package clothSimulator;

import java.util.List;
import java.util.LinkedList;
//import annas.graph.*;

import javax.media.opengl.GL;

import clothSimulator.Constraint.ConstraintType;

public class ConstraintGraphNode {

	
	public Particle p;
	/** all the particles that are related by a constraint (this is the adjacency list) */
	public List<ConstraintGraphNode> neighbours= new LinkedList<ConstraintGraphNode>();
	/**all the constraints that refer to the particle associated with this node */
	public List<Constraint> branches= new LinkedList<Constraint>();
	/** an integer list which describe all the locations (of stretch constraints) in a constraint list wherein a node's particle may lie */
	public List<Integer> CListLocations=new LinkedList<Integer>();
	/** this is a variable that is useful for making the minimum spanning tree.  It is the minimum constraint */
	public Double primKey;
	/** this is the parent of a node when it is in a min spanning tree(when the node is not in an MSP, then it should be null) */
	public ConstraintGraphNode parent;
	/** this is the list of children of a node when it is in a MSP (when the node is not in an MSP, then it should be null) */
	public List<ConstraintGraphNode> children= new LinkedList<ConstraintGraphNode>();
	/** to run Kruskal, each node has to be in a set.  TO define that set we just use a number called theSet */
	public int theSet;
	
	/** boolean to identify if it is in the queue or not */
	public boolean isInQ;

	
	
	/** a constructor that doesn't automatically find the neighbours of a particle */
	public ConstraintGraphNode(Particle thePart, ConstraintList theCList){
		p=thePart;
		for(Constraint c: theCList.theConstraints){
			if(c.ParticleList().contains(p) && c.constraintType()== ConstraintType.STRETCH ){
				CListLocations.add(c.getCLIndex());
			}
		}
	}
	
	public ConstraintGraphNode(ConstraintList theCList, Particle thePart){
		p=thePart;
		//maybe have some method here that fills up neighbours and branches
	}
	
	
	
	private int sharedConstLocation;
//	private double theSharedConstVal;
	/** finds the constraint that refers to both of the given particles (one of which is "this").  It does this by checking
	 * this.neighbours for the argument particle
	 * @return the shared constraint value 
	 */
	public double getSharedConstraintValue(ConstraintGraphNode u, ConstraintList theCList){
		for ( int cLocU : this.CListLocations ) {
			for ( int cLocV : u.CListLocations) {
				if ( cLocU == cLocV ) {
					sharedConstLocation = cLocU;
				}
			}
		}
		return theCList.theConstraints.get(sharedConstLocation).getWeight();		
	}
	
	
	ConstraintGraphNode prevNode;
	/** this is used to draw the minimum spanning tree */
	public void drawChildren(GL gl){
		

		ConstraintGraphNode currNode;
		//we are going to step along the graph, parent to child, until we get to a branch.  Then we recursively call this function on each of the branches
		currNode=this;
		while(currNode.children.size()!=0){
			if(currNode.children.size()>1){
				for(ConstraintGraphNode cgn: currNode.children){
					gl.glBegin( GL.GL_LINES );
						gl.glVertex3d(currNode.p.p.x,currNode.p.p.y,currNode.p.p.z);
						gl.glVertex3d(cgn.p.p.x,cgn.p.p.y,cgn.p.p.z);
					gl.glEnd();
					cgn.drawChildren(gl);
				}
				return;
			}else {
				prevNode=currNode;
				currNode=currNode.children.get(0);
				if(currNode!=null){
					gl.glBegin( GL.GL_LINES );
						gl.glVertex3d(prevNode.p.p.x,prevNode.p.p.y,prevNode.p.p.z);
						gl.glVertex3d(currNode.p.p.x,currNode.p.p.y,currNode.p.p.z);
					gl.glEnd();
				}
			}


			
		}
	}
	

	
}
