import java.util.*;

public class Car {
  // Units of meters/second, meters/second^2 and meters
  double speed;
  double maxAccel, stdDeccel, maxDeccel;
  double minStoppedTail;
  double length;
  
  // Units of tenths of seconds
  int reactionTime, minTail, forecast;
  
  // Unitless
  double eagerness; // Per 1/10 s, to accellerate
      
  Road road;
  double position;
  boolean debug;
  double lastA;
  
  Hashtable toDo = null;

  public void tick(long tickNum){
    double accel = 0.0;
    debug("Tick");
    // Plan next correction according to...
    // Open road
    if(speed < road.speedLimit(position)){
      accel = ((speed+maxAccel) > road.speedLimit(position)) ? (road.speedLimit(position)-speed):maxAccel;
      debug("Not moving at speed limit, accellerating at rate "+accel);
    }
    else if(speed > (road.speedLimit(position)+2)){
      accel = -1*stdDeccel;
    }
    
    // Other cars
    Car next = road.nextCar(position);
    double toNext;

    // ***BUG***
    // Somewhere in here, it fails to get the correct next car...
    // Don't know if the bug is in Road.nextCar or in here somewhere.
    // I think it is the former
    if(next != null)
      System.out.println("Next car is at "+next.position);

    if(next == null)
      toNext = road.len;
    else if(road.loopRoad)
      toNext = (next.position-next.length+road.len-position)%road.len;
    else
      toNext = (next.position-next.length-position);
    if(next.position-position < 0){
      System.out.println("I'm at "+position+" and next is at "+next.position);
      toNext = road.len;
    }
    if(((10*toNext/speed) < minTail) && (speed != 0))
      accel = -1*stdDeccel;
    else if(toNext < minStoppedTail)
      accel = -1*stdDeccel;
    else 
      while((((10*toNext/(speed+accel)) < minTail)) && ((speed+accel) != 0))
	accel /= 3;
    if(next != null)
      if((((10*toNext)/(speed-next.speed)) < forecast) && 
	 (speed > next.speed)){
	accel = -1*maxDeccel;
      }
    
    
    // Constraints

    // Put in hopper to be executed after reactionTime
    debug((toNext/speed)+" seconds behind next car. "+toNext+"/"+speed+"  Executing "+accel);
    debug("Accellerating at rate "+accel);
    if(toDo == null)
      toDo = new Hashtable();
    toDo.put(new Long(tickNum+reactionTime), new Double(accel));

    // Execute changes
    Double execA;
    if((execA = (Double) toDo.get(new Long(tickNum))) != null){
      toDo.remove(new Long(tickNum));
      // Throw in eagerness stuff here
      speed += execA.doubleValue()/10;
      lastA = execA.doubleValue();
      if(speed < 0) {
	speed = 0;
      }
    }
    position += (speed/10);
    if((speed/10) > toNext){
      // Collision
      System.out.println("Collision! (next car in "+toNext+" meters, going "+speed+" m/s)");
      System.out.println("I am: "+minStoppedTail+", "+reactionTime+", "+minTail+".  Composite "+(minTail-reactionTime));
      speed=0;
    }
    }

  public void debug(String s){
    if(debug)
      System.out.println("Debug: "+s);
  }
}
