package au.gov.amsa.risky.format;

import com.google.common.base.Optional;
import com.google.common.base.Preconditions;

public final class Fix {

	public static boolean validate = true;
	private final long mmsi;
	private final float lat;
	private final float lon;
	private final long time;
	private final Optional<NavigationalStatus> navigationalStatus;
	private final Optional<Float> speedOverGroundKnots;
	private final Optional<Float> courseOverGroundDegrees;
	private final Optional<Float> headingDegrees;
	private final AisClass aisClass;
	private final Optional<Integer> latencySeconds;
	private final Optional<Short> source;

	public Fix(long mmsi, float lat, float lon, long time,
			Optional<Integer> latencySeconds, Optional<Short> source,
			Optional<NavigationalStatus> navigationalStatus,
			Optional<Float> speedOverGroundKnots,
			Optional<Float> courseOverGroundDegrees,
			Optional<Float> headingDegrees, AisClass aisClass) {

		if (validate) {
			if (courseOverGroundDegrees.isPresent()) {
				Preconditions.checkArgument(courseOverGroundDegrees.get() < 360
						&& courseOverGroundDegrees.get() >= 0, "cog="+ courseOverGroundDegrees.get());
			}
			if (headingDegrees.isPresent()) {
				Preconditions.checkArgument(headingDegrees.get() < 360
						&& headingDegrees.get() >= 0, "heading="+ headingDegrees.get());
			}
			Preconditions.checkArgument(lat>=-90 && lat <=90, "lat="+ lat);
			Preconditions.checkArgument(lon>=-180 && lon <=180, "lon="+ lon);
		}
		this.mmsi = mmsi;
		this.lat = lat;
		this.lon = lon;
		this.time = time;
		this.latencySeconds = latencySeconds;
		this.source = source;
		this.navigationalStatus = navigationalStatus;
		this.speedOverGroundKnots = speedOverGroundKnots;
		this.courseOverGroundDegrees = courseOverGroundDegrees;
		this.headingDegrees = headingDegrees;
		this.aisClass = aisClass;
	}

	public long getMmsi() {
		return mmsi;
	}

	public long getTime() {
		return time;
	}

	public float getLat() {
		return lat;
	}

	public float getLon() {
		return lon;
	}

	public Optional<NavigationalStatus> getNavigationalStatus() {
		return navigationalStatus;
	}

	public Optional<Float> getSpeedOverGroundKnots() {
		return speedOverGroundKnots;
	}

	public Optional<Float> getCourseOverGroundDegrees() {
		return courseOverGroundDegrees;
	}

	public Optional<Float> getHeadingDegrees() {
		return headingDegrees;
	}

	public AisClass getAisClass() {
		return aisClass;
	}

	public Optional<Integer> getLatencySeconds() {
		return latencySeconds;
	}

	public Optional<Short> getSource() {
		return source;
	}

	public Optional<Byte> getRateOfTurn() {
		return Optional.absent();
	}

	@Override
	public String toString() {
		StringBuilder b = new StringBuilder();
		b.append("Fix [mmsi=");
		b.append(mmsi);
		b.append(", lat=");
		b.append(lat);
		b.append(", lon=");
		b.append(lon);
		b.append(", time=");
		b.append(time);
		b.append(", navigationalStatus=");
		b.append(navigationalStatus);
		b.append(", speedOverGroundKnots=");
		b.append(speedOverGroundKnots);
		b.append(", courseOverGroundDegrees=");
		b.append(courseOverGroundDegrees);
		b.append(", headingDegrees=");
		b.append(headingDegrees);
		b.append(", aisClass=");
		b.append(aisClass);
		b.append(", latencySeconds=");
		b.append(latencySeconds);
		b.append(", source=");
		b.append(source);
		b.append("]");
		return b.toString();
	}

}

@@ -180,16 +180,17 @@
 = true;%0A
+%0A
 %09private
@@ -683,20 +683,17 @@
 ng time,
-%0A%09%09%09
+ 
 Optional
@@ -717,16 +717,25 @@
 Seconds,
+%0A%09       
  Optiona
@@ -750,20 +750,17 @@
  source,
-%0A%09%09%09
+ 
 Optional
@@ -797,26 +797,32 @@
 nalStatus,%0A%09
-%09%09
+        
 Optional%3CFlo
@@ -846,20 +846,17 @@
 ndKnots,
-%0A%09%09%09
+ 
 Optional
@@ -889,18 +889,24 @@
 grees,%0A%09
-%09%09
+        
 Optional
@@ -969,16 +969,297 @@
 date) %7B%0A
+%09%09%09Preconditions.checkNotNull(navigationalStatus);%0A%09%09%09Preconditions.checkNotNull(courseOverGroundDegrees);%0A%09%09%09Preconditions.checkNotNull(headingDegrees);%0A%09%09%09Preconditions.checkNotNull(aisClass);%0A%09%09%09Preconditions.checkNotNull(latencySeconds);%0A%09%09%09Preconditions.checkNotNull(source);%0A
 %09%09%09if (c
@@ -1368,18 +1368,24 @@
 360%0A%09%09%09%09
-%09%09
+        
 && cours
@@ -1418,15 +1418,28 @@
 = 0,
+%0A%09%09%09%09       
  %22cog=%22
+ 
 + co
@@ -1542,16 +1542,29 @@
 rgument(
+%0A%09%09%09%09        
 headingD
@@ -1585,15 +1585,9 @@
  360
-%0A%09%09%09%09%09%09
+ 
 && h
@@ -1622,16 +1622,37 @@
 eading=%22
+%0A%09%09%09%09                
 + headin
@@ -1707,18 +1707,20 @@
 ment(lat
+ 
 %3E=
+ 
 -90 && l
@@ -1724,16 +1724,17 @@
 & lat %3C=
+ 
 90, %22lat
@@ -1735,16 +1735,17 @@
 , %22lat=%22
+ 
 + lat);%0A
@@ -1778,18 +1778,20 @@
 ment(lon
+ 
 %3E=
+ 
 -180 && 
@@ -1796,16 +1796,17 @@
 & lon %3C=
+ 
 180, %22lo
@@ -1808,16 +1808,17 @@
 , %22lon=%22
+ 
 + lon);%0A

add validations to Fix