package edu.wlu.cs.sprenkle;

/**
 * Demonstrates use of throwing IllegalArgumentExceptions to prevent errors.
 * Rewritten since class.
 * 
 * @author CSCI209
 */
public class Birthday implements Comparable<Birthday> {
	private int day;
	private int month;

	private static int[] DAYS_IN_MONTH = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

	private static String[] MONTHS = { "January", "February", "March", "April", "May", "June", "July", "August",
			"September", "October", "November", "December" };

	/**
	 * Creates a new Birthday object with the given month and day
	 * 
	 * @param month the integer month of the birthday, e.g., January is 1, February
	 *              is 2
	 * @param day   the day of the month of the birthday
	 */
	public Birthday(int month, int day) {
		super();
		setBirthday(month, day);
	}

	/**
	 * Returns a String representation of the Birthday as "month/day"
	 * 
	 * @return the Birthday as a string in the format "month/day"
	 */
	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append(month);
		builder.append("/");
		builder.append(day);
		return builder.toString();
	}
	
	/**
	 * Returns a String reperesentation of the Birthday as "month_name day"
	 * @return the Birthday as a string in the format "month_name day"
	 */
	public String longStringFormat() {
		StringBuilder builder = new StringBuilder();
		builder.append(MONTHS[month-1]);
		builder.append(" ");
		builder.append(day);
		return builder.toString();
	}

	/**
	 * Rather than setting the month and the day in separate methods, this is a
	 * better way to implement setting the month and the day. Why?
	 * 
	 * @param month the integer month of the birthday, e.g., January is 1, February
	 *              is 2
	 * @param day   the day of the month of the birthday
	 */
	public void setBirthday(int month, int day) {
		if (month < 1 || month > 12) {
			throw new IllegalArgumentException("month must be between 1 and 12");
		}
		if (day < 1 || day > 31) {
			throw new IllegalArgumentException("day must be between 1 and 31");
		}

		if (day > DAYS_IN_MONTH[month - 1]) {
			throw new IllegalArgumentException(MONTHS[month - 1] + " has only " + DAYS_IN_MONTH[month - 1] + " days.");
		}

		// only set the month and day after we know that
		// the month and day are valid.
		this.month = month;
		this.day = day;
	}

	
	/**
	 * Determines equality if both the month and the day match
	 */
	@Override
	public boolean equals(Object obj) {
		if( obj == this) {
			return true;
		}
		if( ! (obj instanceof Birthday )) {
			return false;
		}
		
		Birthday other = (Birthday) obj;
		
		if( other.getDay() != day ) {
			return false;
		}
		
		return other.getMonth() == month;
	}

	/**
	 * Returns the day of the month of the Birthday
	 * 
	 * @return the day of the month of the Birthday
	 */
	public final int getDay() {
		return day;
	}

	/**
	 * Returns the month of the Birthday, where 1 is January, 2 is February, ...
	 * 
	 * @return the month of the Birthday, where 1 is January, 2 is February, ...
	 */
	public final int getMonth() {
		return month;
	}

	/**
	 * Compares birthdays within the year. There is no year associated with this
	 * Birthday class.
	 */
	@Override
	public int compareTo(Birthday other) {
		if (month < other.getMonth()) {
			return -1;
		}
		if (month > other.getMonth()) {
			return 1;
		}
		// We know it's the same month.
		return day - other.getDay();
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Birthday b = new Birthday(1, 1);
		System.out.println("New Year's Baby: " + b);
		Birthday leapYearBaby = new Birthday(2, 29);
		System.out.println("Leap Year Baby: " + leapYearBaby);

		b.setBirthday(4, 30); // this should work
		System.out.println("End of April birthday: " + b);

		// Test calling the method with the exceptions:
		// Each of the statements below, separately, will throw an exception. // Comment
		// out the others to see what one of them does.
		// (Wouldn't it be great if we had a better way to test exceptions?)
		b.setBirthday(1, 32); // should throw an exception
		b.setBirthday(2, 30); // we'll never get to here because the last statement threw an exception
		b.setBirthday(0, 30);
		Birthday b2 = new Birthday(1, 32);

	}

}
