
/** *********************************************************
 * ISP Charge contains methods to work with charges for the ISP 
 * charges based on usage and package purchased
 *
 * @author Nancy Harris, James Madison
 * @version V1 - 10/25/2007
 */
public class ISPCharge
{
	private char packageCode;
	private double hours;
	
	// declare your constants here.  They should use the private
	// visibility modifier.
	
	// package base price
	private final double PACKAGE_A = 9.95;
	private final double PACKAGE_B = 13.95;
	private final double PACKAGE_C = 19.95; 
	
	// package base hours
	private final double A_HOURS = 10;
	private final double B_HOURS = 20;
	
	// additional charge for hours
	private final double A_ADDTL = 2.0;
	private final double B_ADDTL = 1.0;
	
	// tax rate
	private final double TAX_RATE = .05;
	
	/**************************************************** 
	 *	The constructor sets the package and hours attributes.
	 * 
	 * precondition - The code must be A, B, or C or a, b, or c
	 *              - The hours must be >= 0
	 *
	 * if preconditions are not met, code is set to A and hours to 0
	 *
	 * @param pkg The code for the package, A, B, or C
	 * @param hours The number of hours this month
	 */
	 public ISPCharge(char pkg, double hours)
	 {
	 	this.hours = hours;
		this.packageCode = pkg;
		
		// error check, should not happen
		if (hours < 0)
			hours = 0;
		if (packageCode != 'A' || packageCode != 'B' || packageCode != 'C' ||
		    packageCode != 'a' || packageCode != 'b' || packageCode != 'c')
			packageCode = 'A'; 
		
		this.packageCode = Character.toUpperCase(packageCode); // make consistent
	 }
	
	
	/************************************************
    * getBaseCharge produces the base charge for this package
	 *
	 * @return The base charge for this package
	 */
	private double getBaseCharge()
	 {
	double base;
	 
	 if (packageCode == 'A')
	 	base = PACKAGE_A;
	else if (packageCode == 'B')
		base = PACKAGE_B;
	else
		base = PACKAGE_C;
		
	return base;
	}
	/************************************************
    * getBaseHours produces the base hours for this package
	 *
	 * @return The base hours for this package
	 */
	private double getBaseHours()
	 {
	double baseHours;
	 
	 if (packageCode == 'A')
	 	baseHours = A_HOURS;
	else if (packageCode == 'B')
		baseHours = B_HOURS;
	else
		baseHours = -5;  // should not happen
		
	return baseHours;
	}
	
	/************************************************
    * getAddtlHours produces the base charge for this package
	 *
	 * @return The additional hours for this package
	 */
	private double getAddtlHours()
	 {
	double addtlHours;
	 
	 if (packageCode == 'A')
	   addtlHours = hours - A_HOURS;
	else if (packageCode == 'B')
		addtlHours = hours - B_HOURS;
	else
		addtlHours = -1;  // should not happen
		
		return addtlHours;
	}
	
	/************************************************
	 * calc charge will decide which package to apply
	 * and will return the correct cost.
	 *
	 * @return The charges for this month.
	 */
	public double calcCost()
	{
		double charge;
		
		if (packageCode == 'A')
			charge = calcA();
		else if (packageCode == 'B')
			charge = calcB();
		else
			charge = calcC();
		
		return charge;	
	}
	
	/************************************************
	 * calcA calculates the charges for package A
	 *
	 * @return The calculated charge for package A
	 */
	 public double calcA()
	 {
	 	double charge;
		double addtl;  // additional charge
		
		addtl = 0;
		charge = PACKAGE_A;  // base
		
		if (hours > A_HOURS)  // more than base
			addtl = (hours - A_HOURS) * A_ADDTL;
		
		charge = charge + addtl;
		
		return charge;
	 }	 
	 /************************************************
	 * calcB calculates the charges for package B
	 *
	 * @return The calculated charge for package B
	 */
	 public double calcB()
	 {
		double charge;
		double addtl;  // additional charge
		
		addtl = 0;
		charge = PACKAGE_B;  // base
		
		if (hours > B_HOURS)  // more than base
			addtl = (hours - B_HOURS) * B_ADDTL;
		
		charge = charge + addtl;
		
		return charge;
	 }	 
	 
	 
	 /************************************************
	 * calcC calculates the charges for package C
	 *
	 * @return The charge for package C
	 */
	public double calcC()
	{
	 	return PACKAGE_C;
	}
	 
	 
	 /** calcTax calculates the tax on the passed charge
	  *
	  * @return The cost of tax for this package
	  */
	  public double calcTax()
	  {
	  	double tax;
		
		tax = calcCost() * TAX_RATE;
		
		return tax;
		}
		
		/****************************************************
		 * save B - determines if this package will save money 
		 * by using package B
		 *
		 * @return true if there will be savings, false otherwise
		 */
		 private boolean saveB()
		 {
		 	boolean save;
			
		 	if (this.calcCost() > calcB())
				save = true;
			else
				save = false;
			
			return save;
		}
		
		/****************************************************
		 * save C - determines if this package will save money 
		 * by using package C
		 *
		 * @return true if there will be savings, false otherwise
		 */
		 private boolean saveC()
		 {
		 	boolean save;
			
		 	if (this.calcCost() > calcC())
				save = true;
			else
				save = false;
			
			return save;
		}
	
		/****************************************************
		 * amtSavB - determines the amount of savings 
		 * by using package B
		 *
		 * @return the amount of the savings
		 */
		 private double amtSaveB()
		 {
		 	double savings;
			
			savings = this.calcCost() - this.calcB();
			
			return savings;
					
		 }

		/****************************************************
		 * amtSavC - determines the amount of savings 
		 * by using package C
		 *
		 * @return the amount of the savings
		 */
		 private double amtSaveC()
		 {
		 	double savings;
			
			savings = this.calcCost() - this.calcC();
			
			return savings;
					
		 }
		 
	  /*************************************************
	   * toString describes this charge.  It includes the 
		* package for this charge and the hours.
		*
		* @ return A description of this charge
		*/	  
		public String toString()
		{
			return "Package: " + packageCode + "\tHours: " + hours;
		}
		
	  /****************************************************
	   * makeBill
		*
		* @returns a String to represent the bill
		*/
		public String makeBill()
		{
			String builder;
			builder = "";
			
			// get basic bill
			builder = builder + "Customer Bill\n\n";
			builder = builder + "Package: " + packageCode;
			builder = builder + "\nHours Used: " + hours;
			builder = builder + "\n\nBase Charge: " + getBaseCharge();
			
			// lines only if package C
			if (packageCode != 'C')
			{
				builder = builder + "\nBaseHours: " + getBaseHours();
			 	builder = builder + "\nAdditional Hours: " + getAddtlHours();
			}
			
			builder = builder + "\nTotal Charge: " + calcCost();
			builder = builder + "\nTax: " + calcTax();
			builder = builder + "\nPay this Amount: " + (calcCost() + calcTax()) + "\n";
		
			// check for comparison
			if (packageCode == 'A' || packageCode == 'B')
			{
				if (saveB())  // we save with B
				{
					builder = builder + "\nYou could have saved " + amtSaveB() + "with package B. " +
					   "Call 1-888-555-1234 for more information.";
				}
				
				if (saveC())
				{
					builder = builder + "\nYou could have saved " + amtSaveC() + "with package C. " +
					   "Call 1-888-555-1234 for more information.";
				}
			}
			
			return builder;
		}		
}