/**
 * A two-part measurement (e.g., a length in feet and inches, a
 * weight in pounds and ounces, ...)
 *
 * A two-part measurement consists of a number of 
 * large units (e.g., feet) and a number of small 
 * units (e.g., inches)
 *
 * This class is abstract.  Concrete children must implemen the
 * initializeUnits() method that initializes various "constants"
 * that are used throughout the class.
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0  
 * 
 */
 public abstract class  TwoPartMeasure 
 {
    private int           large, sign, small;
   
    protected int         smallsPerLarge;
    protected String      largeUnitsSingular, largeUnitsPlural;
    protected String      smallUnitsSingular, smallUnitsPlural;

    /**
     * Default Constructor
     */
     public TwoPartMeasure()
     {
			this(0, 0, true);
     }


    /**
     * Explicit Value Constructor
     *
     * @param large  The number of large units (must be positive)
     * @param small  The number of small units (must be positive)
     */
     public TwoPartMeasure(int large, int small)
     {
			this(large, small, true);
     }


    /**
     * Explicit Value Constructor
     *
     * @param large    The number of large units (must be positive)
     * @param small    The number of small units (must be positive)
     * @param positive true for positive and false for negative
     */
     public TwoPartMeasure(int large, int small, boolean positive)
     {
			this.large = Math.abs(large);
			this.small = Math.abs(small);

			this.sign   = 1;
			
			if (!positive) 
				this.sign = -1;

			initializeUnits();
    }


    /**
     * Change this TwoPartMeasure by a given amount
     *
     * @param other   The amount to change this TwoPartMeasure by
     */
     public void changeBy(TwoPartMeasure other)
     {
			int     otherTotal, thisTotal, total;

			otherTotal = other.toSmall();
			thisTotal  = this.toSmall();

			total = thisTotal + otherTotal;

			large = total / smallsPerLarge;
			small = total % smallsPerLarge;
     }


    /**
     * Check to see if thisTwoPartMeasure is equal to 
     * a given TwoPartMeasure
     *
     * @param other   The other TwoPartMeasure use in the comparison
     * @return        true if the two are equal and false otherwise
     */
     public boolean equals(TwoPartMeasure other)
     {
			boolean comparison;
			int     otherTotal, thisTotal;

			thisTotal  = this.toSmall();
			otherTotal = other.toSmall();

			comparison = false;
			
			if (thisTotal == otherTotal) 
				comparison = true;

			return comparison;
     }


    /**
     * Initialize the "constants" used by a TwoPartMeasure,
     * specifically:
     *
     *    smallsPerLarge     (e.g., inches per foot, ounces per pound)
     *    largeUnitsSingular (e.g., "foot", "pound")
     *    largeUnitsPlural   (e.g., "feet", "pounds")
     *    smallUnitsSingular (e.g., "inch", "ounce")
     *    smallUnitsPlural   (e.g., "inches", "ounces")
     */
	abstract protected void initializeUnits();



    /**
     * "Convert" this TwoPartMeasure to small units
     * (e.g., from 5 feet 7 inches to 67 inches)
     *
     * @return   The value in small units
     */
     private int toSmall()
     {
			int         total;

			total = sign * ((large * smallsPerLarge) + small);
			
			return total;
     }


    /**
     * Get a String representation of this Length
     *
     * @return  The String
     */ 
     public String toString()
     {
			String     aString;

			aString  = new String();
			
			if (sign < 0) 
				aString = aString + "Negative ";

			if (large == 1) 
			    aString = aString + large + " " + largeUnitsSingular;
			else            
			    aString = aString + large + " " + largeUnitsPlural;

			if (small == 1) 
				aString = aString + "  " + small + " " + smallUnitsSingular;
			else 
			   aString = aString + "  " + small + " " + smallUnitsPlural;

			return aString;
    }

} // end TwoParMeasure
