//---------------------------------------------------------------------------------------------	
//  CS100 P2: Q2
//
//  Class GymMember is a general class describing properties of members at a gym. 
//  It has fields name, address, phone, status (fit or flab); a set of
//  "get" methods to obtain these field values; a toString method which returns a
//  basic description of the user; and a getID and getYogDisc methods.
//  Class GymMember is the superclass for classes Fit and Flab.
//
//  Classes Fit and Flab introduce new variables to keep track of specific account info
//  such as account numbers, penalties to be charged for not meeting member requirements
//  etc.  See below for details.  The constructors for each automatically assign a new ID
//  number to a newly created Fit or Flab member.  A variable monthsDelinq keeps track of
//  the number of weeks the members fail to meet their weekly visit requirements.  Related
//  is a method visitsThisWeek which takes as input the number of visits and the month
//  to which the week belongs.  Appropriate object variables are updated to keep track of
//  the new balances if delinquent.  Method yearlyChargeToDate returns the current
//  account balance of the member in question.  Fit and Flab override Class GymMember's
//  getID and getYogDisc methods.
// 
//  Class TestGymMember demonstrates that the classes work appropriately by instantiating
//  two examples each of class Fit and Flab and uses the instance methods of classes Fit and Flab
//  as well as introduces two new methods, checkAccount and buyYogurt to see those aspects of
//  Fit and Flab.
//
//  Author 	:   Alan Renaud (ajr5@cornell.edu)
//  Date		:   15 July 1999	
//---------------------------------------------------------------------------------------------	


class GymMember {
	protected String name;
	protected String address;
	protected String phone;
	protected String status;
	
	//   Constructor 
	GymMember (String n, String a, String p, String s)
	{
		name = n;
		address = a;
		phone = p;
		status = s;
	}

	//---------------------------------------------------------------------------------------------	
	//  getName
	//
	//  Returns member's name
	//---------------------------------------------------------------------------------------------		
	public String getName()
	{	
		return name;
	}

	//---------------------------------------------------------------------------------------------	
	//  getAddress
	//
	//  Returns member's address
	//---------------------------------------------------------------------------------------------		
	public String getAddress()
	{	
		return address;
	}

	//---------------------------------------------------------------------------------------------	
	//  getPhone
	//
	//  Returns member's phone number
	//---------------------------------------------------------------------------------------------		
	public String getPhone()
	{	
		return phone;
	}
	
	//---------------------------------------------------------------------------------------------	
	//  getStatus
	//
	//  Returns member's status
	//---------------------------------------------------------------------------------------------		
	public String getStatus()
	{	
		return status;
	}
	
	//---------------------------------------------------------------------------------------------	
	//  toString
	//
	//  Returns a description of the member
	//---------------------------------------------------------------------------------------------		
	public String toString()
	{
		return  "Name: " + name + "\nAddress: " + address + "\nPhone: " + phone + "\nMember status: " + status + "\n\n";
	}
	
	//---------------------------------------------------------------------------------------------	
	//  getID()
	//
	//  Returns member's idNumber
	//---------------------------------------------------------------------------------------------		
	public int getID()
	{	
		System.out.println("No ID information at this level.");
		return 0;
	}
	
	
	//---------------------------------------------------------------------------------------------	
	//  getYogurtDisc
	//
	//  Returns member's discount at the yogurt bar
	//---------------------------------------------------------------------------------------------		
	public double getYogurtDisc()
	{	
		System.out.println("No yogurt discount at this level.");
		return 0;
	}
	
}
// -------End class GymMember


// -------begin class Fit
class Fit extends GymMember {

	private int idNumber;
	private static int numFitMembers;
	private final static int fitStartID = 1;
	private static int[] monthsDelinq = new int[12];
	public final static int fitYearlyCharge = 250;
	public static double yogurtDisc = 0.25; 
	final public static int minWeeklyVisits = 4;
	final public static int fitMonthCharge = 20;
		

	//---------------------------------------------------------------------------------------------	
	//  Fit Constructor
	//
	//  Automatically updates the number of  active Fit members and assigns the 
	//  member a correct ID number.
	//---------------------------------------------------------------------------------------------	
	Fit (String n, String a, String p, String s)
	{
		super(n, a, p, s);
		numFitMembers++;
		idNumber = fitStartID + numFitMembers - 1;
	}

	//---------------------------------------------------------------------------------------------	
	//  getID()
	//
	//  Returns member's idNumber
	//---------------------------------------------------------------------------------------------		
	public  int getID()
	{	
		return idNumber;
	}
		
	//---------------------------------------------------------------------------------------------	
	//  getYogurtDisc
	//
	//  Returns member's discount at the yogurt bar
	//---------------------------------------------------------------------------------------------		
	public double getYogurtDisc()
	{	
		return yogurtDisc;
	}
	
	//---------------------------------------------------------------------------------------------	
	//  visitsThisWeek
	//
	//  input	:   	number of visits, name of month
	//  return	:	none
	//
	//  appropriately updates variable monthsDelinq if user does not make minimum
	//  number of visits.
	//---------------------------------------------------------------------------------------------		
	public static void visitsThisWeek( int numVisits, String mnth)
	{	String[] months = {"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"};
		mnth = mnth.toLowerCase();
		if (numVisits < minWeeklyVisits)
			for (int i=0; i<=11; i++)
				if (mnth.startsWith(months[i]))
					monthsDelinq[i]++;	
	}
	
	//---------------------------------------------------------------------------------------------	
	//  yearlyChargeToDate
	//
	//  input	:   	none
	//  return	:	the current bill for the user
	//
	//  Returns the baseYearlyCharge plus any penalties
	//---------------------------------------------------------------------------------------------		
	public double yearlyChargeToDate()
	{	int penaltyCount=0;
		for (int k=0; k<=11; k++)
			if (monthsDelinq[k] != 0)
				penaltyCount++;
		return fitYearlyCharge + fitMonthCharge*penaltyCount;
	}
	
}
// -------End class Fit


