package util;

import com.buglabs.bug.module.gps.pub.LatLon;

/**
 * Fun stuff you can do with LatLon objects. 
 * 
 * @author finsprings
 *
 */
public class PositionHelper {
	/// Equitorial radius of the Earth in kilometers
	private static final double EARTH_RADIUS = 6378.14;
	
	/**
	 * Use the Haversine formula to calculate the distance between two positions
	 * in kilometers. Wrap the answer in a call to kilometersToMiles() if you
	 * prefer imperial.
	 * 
	 * @param latLon1 first position
	 * @param latLon2 second position
	 * @return distance in kilometers between latLon1 and latLon2
	 */
	public static double calculateDistance(final LatLon latLon1, final LatLon latLon2) {
		final double dLat = Math.toRadians(latLon2.latitude - latLon1.latitude);
		final double dLon = Math.toRadians(latLon2.longitude - latLon1.longitude);
		final double a = Math.sin( dLat / 2) *
				Math.sin( dLat / 2) +
		        Math.cos( Math.toRadians( latLon1.latitude )) *
		        Math.cos( Math.toRadians( latLon2.latitude )) * 
		        Math.sin( dLon / 2) *
		        Math.sin( dLon / 2); 
		final double c = 2 * Math.atan2( Math.sqrt( a ), Math.sqrt( 1 - a )); 
		final double d = EARTH_RADIUS * c;
		
		return d;
	}
	
	public static double kilometersToMiles( final double km ) {
		return km * 5.0 / 8.0;
	}
	
	/**
	 * Converts a LatLon to a displayable format.
	 * TODO ideally this would be done by LatLon.toString() if it had one.
	 *
	 * @param latLon
	 * @return latLon in a displayable format
	 */
	public static String latLonToString( final LatLon latLon ) {
		/* System.out.println( "Converting (" + latLon.latitude + ", " +
				latLon.longitude  + ")" ); */
		long latDegrees = (long) Math.floor( Math.abs( latLon.latitude ) );
		long latMinutes = (long) Math.round( 100 * ( Math.abs( latLon.latitude ) - latDegrees ) * 0.6);
		final String latDir = (latLon.latitude < 0) ? "S" : "N";
		
		// cope with rounding up to a full degree
		if ( latMinutes == 60 ) {
			latDegrees = latDegrees + 1;
			latMinutes = 0;
		}
		
		long lonDegrees = (long) Math.floor( Math.abs( latLon.longitude ));
		long lonMinutes = (long) Math.round( 100 * ( Math.abs( latLon.longitude ) - lonDegrees ) * 0.6);
		
		// cope with rounding up to a full degree
		if ( lonMinutes == 60 ) {
			lonDegrees = lonDegrees + 1;
			lonMinutes = 0;
		}
			
		final String lonDir = (latLon.longitude < 0) ? "W" : "E";
		
		return "" + latDegrees + "\' " + latMinutes + "\" " + latDir +
			", " + lonDegrees + "\' " + lonMinutes + "\" " + lonDir;
	}
}