// Copyright 2003 by Basil Vandegriend. All rights reserved.

package com.basilv.core;

import java.sql.Date;

/**
 * Represents a period of time.
 */
public class DateRange
{

	private Date start;

	private Date end;

	public DateRange(Date start, Date end) {
		this.start = start;
		this.end = end;
	}

	public Date getStart() {
		return start;
	}

	public Date getEnd() {
		return end;
	}

	public boolean isValid() {
		if (getStart() == null) {
			return false;
		}

		return !isEndBeforeStart();
	}

	public boolean isEndBeforeStart() {
		if (getEnd() == null || getStart() == null) {
			return false;
		}

		return getEnd().before(getStart());
	}

	/**
	 * Return true if this date range overlaps with the other date range.
	 */
	public boolean overlaps(DateRange other) {
		Assert.notNull("other", other);

		// Invalid dates don't overlap
		if (!isValid() || !other.isValid()) {
			return false;
		}

		// If both ranges have the same endpoint null, then there is overlap
		// this : [------------
		// other: [-----
		if (getStart() == null && other.getStart() == null) {
			return true;
		}

		// Start date of one range within the other range
		// this : [------]
		// other: [------]
		if (contains(other.getStart())) {
			return true;
		}

		// Other start is before this start, but end is contained
		// this : [---]
		// other: [---]
		// OR
		// this : [---]
		// other: [---------
		if (other.getStart().before(getStart())) {
			if (other.getEnd() == null || !other.getEnd().before(getStart())) {
				return true;
			}
		}

		return false;
	}

	/**
	 * Return true if this date range contains the specified date.
	 */
	public boolean contains(Date date) {
		Assert.notNull("date", date);

		boolean afterStart = true;
		boolean beforeEnd = true;

		if (getStart() != null && getStart().after(date)) {
			afterStart = false;
		}

		if (getEnd() != null && getEnd().before(date)) {
			beforeEnd = false;
		}

		return afterStart && beforeEnd;
	}

}
