package adjusting.availability_adjusting;

import java.io.Serializable;
import java.util.GregorianCalendar;

/**
 * This class represents the artificial failure period which will occur for the server.
 * 
 * A collection of these objects constructs a Failure Trace for a specific Server
 * object.
 * 
 * @see FailureTrace
 * 
 * @author Majd Kokaly
 * 
 */
public class FailurePeriod implements Serializable {
	/**
	 * The serialVersionUID is used to universally identify this version of this
	 * class.
	 */
	private static final long serialVersionUID = 1529667125846716840L;

	/**
	 * The time when this period begins.
	 */
	GregorianCalendar beginningTime;

	/**
	 * The time when this period ends.
	 */
	GregorianCalendar endTime;

	/**
	 * The default constructor
	 * 
	 * @param beginningTime
	 *            Sets the data member beginningTime.
	 * @param endTime
	 *            Sets the data member endTime.
	 */
	public FailurePeriod(GregorianCalendar beginningTime, GregorianCalendar endTime) {
		this.setBeginningTime(beginningTime);
		this.setEndTime(endTime);

		if (beginningTime.after(endTime)) {
			endTime = (GregorianCalendar) beginningTime.clone();
			this.setEndTime(endTime);
			System.err.print("FailingPeriod.FailingPeriod(): beggining time is after end time.");
		}
	}

	public GregorianCalendar getBeginningTime() {
		return beginningTime;
	}

	private void setBeginningTime(GregorianCalendar beginningTime) {
		this.beginningTime = beginningTime;
	}

	public GregorianCalendar getEndTime() {
		return endTime;
	}

	private void setEndTime(GregorianCalendar endTime) {
		this.endTime = endTime;
	}

	/**
	 * 
	 * @param time
	 *            Is a GregorianCalendar (i.e time object).
	 * @return true if time lies within this FailurePeriod object and false otherwise.
	 */
	protected boolean isTimeInPeriod(GregorianCalendar time) {
		return (time.after(this.getBeginningTime()) && time.before(this.getEndTime()));
	}

	/**
	 * @param period
	 *            is a FailurePeriod object to be checked
	 * @return true if the period object is overlapping with this FailurePeriod
	 *         object.
	 */
	protected boolean isOverLapped(FailurePeriod period) {
		return (this.isTimeInPeriod(period.getBeginningTime()) || this.isTimeInPeriod(period.getEndTime()) || 
				(period.getBeginningTime().before(this.beginningTime) && period.getEndTime().after(this.endTime)));
	}

	/**
	 * 
	 * @return the length of this period in minutes
	 */
	public double getLengthInMinutes() {
		return (this.getEndTime().getTimeInMillis() - this.getBeginningTime().getTimeInMillis()) / 60000.0;
	}

	/**
	 * 
	 * @return the length of this period in milliseconds
	 */
	public double getLengthInMillis() {
		return (this.getEndTime().getTimeInMillis() - this.getBeginningTime().getTimeInMillis());
	}

	public String toString() {
		return this.getBeginningTime().getTime().toString() + " - " + this.getEndTime().getTime().toString() + "("
				+ this.getLengthInMinutes() + " minutes )";
	}

	public void print() {
		System.out.println(this.toString());
	}

}
