/**
 * Models a bird.
 * 
 * Demonstrates methods, constructors, and encapsulation.
 * This version has been updated to demonstrate more methods and
 * encapsulation.
 *
 * @author Zach Tomaszewski
 * @version 22 Oct 2008
 */
public class BirdRevised {

  //constants to be used when setting a bird's size
  public static final int EGG = 0;
  public static final int HATCHLING = 1;  
  public static final int TINY = 2;
  public static final int SMALL = 3;
  public static final int MEDIUM = 4;
  public static final int LARGE = 5;

  //instance variables: every instance gets its own copy of these
  //variables are now private, and so can only be affected through methods
  private int size;        //this bird's current size
  private boolean canFly;  //whether this particular bird can fly
  private boolean typeCanFly;  //whether this type of bird can normally fly
  private String type;     //this bird's common name or species
  private int maxSize;     //the maximum size this bird can grow


  //CONSTRUCTORS

  /**
   * Constructs a new Bird of the given type, size, max size, and 
   * normal flight capability.  That is, typeCanFly specifies whether
   * this type of bird can normally fly; any bird smaller than TINY
   * cannot fly regardless of type.
   *
   * Limits: TINY <= maxSize <= LARGE; 
   *         EGG <= size <= maxSize
   *
   * If size or maxSize is to small/large, it will be adjusted to be the
   * smallest/largest allowed value.
   */
  public BirdRevised(String type, int size, int maxSize, boolean typeCanFly) {
    //constrain max size
    if (maxSize > LARGE) {
      this.maxSize = LARGE;
    }else if (maxSize < TINY) {
      this.maxSize = TINY;
    } else {
      this.maxSize = maxSize;
    }

    //constrain size
    if (size > this.maxSize) {
      this.size = this.maxSize;
    }else if (size < EGG) {
      this.size = EGG;
    }else {
      this.size = size;
    }
    this.typeCanFly = typeCanFly;
    this.canFly = (this.size < TINY) ? false : this.typeCanFly;
    this.type = type;
  }


  /**
   * Constructs an egg-"sized" flying bird of the given type and maxSize.
   * Note that no bird can fly until it is of greater size than HATCHLING.
   */
  public BirdRevised(String type, int maxSize) {
    //actually going to let other constructor do the work
    this(type, EGG, maxSize, true);
  }


  //METHODS
  
  /**
   * Prints this Bird to the screen as a single line of text.
   */
  public void print() {
    System.out.print("This " + this.type + " is ");
    switch (this.size){
      case EGG: System.out.print("still in its egg"); break;
      case HATCHLING: System.out.print("only a chick"); break;
      case TINY: System.out.print("of tiny size"); break;
      case SMALL: System.out.print("of small size"); break;
      case MEDIUM: System.out.print("of medium size"); break;
      case LARGE: System.out.print("of large size"); break;
      default: System.out.print("mutated"); break;
    }
    System.out.print(" and it can");
    if (!this.canFly) {
      System.out.print("not");
    }
    System.out.println(" fly.");
    return;
  }  

 
  /**
   * Feeds this bird, which causes it to grow one size (unless it has
   * already reached its max size).  
   * Returns true if the bird ate the food.
   *
   * Feeding an egg does nothing, and so returns false.
   */
  public boolean feed() {
    if (this.size == EGG) {
      //can't feed an egg
      return false;
    }

    if (this.size == HATCHLING) {
      this.size++;
      //grown enough to fly, if this type can fly
      this.canFly = this.typeCanFly;
    }else if (this.size < this.maxSize) {
      //can grow from this feeding
      this.size++;
    }else {
      //already reached max size, so feeding does nothing
    }
    return true;
  }


  /**
   * Causes this bird to hatch and become HATCHLING size if it is currently 
   * of EGG size.  Otherwise does nothing for already-hatched birds.
   */
  public void hatch() {
    if (this.size == EGG) {
      this.size++;
    }
  }

  
  //METHODs -- Accessors (and 1 sort-of mutator)

  /** Returns the current size of this bird. */
  public int getSize() {
    return this.size;
  }

  /** Returns whether this bird has hatched yet. */
  public boolean hasHatched() {
    return (size != EGG);
  }
 
  /** Returns the max size that a bird of this type can grow */
  public int getMaxSize() {
    return this.maxSize;    
  }
   
  public String getType() {
    return this.type;
  }

  /** Returns whether or not this bird can fly. */
  public boolean canFly() {
    return this.canFly;
  }

  /** 
   * Prevents this adult bird from flying (if it could due to its type).
   * Note that clipping a hatchling has little effect, as its 
   * feathers will grow in as it grows in size.
   */
  public void clipWings() {
    //sort of like a mutator, though I didn't pass in the new value.
    this.canFly = false;
  }


  //No setSize because I want a bird's size to only change through feeding.
  //Also, once a bird exists, I don't want its type, maxSize, 
  //or typeCanFly to change.  And it doesn't make sense to be able to
  //change a bird's size directly.
 
}