// -------Begin class Flab
class Flab extends GymMember {

	private int idNumber;
	private static int numFlabMembers;
	private final static int flabStartID = 500000;
	private static int[] monthsDelinq = new int[12];
	public final static int flabYearlyCharge = 100;
	public static double yogurtDisc = 0; 
	final public static int maxWeeklyVisits = 3;
	final public static int flabMonthCharge = 25;

	//---------------------------------------------------------------------------------------------	
	//  Flab Constructor
	//
	//  Automatically updates the number of  active Flab members and assigns the 
	//  member a correct ID number.
	//---------------------------------------------------------------------------------------------	
	Flab (String n, String a, String p, String s)
	{
		super(n, a, p, s);
		numFlabMembers++;
		idNumber = flabStartID + numFlabMembers - 1;
	}
	
	//---------------------------------------------------------------------------------------------	
	//  getID()
	//
	//  Returns member's idNumber
	//---------------------------------------------------------------------------------------------		
	public  int getID()
	{	
		return idNumber;
	}

	//---------------------------------------------------------------------------------------------	
	//  getYogurtDisc
	//
	//  Returns member's discount at the yogurt bar
	//---------------------------------------------------------------------------------------------		
	public double getYogurtDisc()
	{	
		return yogurtDisc;
	}

	//---------------------------------------------------------------------------------------------	
	//  visitsThisWeek
	//
	//  input	:   	number of visits, name of month
	//  return	:	none
	//
	//  appropriately updates variable monthsDelinq if user does makes too many
	//  visits.
	//---------------------------------------------------------------------------------------------		
	public static void visitsThisWeek( int numVisits, String mnth)
	{	String[] months = {"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"};
		mnth = mnth.toLowerCase();
		if (numVisits > maxWeeklyVisits)
			for (int i=0; i<=11; i++)
				if (mnth.startsWith(months[i]))
					monthsDelinq[i]++;	
	}
	
	//---------------------------------------------------------------------------------------------	
	//  yearlyChargeToDate
	//
	//  input	:   	none
	//  return	:	the current bill for the user
	//
	//  Returns the baseYearlyCharge plus any penalties
	//---------------------------------------------------------------------------------------------		
	public double yearlyChargeToDate()
	{	int penaltyCount=0;
		for (int k=0; k<=11; k++)
			if (monthsDelinq[k] != 0)
				penaltyCount++;
		return flabYearlyCharge + flabMonthCharge*penaltyCount;
	}

}
// -------End class Flab


// -------Begin class TestGymMember
class TestGymMember {

	public static void main(String[] args) 
	{	
		TokenReader in = new TokenReader(System.in);
		Fit alan = new Fit("Alan Renaud", "43 Highgate Crescent", "(204) 253-1134", "Fit");
		Fit joe = new Fit("Joe Smith", "18 Paddington Road", "(204) 266-1234", "Fit");
		Flab jane = new Flab("Jane Bottles", "50 Junction Street", "(305) 935-0777", "Flab");
		Flab don = new Flab("Donnie Mack", "1 Las Vegas Plaza", "(519) 976-0001", "Flab");

		//  see if fit update method works
		alan.visitsThisWeek(5, "January");
		System.out.println(alan.name + "\'s charge to date = " + alan.yearlyChargeToDate());
		alan.visitsThisWeek(1, "March");
		System.out.println(alan.name + "\'s charge to date = " + alan.yearlyChargeToDate() + "\n");
		//  see if flab update works
		jane.visitsThisWeek(1, "noVEMBER");
		System.out.println(jane.name + "\'s charge to date = " + jane.yearlyChargeToDate());
		jane.visitsThisWeek(5, "DECember");
		System.out.println(jane.name + "\'s charge to date = " + jane.yearlyChargeToDate() + "\n");
		
		//  see if account information is correct 
		checkAccount(joe);
		checkAccount(don);
		
		//  test buyYogurt method
		buyYogurt(alan);
		
		in.waitUntilEnter();
	}


	//---------------------------------------------------------------------------------------------	
	//  buyYogurt
	//
	//  input	:   	object of type GymMember
	//  return	:	none
	//
	//  Silly program to test if user gets correct discount
	//---------------------------------------------------------------------------------------------		
	public static void buyYogurt (GymMember joe)
	{
		TokenReader in = new TokenReader(System.in);
		System.out.print("Hello, " + joe.getName() + ".  How much are we spending today? (eg., dollars.cents)  ");
		System.out.flush();
		double choice = in.readDouble();
		double price = choice * (1.0 - joe.getYogurtDisc());
		if (price > 0)
		{
			System.out.println("Just allow me to swipe your membership card ... ");
			//  calculate discount
			System.out.println("That'll be " + (Math.floor(price*100 + 0.5)/100) + ", thank you.\n\n");
		} else if (price < 0)
			System.out.println("Oh you want US to give YOU money?  I'm sorry, this isn't a bank.");
		else
			System.out.println("I guess you're not buying anything today.  See you later!");
	}


	//---------------------------------------------------------------------------------------------	
	//  checkAccount
	//
	//  input	:   	object of type GymMember
	//  return	:	none
	//
	//  Another silly program to test if user has correct account information.
	//---------------------------------------------------------------------------------------------		
	public static void checkAccount(GymMember bob)
	{
		System.out.println( bob.getName() + "\'s account number is: " + bob.getID());
		System.out.println(bob.getName() + "\'s account information is: \n" + bob.toString());
	}

}