package com.planetmayo.debrief.satc.model.states;

import java.util.Date;

import com.planetmayo.debrief.satc.model.states.BaseRange.IncompatibleStateException;

public class BoundedState implements Comparable<BoundedState>
{
	private final Date _time;
	
	private SpeedRange _speed;
	
	private CourseRange _course;
	
	private LocationRange _location;
	
	/** the leg that this state is a member of
	 * 
	 */
	private String _memberOf;

	public BoundedState(Date time)
	{
		if (time == null) 
		{
			throw new IllegalArgumentException("time can't be null");
		}
		_time = time;
	}

	@Override
	public int compareTo(BoundedState o)
	{
		return getTime().compareTo(o.getTime());
	}

	/**
	 * apply all of the supplied state's constraints to ourselves
	 * 
	 * @param newState
	 */
	public void constrainTo(BoundedState newState)
			throws IncompatibleStateException
	{
		if (newState._speed != null)
			this.constrainTo(newState._speed);
		if (newState._course != null)
			this.constrainTo(newState._course);
		if (newState._location != null)
			this.constrainTo(newState._location);
	}

	/**
	 * apply the specified constraint to ourselves
	 * 
	 * @param range
	 */
	public void constrainTo(CourseRange range) throws IncompatibleStateException
	{
		// do we have any speed constraints?
		if (_course == null)
		{
			// no, better create some
			_course = new CourseRange(range);
		}
		else
		{ // yes, further constrain to this set
			_course.constrainTo(range);
		}
	}

	/**
	 * apply the specified constraint to ourselves
	 * 
	 * @param range
	 */
	public void constrainTo(LocationRange range)
			throws IncompatibleStateException
	{
		// do we have any speed constraints?
		if (_location == null)
		{
			// no, better create some
			_location = new LocationRange(range);
		}
		else
		{ // yes, further constrain to this set
			_location.constrainTo(range);
		}
	}

	/**
	 * apply the specified constraint to ourselves
	 * 
	 * @param range
	 */
	public void constrainTo(SpeedRange range) throws IncompatibleStateException
	{
		// do we have any speed constraints?
		if (_speed == null)
		{
			// no, better create some
			_speed = new SpeedRange(range);
		}
		else
		{ // yes, further constrain to this set
			_speed.constrainTo(range);
		}
	}
	
	public void setMemberOf(String legName)
	{
		_memberOf = legName;
	}
	
	public String getMemberOf()
	{
		return _memberOf;
	}

	public CourseRange getCourse()
	{
		return _course;
	}

	public LocationRange getLocation()
	{
		return _location;
	}

	public SpeedRange getSpeed()
	{
		return _speed;
	}

	public Date getTime()
	{
		return _time;
	}

}

@@ -246,18 +246,17 @@
  _time;%0A
-%09
 %0A
+
 %09private
@@ -275,18 +275,17 @@
 _speed;%0A
-%09
 %0A
+
 %09private
@@ -306,18 +306,17 @@
 course;%0A
-%09
 %0A
+
 %09private
@@ -345,14 +345,17 @@
 on;%0A
-%09
 %0A%09/**
+%0A%09 *
  the
@@ -482,17 +482,16 @@
 == null)
- 
 %0A%09%09%7B%0A%09%09%09
@@ -1375,33 +1375,36 @@
 ;%0A%09%09%7D%0A%09%09else%0A%09%09%7B
- 
+%0A%09%09%09
 // yes, further 
@@ -1421,24 +1421,38 @@
 to this set%0A
+%0A%09%09%09try%0A%09%09%09%7B%0A%09
 %09%09%09_course.c
@@ -1462,32 +1462,161 @@
 trainTo(range);%0A
+%09%09%09%7D%0A%09%09%09catch (IncompatibleStateException e)%0A%09%09%09%7B%0A%09%09%09%09// inject the state details%0A%09%09%09%09e.setFailingState(this);%0A%09%09%09%09throw e;%0A%09%09%09%7D%0A
 %09%09%7D%0A%09%7D%0A%0A%09/**%0A%09 *
@@ -2380,26 +2380,25 @@
 ge);%0A%09%09%7D%0A%09%7D%0A
-%09
 %0A
+
 %09public void
@@ -2459,10 +2459,9 @@
 %0A%09%7D%0A
-%09
 %0A
+
 %09pub
@@ -2708,24 +2708,24 @@
 etTime()%0A%09%7B%0A
-
 %09%09return _ti
@@ -2732,10 +2732,235 @@
 me;%0A%09%7D%0A%0A
+%09public void setLocation(LocationRange newRange)%0A%09%7B%0A%09%09_location = newRange;%0A%09%7D%0A%0A%09public void setSpeed(SpeedRange newRange)%0A%09%7B%0A%09%09_speed = newRange;%0A%09%7D%0A%0A%09public void setCourse(CourseRange newRange)%0A%09%7B%0A%09%09_course = newRange;%0A%09%7D%0A%0A
 %7D%0A

allow ranges to be overwritten (that's the only way to relax them)