package examples.supplierclasses; 
/**
 * This class represents an automobile. Notice that some of the variables are
 * protected and some are private. These modifiers must be carefully chosen.
 * For example, I chose final for all variables relating to the fuel level
 * because I don't want clients (including subclasses) to be able to access
 * these variables.
 *
 * But I'm not sure about make. So I left it protected so that subclasses can
 * access this variable.
 */
public class Car {
  /**
   * Instance and class variables typically go at the start of the class body.
   */
  /**
   * Here are some constants (as indicated by final). These constants also
   * belong to the class because they are declared static. Variables declared
   * final are typically declared static too since there's no need to duplicate
   * these values to each instance. These are declared public since they're
   * meant to be used by clients when calling the setMake method.
   */
  public static final int HONDA = 0;
  public static final int CHEVROLET = 1;
  public static final int FORD = 2;
 /**
  * The brand of this car. (e.g. Honda)
  */
  protected int make = -1;
 /**
  * true when fuelAmount <= lowFuelThreshold, false otherwise
  */
  private boolean lowFuel;
 /**
  * When fuel amount is less than or equal to this amount, fuelLow is set
  * to true.
  */
  private float lowFuelThreshold;
 /**
  * Miles per gallon of this vehicle.
  */
  private float mpg;
 /**
  * Amount of gas in gallons that this car's tank current contains.
  */
  private float fuelAmount;
 /**
  * A no-argument constructor. Initializes variables with default values.
  */
  public Car() {
    fuelAmount = 10;
    mpg = 22;
    lowFuelThreshold = 2;
    lowFuel = false;
  } // end constructor
  /**
   * Notice that the constructor is "overloaded." There are multiple
   * constructors and client classes can use any one of them.
   */
  public Car(float fuelAmount, float mpg, float lowFuelThreshold) {
    // I have to use "this" here since the formal parameter fuelAmount,    shadows
    // my instance variable of the same name
    this.fuelAmount = fuelAmount;
    this.mpg = mpg;
    this.lowFuelThreshold = lowFuelThreshold;
    // it's possible that we start in a low-fuel condition; test it here
    lowFuel = fuelAmount <= lowFuelThreshold;
  } // end constructor
 /**
  * Drive the car the distance indicated by miles. The return value of this
  * method is a boolean that indicates if this operation was successful (i.e.
  * if there was enough fuel to go the distance).
  */
  public boolean drive(int miles) {
    // calculate how many gallons it will take to go the distance in miles;
    // gallonsRequired is a "local" variable; it exists only during the
    // execution of this method (i.e. its lifetime)
    float gallonsRequired = miles * (1 / mpg);
    // if we have enough fuel, deduct gallons from current amount, check for low
    // fuel, and return true; otherwise, return false
    if (gallonsRequired <= fuelAmount) {
      fuelAmount -= gallonsRequired;
      // check for low fuel
      if (fuelAmount <= lowFuelThreshold) {
        lowFuel = true;
      }
      
      return true;
    }
    else {
      return false;
    }
  } // end method drive
  /**
   * setMake is an accessor method. In this case it provides write-only access.
   * The items inside the parentheses are referred to as formal parameters.
   */
  public void setMake(int make) {
    this.make = make;
  } // end method setMake
  /**
   * toString method is overridden. In other words, we've specified a different
   * implementation of this method than our parent class did. We've used
   * StringBuffer to reduce the amount of intermediate strings created while
   * creating the string representation of this object.
   *
   * "FuelAmount: " is a string literal and "+" is the concatentation operator
   * when dealing with strings.
   */
  public String toString() {
    StringBuffer buf = new StringBuffer();
    buf.append("FuelAmount: " + fuelAmount);
    buf.append(", LowFuel: " + lowFuel);
    return buf.toString();
  } // end method toString
  /**
   * Since this class contains a main method, it is runnable. The code inside
   * main can be used for quick testing of a class.
   */
  public static void main(String[] args) {
    // use the new operator in conjunction with the constructor and
    // bind the object to the variable c1 that is declared to by type Car
    Car c1 = new Car(9, 15.3f, 3);
    // call the setMake method and use the static member of the Car class as an
    // argument
    c1.setMake(Car.HONDA);
    // print to the screen the state of the car's fuel
    System.out.println("State of car before driving\n" + c1);
    // call the drive method on the object bound to c1
    c1.drive(120);
    // print ending state; note: System.out.println uses our toString method to
    // produce its output
    System.out.println("State of car after driving\n" + c1);
    // array to hold 3 Car instances
    Car[] fleet = new Car[3];
    // create new Car instances and bind to each array slot
    for (int i = 0; i < fleet.length; i++) {
      fleet[i] = new Car(); // using no-arg constructor
    }
    // the drive method returns a boolean value that represents the success of
    // the drive operation; each successX is a local variable since each is
    // declared inside the method body
    boolean success0 = fleet[0].drive(300);
    boolean success1 = fleet[1].drive(180);
    boolean success2 = fleet[2].drive(4);
    System.out.println("Car #1 successfully drove 300 miles: " + success0);
    System.out.println("Car #2 successfully drove 180 miles: " + success1);
    System.out.println("Car #3 successfully drove 4 miles: " + success2);
  } // end method main
} // end class Car