 /**
 * @author Felipe Lopez P. - Cristian Carrasco G.
 * Clase RubberBand: esta clase modela el elemento físico elástico.
 * Esta clase se modificó levemente de la clase MyString.
 * Un leve cambio, es que el atributo stiffness no es igual para todos los 
 * elásticos como en la clase MyString.
 * Cuando el elástico se encuentra en tension se comporta como un resorte
 * con constante elastica muy grande. Cuando el elastico esta en relajo la fuerza
 * ejercida por esta es cero.
 */
public class RubberBand extends PhysicsElement  {
   private static int id=0;  // String identification
   protected float restLength;
   private final float stiffness;
   protected Block block_a, block_b;
   
   /**
    * Constructor del objeto elastico.
    * El constructor fue modificado con respecto a la clase MyString, ya que en esta 
    * clase cada objeto puede tener diferente constante elastica, no asi en la clase de
    * las cuerdas.
    * @param restLength La variable ingresada es el largo del elastico. 
    * @param stiffness La variable ingresada es la constante de elasticidad del elástico.
    */
   public RubberBand(float restLength, float stiffness){
      super(id++);
      this.stiffness = stiffness;     
      this.restLength = restLength;
      block_a = block_b = null;
   }
   /**
    * Union de un bloque con una elástico.
    * @param a Bloque que se desea unir.
    */
   public void attachBlock_a (Block a) {
      block_a = a;
      block_a.attachString(this);
   }
   /**
    * Desunion del bloque "a" con el elástico.
    */
   public void detachBlock_a(){
      if (block_a == null) return;
      block_a.detachString(this);
      block_a=null;
   }
   /**
    * Union de un bloque con un elástico.
    * @param b Bloque que se desea unir.
    */
   public void attachBlock_b (Block b) {
      block_b = b;
      block_b.attachString(this);
   }
   /**
    * Desunion del bloque "b" con el elástico.
    */
   public void detachBlock_b(){
      if (block_b == null) return;
      block_b.detachString(this);
      block_b=null;
   }
   /**
    * Posicion del bloque A.
    * @return posicion del bloque A en un Vector2D.
    */
   protected Vector2D getPositionA() {
      if (block_a != null)
         return block_a.getPosition();
      return null;
   }
   /**
    * Posicion del bloque B.
    * @return posicion del bloque B en un Vector2D.
    */
   protected Vector2D getPositionB() {
      if (block_b != null)
         return block_b.getPosition();
      return null;
   }
   /**
    * Obtencion del Vector.
    * @return vector devuelto en un Vector2D.
    */
   protected Vector2D getVector() {
      Vector2D b = getPositionB();
      Vector2D a = getPositionA();
      if (a== null || b==null) return new Vector2D();
      else return b.minus(a);
   }
   /**
    * Calculo de la fuerza.
    * @param block
    * @return fuerza existente entre las masas y los elásticos. La fuerza se devuelve en un Vector2D.
    */
   public Vector2D getForce(Block block) {
      Vector2D force;
      if ((block_a == null) || (block_b == null))
          return new Vector2D();
      Vector2D stringVector = getVector();
      double stretch = stringVector.module() - restLength;
      if(stretch >= 0){
      force = stringVector.unitary().times(stretch*stiffness);
      if (block == block_a) return force;
      if (block == block_b) return force.times(-1);
      else return new Vector2D();
      } else return new Vector2D() ;
   }
   public void computeNextState(double delta_t) {
   }
   public void updateState(){
   }
   public String getDescription() {
      return "String#"+ 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+",";
   }
}
