public class Spring extends PhysicsElement  {
   private static int id=0;  // Spring identification
   protected float restLength;
   private final float stiffness;
   protected Block block_a, block_b;

   private Spring(){   // nobody can create a block without state
      super(id++);
      stiffness=0;
   }
   public Spring(float restLength, float stiffness){
      super(id++);
      this.restLength = restLength;
      this.stiffness = stiffness;
      block_a = block_b = null;
   }
   public void attachBlock_a (Block a) {
      block_a = a;
      block_a.attachSpring(this);
   }
   public void detachBlock_a(){
      if (block_a == null) return;
      block_a.detachSpring(this);
      block_a=null;
   }
   public void attachBlock_b (Block b) {
      block_b = b;
      block_b.attachSpring(this);
   }
   public void detachBlock_b(){
      if (block_b == null) return;
      block_b.detachSpring(this);
      block_b=null;
   }
   protected Vector2D getPositionA() {
      if (block_a != null)
         return block_a.getPosition();
      return null;
   }
   protected Vector2D getPositionB() {
      if (block_b != null)
         return block_b.getPosition();
      return null;
   }
   protected Vector2D getVector() {
      Vector2D b = getPositionB();
      Vector2D a = getPositionA();
      if (a== null || b==null) return new Vector2D();
      else return b.minus(a);
   }
   public Vector2D getForce(Block block) {
      Vector2D force;
      if ((block_a == null) || (block_b == null))
         return new Vector2D(); 
      Vector2D springVector = getVector();
      double stretch = springVector.module() - restLength;
      force = springVector.unitary().times(stretch*stiffness);
      if (block == block_a) return force;
      if (block == block_b) return force.times(-1);
      else return new Vector2D();
   }
   public void computeNextState(double delta_t) {
   }
   public void updateState(){
   }
   public String getDescription() {
      return "Spring#"+ getId()+": "+Vector2D.getDescription()+
            ","+Vector2D.getDescription()+",";
   }
   public String getState() {
      String s;
      if (block_a != null) 
         s = block_a.getPosition()+",";
      else if (block_b != null)
              s = block_b.getPosition().minus(new Vector2D(restLength,0))+",";
            else  
              s = new Vector2D()+",";  // up to here left end is determined 
      if (block_a != null)
         s += block_a.getPosition();
      else if (block_b != null)
               s += block_b.getPosition().plus(new Vector2D(restLength,0));
            else
               s += new Vector2D();
      return s+",";
   }
}
