/* particleSystem.java 
 * Created on Apr 25, 2006 
 */ 

/* particleSystem.java 
 * Created on Apr 20, 2006 
 */


import processing.core.PApplet;

public class particleSystem {
	// NUMBERS
	int	numParticles;
	int	numSprings;
	int	numMuscles;
	
	
	PApplet p;
	
	int numIterations;
	
	// ARRAYS OF ELEMENTS
	particle particles[];
	spring springs[];
	muscle muscles[];
	
float[] tempx;
float[] tempy;
	
	public particleSystem(PApplet p_) {
		float musPercent = 0.5f;
	    int inCount = 0;
	    int mCount = 0;
	    int sCount = 0;
	    p = p_;
	    
	    numParticles = (int) p_.random(3,12);
	    int numSpringMus;
	    int numPa = numParticles - 1;
	    int springCount = 0;
	    int oldSpringCount = 0;
	    while (numPa > 0) {
	      springCount = numPa + oldSpringCount;
	      oldSpringCount = springCount;
	      numPa--;
	    }
	    
	    numSpringMus = (int) p_.random((numParticles - 1), (springCount+1));
	    numMuscles = PApplet.round(musPercent*numSpringMus);
	    numSprings = numSpringMus - numMuscles;
	    particles 	= new particle[numParticles];
		if(numSprings != 0)	springs		= new spring[numSprings];
		if(numMuscles != 0)	muscles		= new muscle[numMuscles];
	
//	    println("springs: " + numSprings + " muscles: " + numMuscles + " Springs and Muscles: " + numSpringMus);

	    for (int particleCount = 0; particleCount < numParticles; particleCount++){
	        particles[particleCount] = new particle(p_, 0, new Vector3D(((p_.width/2)-p_.random(-30,30)),((p_.height/2)+p_.random(-30,30))),4);
	      }
	   
	        for (int h = 0; h < numParticles; h ++){ 
	          for (int j = h; j < numParticles; j ++){ 
	            if (h != j) {
	              if (inCount > numSpringMus-1) break;
	              if ((p_.random(1) < 0.75) && (mCount < numMuscles)) {
	                muscles[mCount]   = new muscle(p_,this,h,j);
	                mCount++;
	                inCount++;
	              }
	              else if (sCount < numSprings){
	               springs[sCount]   = new spring(p_,this,h,j);
	                sCount++;
	                inCount++; 
	              }
	              else break;
	          
	              

	            }

	          }
	        }            
		
		numIterations = 1;
		
		
	
	
	

	tempx = new float[numParticles];
	tempy = new float[numParticles];
	}
	public void setIterations(int n) {
		numIterations = n;
	}
	
	  public void satisfyConstraints() {


	        float dx, dy, dlength, diff;
	        int A, B;
	        spring s;
	       
	        for (int i=0; i<this.numParticles; i++) {
	          this.tempx[i] = PApplet.min(this.particles[i].loc.x, p.width);
	          this.tempy[i] = PApplet.min(this.particles[i].loc.y, p.height);

	        }

	        for(int i =0; i<this.numSprings; i++) {
	          s = this.springs[i];
	          s.softLength = s.restLength;
	        }



	        for(int numIt = 0; numIt<this.numIterations; numIt++) {
	          // constraint 1: all particles inside the box(world constraints)
	          for (int i = 0; i < this.numParticles; i++) {
	            this.particles[i].loc.x = PApplet.max(PApplet.min(this.particles[i].loc.x,p.width),0);
	            this.particles[i].loc.y = PApplet.max(PApplet.min(this.particles[i].loc.y,p.height),0);
	          }

	          // constraint 2: internal constraints (springs + muscles)
	          for(int i =0; i<this.numSprings; i++) {
	            A = this.springs[i].A;
	            B = this.springs[i].B;


	            dx = this.particles[B].loc.x - this.particles[A].loc.x;
	            dy = this.particles[B].loc.y - this.particles[A].loc.y;


	            dlength =  PApplet.sqrt(dx*dx + dy*dy); 
	            diff = (dlength - this.springs[i].softLength)/dlength;
	            this.particles[A].loc.x += dx*0.5f*diff;
	            this.particles[A].loc.y += dy*0.5f*diff;
	            this.particles[B].loc.x -= dx*0.5f*diff;
	            this.particles[B].loc.y -= dy*0.5f*diff;
	          }
	          // println("muscles: " + this.numMuscles);
	          for(int i=0; i<this.numMuscles;i++) {
	            if(this.muscles.length >0) this.muscles[i].work();

	          }
	        }

	        for(int i=0; i<this.numParticles; i++) {
	          if (this.particles[i].particleSelected != -1)
	          {
	            this.particles[i].loc.x = p.mouseX;
	            this.particles[i].loc.y = p.mouseY;
	          }
	        }


	      }
	        

	public void draw() {
		
		for(int i =0; i<numMuscles; i++) {
			muscles[i].mdraw();
		}
		
		for(int i =0; i<numSprings; i++) {
			  
			springs[i].draw();
		}
		
		for(int i =0; i<numParticles; i++) {
			particles[i].mdraw();
			particles[i].mouseOver();
		}
		// TODO neck of the draw functions
		
	}
	
}
