// fromto.js
//
// javascript library for displaying route to selected location

//
// Configuration variables
//
// Location shown when map first presented
var start_place = 'Melbourne, Australia';
//
// Zoom level should the map be at when first presented
var start_zoom = 10;
//
// Set the Map type to display (G_NORMAL_MAP, G_SATELLITE_MAP, G_HYBRID_MAP)
var map_type = G_NORMAL_MAP; 
//
// Use custom icons instead of default map pins?
var custom_icons_enabled = false;
//
// End of Configuration variables - Do not edit below this line
//

// Custom Icons
//
// The following are included as *examples* .
//
var icons = {};
// Specify an icon for the 'from' position
icons['from'] = new GIcon();
icons['from'].image = 'images/tempMarker.png';
icons['from'].iconSize = new GSize(32, 21);
icons['from'].iconAnchor = new GPoint(0, 11);
//
// Specify an icon for the 'from' position
icons['to'] = new GIcon();
icons['to'].image = 'images/tempMarker.png';
icons['to'].iconSize = new GSize(32, 21);
icons['to'].iconAnchor = new GPoint(0, 11);

var map;				// The map on the page
var geocoder;			// gmaps geocoder object
var directions;			// directions object
var routeline;			// remove from map with "map.removeOverlay(routeLine)"
var bounds;

// This is where we start the start and end point. 
var points = {
	from: { name: null, address: null, point: null, marker: null}, 
	to:   { name: null, address: null, point: null, marker: null}
}; 

// only defined here to make debugging easier
var directionsHTML;
var directionsPanel;

// Initialize some objects and display the map
function load() {
	if (GBrowserIsCompatible()) {
		map = new GMap2(document.getElementById("map"));
		directionsPanel = document.getElementById("directions_panel"); // XXX what if missing?
		geocoder = new GClientGeocoder();
		map.setCenter(new GLatLng(37.4419, -122.1419), start_zoom);
		geocoder.getLatLng(
	    	start_place,
	    	function(point) {
				map.setCenter(point, start_zoom);
				map.setMapType(map_type);
			}
	  	);
	}
}

// Set the start or end point and redraw the map
function setPoint(type, address, place_name) {
	if (! address) return false;
	geocoder.getLatLng(
    	address,
    	function(point) {
			if (!point) {
				alert(address + " not found");
			} else {
				points[type].point = point;
				points[type].place_name = place_name;
				points[type].address = address;
				redrawMap();
			}
		}
  	);
}

// Clear the map and redraw markers and polyline (when appropriate)
function redrawMap() {
    map.clearOverlays();
	if (points.from.point && points.to.point) {
		requestRoute();
	} else if (point = (points.from.point || points.to.point)) {
		addMarker('from') || addMarker('to');
		map.setCenter(point, 11);	
	}
}

// Add a marker to the map
function addMarker(type) {
	if (points[type].point) {
		icon = (custom_icons_enabled ? icons[type] : null );
		points[type].marker = new GMarker(points[type].point, icon);		
		map.addOverlay(points[type].marker);
		return true; // we can use boolean when calling this function now
	}
}

// Update the start and end points with values in the form
function updateMap() {
	map.clearOverlays();
	setPoint('from', document.getElementById('from').value, '');
	setPoint('to', document.getElementById('to').value, 
		document.getElementById('to').options[document.getElementById('to').selectedIndex].text);
}

// Send a request to Gmaps for directions and a polyline from A to B.
function requestRoute() {
	if (points.from.point && points.to.point) {
		
		directions = new GDirections();
		// This alternative method of calling GDirections results in Gmaps updating 
		// the map and directions on the page. We prefer to do it ourselves to control 
		// the styling/functionality directions = new GDirections(map, directionsPanel);
		
		// Deal with error when Gmaps fails to look up address
		var handleErrors = function () {
			var status = directions.getStatus();
			//debugger;
			alert('Unable to find directions from your location - please be more specific');
		};
		
		directions.load(points.from.address + ' to ' + points.to.address, {getPolyline: true, getSteps: true});
		GEvent.addListener(directions, "error", handleErrors);
		GEvent.addListener(directions, "load", onGDirectionsLoad);
	}
}

// This callback is used by requestRoute() to process the directions returned by Gmaps
function onGDirectionsLoad() {
	if (document.getElementById("distance") && directions.getDistance()){
		document.getElementById("distance").innerHTML = directions.getDistance().html;
	}
	if (document.getElementById("duration") && directions.getDuration()){
		document.getElementById("duration").innerHTML = directions.getDuration().html;
	}
	
	// display the polyline for the directions
	map.clearOverlays();
	routeLine = directions.getPolyline();
	map.addOverlay(routeLine);
	
	addMarker('from');
	addMarker('to');
	centerMap();
	
	buildDirectionsHTML();	
}

// Build up HTML with nicely formatted directions to display on page
function buildDirectionsHTML(){
	var route = directions.getRoute(0);
	if (! route ) return false;
	
	directionsHTML = [];
	directionsHTML.push('<p>'+points.from.place_name + ' '+route.getStartGeocode().address+'</p>');
	steps = [];
	for (index=0; index<route.getNumSteps(); index++) {
		step = route.getStep(index);
		stepHTML = '<span>'+step.getDescriptionHtml()+'</span>';
		stepHTML += '<span>'+step.getDistance().html+'</span>';
		steps.push('<li>'+stepHTML+'</li>')
	}
	directionsHTML.push('<ol>' + steps.join("\n") + '</ol>');
	directionsHTML.push('<p>'+points.to.place_name + ' '+route.getEndGeocode().address+'</p>');
	if (document.getElementById("directions_html") && directionsHTML) {
		document.getElementById("directions_html").innerHTML = directionsHTML.join("\n");
	}
}

function centerMap() {
	bounds = new GLatLngBounds();
	bounds.extend(points.from.point);
	bounds.extend(points.to.point);
	map.setCenter(bounds.getCenter());
	map.setZoom(map.getBoundsZoomLevel(bounds));
}
	