    var map;
    var gdir;
    var geocoder = null;
    var addressMarker;
    var wayPointCount = 0;
    var bounds = null;
    var markers = null;
    var rail;
    
    // We need 7 different search objects .. eek!
    // as each one needs a different callback
    // Couldn't find a better way to do this :(
   	var startLocationPostcodeSearch = new GlocalSearch();
   	var endLocationPostcodeSearch = new GlocalSearch();
   	var wayPoint1PostcodeSearch = new GlocalSearch();
   	var wayPoint2PostcodeSearch = new GlocalSearch(); 
   	var wayPoint3PostcodeSearch = new GlocalSearch(); 
   	var wayPoint4PostcodeSearch = new GlocalSearch(); 
   	var wayPoint5PostcodeSearch = new GlocalSearch(); 
   	
   	// Setup the call backs for each
   	startLocationPostcodeSearch.setSearchCompleteCallback(null, startLocationPostcodeCallback);
   	endLocationPostcodeSearch.setSearchCompleteCallback(null, endLocationPostcodeCallback);  
   	wayPoint1PostcodeSearch.setSearchCompleteCallback(null, wayPoint1PostcodeCallback);
   	wayPoint2PostcodeSearch.setSearchCompleteCallback(null, wayPoint2PostcodeCallback);
   	wayPoint3PostcodeSearch.setSearchCompleteCallback(null, wayPoint3PostcodeCallback);
   	wayPoint4PostcodeSearch.setSearchCompleteCallback(null, wayPoint4PostcodeCallback);
   	wayPoint5PostcodeSearch.setSearchCompleteCallback(null, wayPoint5PostcodeCallback);
   	  	   	   	   	

    
    // The number of post codes that need geocoding
    var numPostcodesToGeocode = 0;
    // The number of post code that have been geocoded
    var numPostcodesGeocoded = 0;
    
    // LatLngs for the 7 possible locations
    // Will be populated if any were entered as a postcode
    var startLocationLatLng = null;
    var endLocationLatLng = null;
    
    var wayPoint1LatLng = null;
    var wayPoint2LatLng = null;
    var wayPoint3LatLng = null;
    var wayPoint4LatLng = null;
    var wayPoint5LatLng = null;
    
    // Postcodes entered for 7 possible locations
    // Will be populate if any were entered as a postcode   
    var startLocationPostcode = null;
    var endLocationPostcode = null;  
    var wayPointPostcodes = [];				
          
    /*var wayPoint1Postcode = null;
    var wayPoint2Postcode = null;
    var wayPoint3Postcode = null;
    var wayPoint4Postcode = null;
    var wayPoint5Postcode = null; */  

/*
	var walkModeCategory = 9;
	var cycleModeCategory = 10;	
	var motorcycleModeCategory = 11;
	var busModeCategory = 12;
	var carModeCategory = 13;
	var railModeCategory = 14;
	var flyModeCategory = 15;
	var tubeModeCategory = 17;
	var taxiModeCategory = 18;

*/
  	
  	var flyCategoryId = 15;
  	var tubeCategoryId = 17;
	var railCategoryId = 14;

	/* Initialize Map */
    function initialize() 
    {
      if (GBrowserIsCompatible()) 
      { 
        map = new GMap2(document.getElementById("map_canvas"));
        gdir = new GDirections(map);
        bounds = new GLatLngBounds();
        markers = new Array();
        
        rail = new RRDirections(map, 'test');
        
        reset();
        
        // Set the map center
        map.setCenter(new GLatLng(52.961875, -2), 6);
        
        //map.addControl(new GLargeMapControl());
        map.addControl(new GMapTypeControl());
        map.addControl(new GSmallMapControl());

        
        GEvent.addListener(gdir, "load", onGDirectionsLoad);
        GEvent.addListener(gdir, "error", handleErrors);

      }
    }
    
    /* ------------------------------------------------------------------ */
    /* Common */    
    
    // Reset the default (UK directions map)
    function resetDefaultMap()
    {
        // Set the map center
        map.setCenter(new GLatLng(52.961875, -2), 6);   

      	// Clear overlays
		map.clearOverlays();
		// Clear bounds
		bounds = new GLatLngBounds();
		// Clear markers
		markers = new Array();  
    }
    
    // Reset the fly map
    function resetFlyMap()
    {
		// Centre the map
      	map.setCenter(new GLatLng(34, 0), 1);
      	// Clear overlays
		map.clearOverlays();
		// Clear bounds
		bounds = new GLatLngBounds();
		// Clear markers
		markers = new Array();    
    }    
    
    // Main function to start any distance calculation
	function getDistance()
	{
		$('error_message').style.display = "none";
		
    	if (($('TravelModeCategoryId').options[$('TravelModeCategoryId').selectedIndex]).value == -1)
    	{
    		alert('Please select your mode of transport first');    	
    	}
    	else
    	{
    		// Are they flying
    		if (($('TravelModeCategoryId').options[$('TravelModeCategoryId').selectedIndex]).value == flyCategoryId)
    		{
    			setFlyPoints();
    		}
    		else if (($('TravelModeCategoryId').options[$('TravelModeCategoryId').selectedIndex]).value == tubeCategoryId)
    		{
    			tubeDirections('tube');
    		}
    		else if (($('TravelModeCategoryId').options[$('TravelModeCategoryId').selectedIndex]).value == railCategoryId)
    		{
    			tubeDirections('rtm');
    		}
    		else
    		{
    			directionsFirstPass();
    		}
    		
    		
    		    	
    	}
	}
	
	function showRailInput()
	{
		$("rail_help_text").style.display = "block";	
		$("tube_help_text").style.display = "none";			
		$("fly_help_text").style.display = "none";
		$("standard_help_text").style.display = "none";
		$("standard_help_text2").style.display = "none";
		
		clearFields();
		
		$("addDestinationLink").style.display = "none";	
	}
	function showTubeInput()
	{
		$("rail_help_text").style.display = "none";		
		$("tube_help_text").style.display = "block";	
		$("fly_help_text").style.display = "none";
		$("standard_help_text").style.display = "none";
		$("standard_help_text2").style.display = "none";
		
		clearFields();
		
		$("addDestinationLink").style.display = "none";	
	}
	
	// Show the input box and text for flying journeys
	function showFlyInput()
	{
		$("rail_help_text").style.display = "none";			
		$("fly_help_text").style.display = "block";
		$("tube_help_text").style.display = "none";			
		$("standard_help_text").style.display = "none";
		$("standard_help_text2").style.display = "none";		
		
		clearFields();
		
		$("addDestinationLink").style.display = "none";
	}
	
	// Show the input box and text for other journeys
	function showDefaultInput()
	{
		$("rail_help_text").style.display = "none";			
		$("fly_help_text").style.display = "none";
		$("tube_help_text").style.display = "none";					
		$("standard_help_text").style.display = "block";
		$("standard_help_text2").style.display = "block";
		
		clearFields();
		
		$("addDestinationLink").style.display = "block";
	

	}
	
	// Reset the journey box fully
	function reset()
	{
		hideErrors();
		editJourney();
		clearFields();
		
    	// Are they flying
    	if (($('TravelModeCategoryId').options[$('TravelModeCategoryId').selectedIndex]).value == flyCategoryId)
    	{
    		showFlyInput();
    	}
    	else if (($('TravelModeCategoryId').options[$('TravelModeCategoryId').selectedIndex]).value == tubeCategoryId)
    	{
    		showTubeInput();
    	}
    	else if (($('TravelModeCategoryId').options[$('TravelModeCategoryId').selectedIndex]).value == railCategoryId)
    	{
    		showRailInput();
    	}
    	else
    	{
    		showDefaultInput();
    	}		
		
	}
	
	function resetVars()
	{
		numPostcodesToGeocode = 0;
		numPostcodesGeocoded = 0;
		wayPointCount= 0;	
		
		startLocationLatLng = null;
		endLocationLatLng = null;		
	    wayPoint1LatLng = null;
	    wayPoint2LatLng = null;
	    wayPoint3LatLng = null;
	    wayPoint4LatLng = null;
	    wayPoint5LatLng = null; 	
	    
	    startLocationPostcode = null;
	    endLocationPostcode = null; 
	   	wayPointPostcodes = [];	
	   				
	    /*wayPoint1Postcode = null;
	    wayPoint2Postcode = null;
	    wayPoint3Postcode = null;
	    wayPoint4Postcode = null;
	    wayPoint5Postcode = null;*/    	    
	}
	
	// Clear all journey realted input fields
	function clearFields()
	{
		$("JourneyEmissionsInputStartLocation").value = "";
		$("JourneyEmissionsInputEndLocation").value = "";		
		$("JourneyEmissionsInputWayPoint1").value = "";
		$("JourneyEmissionsInputWayPoint2").value = "";
		$("JourneyEmissionsInputWayPoint3").value = "";
		$("JourneyEmissionsInputWayPoint4").value = "";
		$("JourneyEmissionsInputWayPoint5").value = "";
		$("JourneyEmissionsInputDistance").value = "";		
		
		$("wayPoint1Div").style.display = "none";
		$("wayPoint2Div").style.display = "none";
		$("wayPoint3Div").style.display = "none";
		$("wayPoint4Div").style.display = "none";
		$("wayPoint5Div").style.display = "none";
		
		showAjaxWait(false);		
		resetVars();
		
               				
	}
	
	// Show the edit journey 'page'
	function editJourney()
	{
		showAjaxWait(false);	
		$("journey_input_container").style.display = "block";
		$("journey_overview_container").style.display = "none";	
		$("select_journey_header").innerHTML = "Select journey";
		hideErrors();	
	}
	
	// Show the view journey 'page'
	function viewJourneyOverview()
	{
		$("journey_input_container").style.display = "none";
		$("journey_overview_container").style.display = "block";	
		$("select_journey_header").innerHTML = "Your journey";
			
	}	
	
	// Render the overview of a journey
	function renderJourneyOverview(locations, distance, letterMarkers)
	{
		if (letterMarkers == null)
		{
			letterMarkers = true;
		}
		
		var trTemplate = new Template('<tr><td class="marker">#{img}</td><td>#{location}</td></tr>');
		
		var html = "<table>";
		
		for (i=0; i < locations.length; i++)
		{
			if (letterMarkers)
			{
				var location = {img: '<img src=\"/img/maps/icon_green' + i + '_bluebg.png\"/>', location: locations[i] };
			}
			else
			{
				var location = {img: '<img src=\"/img/maps/red-dot_bluebg.png\"/>', location: locations[i] };			
			}
			
			// let's format our data
			html += trTemplate.evaluate(location);		
		}

		html += "</table>";
		html += "<div class=\"distance\">Total Distance: " + distance + "km</div>";

		$("journey_overview").innerHTML = html;	

	}    
    
    function showTubeErrorMessage()
    {
    	$('tube_error_message').style.display = "block";          
    }
    
    // Show the error message relevant to flying routes
    function showFlyErrorMessage()
    {
    	$('fly_error_message').style.display = "block";      
    }
    
    // Show the general error message
    function showErrorMessage()
    {
		$('error_message').style.display = "block";        
    }
    
    // Hide all errors
    function hideErrors()
    {
    	$('error_message').style.display = "none";
    	$('fly_error_message').style.display = "none";  
    	$('tube_error_message').style.display = "none";
    	$('rail_error_message').style.display = "none";               	
    }    

    
    /* ------------------------------------------------------------------ */
    /* Postcodes */   
    
    //endLocationPostcodeCallback
    
    function postcodeSearchResultsToPoint(results)
    {
	      if (results[0]) 
	      {    
	        var resultLat = results[0].lat;
	        var resultLng = results[0].lng;
	        var point = new GLatLng(resultLat,resultLng);
	        return point;
	      }
	      
	      return null;
     
    }
    
	function postcodeSearch(postcode, search)
	{
		search.execute(postcode + ", UK");		
	}

	
	// Determines if a string is a valid postcode
	function containsValidPostcode(p) 
	{
		var containsPostCode = false;
		
		//var postcodeRegEx = /[A-Z]{1,2}[0-9]{1,2} ?[0-9][A-Z]{2}/i;
		var postcodeRegEx = /[A-Z]{1,2}[0-9][0-9A-Z]{0,1} ?[0-9][A-Z]{2}/i;		
		
		containsPostCode = postcodeRegEx.test(p);
		
		return containsPostCode;
		
		//var postcodeRegEx = /[A-Z]{1,2}[0-9]{1,2} ?[0-9][A-Z]{2}/i;
		//containsPostCode = postcodeRegEx.test(p)		
	}
	    
    
    /* ------------------------------------------------------------------ */
    /* Fly Routes */
    
	// Starts the process of searching for fly from / to points
	function setFlyPoints()
	{
		resetFlyMap();
		hideErrors();

		var startLocation = $('JourneyEmissionsInputStartLocation').value;
		var endLocation = $('JourneyEmissionsInputEndLocation').value;

		// Do we have a starnd and endLocation as a minimum?
		if (startLocation == null || startLocation == "" ||
			endLocation == null || endLocation == "")
		{
			alert("Please enter a start and end location");
		}
		else
		{
		 	search(startLocation, true);
		 	search(endLocation, false);
		
		}

	}  

	// Calls the geonames JSON webservice with the search term
	function search(locationName, startLocation) 
	{
		showAjaxWait(true);
			
		var callBack = "addEndFlyLocation";
		
		if (startLocation)
		{
			callBack = "addStartFlyLocation";
		}
		
		var airport = "";
		if (locationName.length == 3)
		{
			airport = "&featureCode=AIRP";
		}

		request = 'http://ws.geonames.org/searchJSON?q=' +  escape(locationName)  + '&maxRows=1&callback=' + callBack + airport;
	
		// Create a new script object
		// (implementation of this class is in /export/jsr_class.js)
		aObj = new JSONscriptRequest(request);
		// Build the script tag
		aObj.buildScriptTag();
		// Execute (add) the script tag
		aObj.addScriptTag();
	}
	
	// Populates the start location text field when data is found
	function addStartFlyLocation(jData)
	{		
		// If we have data we can do start location specific stuff here
		if (jData != null)
		{
			if (jData.geonames != null)
			{
				if (jData.geonames[0] != null)
				{
					$('JourneyEmissionsInputStartLocation').value = jData.geonames[0].name;	
		        }
	       	}
        }
        	
		addFlyLocation(jData);
	}
	
	// Populates the end location text field when data is found	
	function addEndFlyLocation(jData)
	{
		
		if (jData != null)
		{
			if (jData.geonames != null)
			{		
				// If we have data we can do end location specific stuff here
				if (jData.geonames[0] != null)
				{
					$('JourneyEmissionsInputEndLocation').value = jData.geonames[0].name;	
		        }
		    }
		}	
		        	
		addFlyLocation(jData);
	}
	
	
	// Add the fly from location to the Google Map
	function addFlyLocation(jData)
	{
		if (jData != null)
		{
			// We are only requesting one result, if that's null, nothing was found
			if (jData.geonames == null)
			{
					$('fly_error_message').style.display = "block";
					showAjaxWait(false);						
			}
			else
			{
				if (jData.geonames[0] == null)
				{
					$('fly_error_message').style.display = "block";	
					showAjaxWait(false);													
	        	}
	        	else
	        	{
		        	var latlng = new GLatLng(jData.geonames[0].lat, jData.geonames[0].lng);
		              
		            var marker = new GMarker(latlng);                 
		        	map.addOverlay(marker);
		        	bounds.extend(marker.getPoint());
		        	        	
		        	markers.push(marker);
		        	
		        	if (markers.length == 2)
		        	{
						showAjaxWait(false);						
							        	
		        		// Zoom to bounds
						map.setZoom(map.getBoundsZoomLevel(bounds));
						map.setCenter(bounds.getCenter()); 
				      
				        var polyOptions = {geodesic:true};
				        
				        var polyline = new GPolyline([markers[0].getLatLng(),
				          markers[1].getLatLng()], "#ff0000", 4, 1, polyOptions);
				          
				        var distanceM = polyline.getLength();
						var distanceKm = distanceM / 1000;
						distanceKm = distanceKm.toFixed(2);	
						
						// Have they put in the same start and end locations
						if (distanceM > 0)
						{
					        $('JourneyEmissionsInputDistance').value = distanceKm;
		
					        map.addOverlay(polyline);
					        
					       			       
					        var locations = new Array();
					        locations.push($('JourneyEmissionsInputStartLocation').value);
					        locations.push($('JourneyEmissionsInputEndLocation').value);
					        
							renderJourneyOverview(locations, distanceKm, false);				
							viewJourneyOverview();	
						}
						else
						{
							resetFlyMap();
							showFlyErrorMessage();
							clearFields();
						}		        
				      
				             		
		        	}        	
	        	}
        	}
			
		}
		else
		{
			$('fly_error_message').style.display = "block";					
		}

	}	
	  
    
    function showAjaxWait(show)
    {
    	if(show)
    	{
			$('ajax_wait').style.display = "block";
			$('calc_distance_button').style.display = "none";		    	
    	}
    	else
    	{
			$('ajax_wait').style.display = "none";
			$('calc_distance_button').style.display = "block";		    	
    	}

    }
    
    
    /* ------------------------------------------------------------------ */
    /* Tube Directions */   

	function tubeDirections(mode)
	{
    	resetVars();
    	resetDefaultMap();
    	
		var startLocation = $('JourneyEmissionsInputStartLocation').value;
		var endLocation = $('JourneyEmissionsInputEndLocation').value;
		
		// Do we have a starnd and endLocation as a minimum?
		if (startLocation == null || startLocation == "" ||
			endLocation == null || endLocation == "")
		{
			alert("Please enter a start and end location");
		}
		else
		{
			showAjaxWait(true);
			
			// Array of route locations
			var wayPoints = new Array();
			
			// Add the start location and end location, we know they're not empty
			wayPoints.push(startLocation);
			wayPoints.push(endLocation);
			
			// Load from waypoints doesn't seem to work
	    	//rail.loadFromWaypoints(['bank', 'camden town']);
	    	
	    	// Setup query option with callbacks
			var queryOpts = {locale:"en_GB", modes:mode, onaddoverlay: function() {onRRDirectionsLoad();}, onerror: function() {tubeHandleErrors();}};
			// Attempt to load the directions
	    	rail.load(startLocation + " to " + endLocation, queryOpts);	
		}	
	}
	
	function onRRDirectionsLoad()
	{
		showAjaxWait(false);
    	
		// Distance comes back in m, need to convert to km
		var distanceM = rail.getDistance().meters;
		var distanceKm = distanceM / 1000;
		distanceKm = distanceKm.toFixed(2);
		
		if (distanceM == 0)
		{

			clearFields();
			showErrorMessage();
			
		} 
		else
		{		
			// Make it look pretty in title case
			$("JourneyEmissionsInputStartLocation").value = toTitleCase($("JourneyEmissionsInputStartLocation").value);
			$("JourneyEmissionsInputEndLocation").value = toTitleCase($("JourneyEmissionsInputEndLocation").value);

			$("JourneyEmissionsInputDistance").value = distanceKm;
			$("JourneyEmissionsInputStartLocation").value;
			$("JourneyEmissionsInputEndLocation").value;
			
			
			var locations = new Array();
//begin new code
			var marker = rail.getMarker(0);
			var placename = (marker.info && (typeof marker.info.name == 'string')) ? marker.info.name : $("JourneyEmissionsInputStartLocation").value;
			locations.push(placename);
			
			var marker = rail.getMarker(1);
			var placename = (marker.info && (typeof marker.info.name == 'string')) ? marker.info.name : $("JourneyEmissionsInputEndLocation").value;
			locations.push(placename);
//end new code	
			renderJourneyOverview(locations, distanceKm);				
			viewJourneyOverview();	
		}		
	}
	
	function tubeHandleErrors()
	{
		showAjaxWait(false);
		showTubeErrorMessage();	
	}  

   	
    /* ------------------------------------------------------------------ */
    /* Directions */
    
    function postCodeLookupError()
    {
		$('error_message').style.display = "block";
		showAjaxWait(false);
		resetVars();
   	}
    
    // Runs the second directions pass if ready
    // i.e. if all postcode lookups have returned
    function runSecondPassIfReady()
    {
    	if (numPostcodesGeocoded == numPostcodesToGeocode)
    	{
    		directionsSecondPass();
    	}
    }   
    
    // Start location
    function startLocationPostcodeCallback()
    {
    	point = postcodeSearchResultsToPoint(startLocationPostcodeSearch.results);
    	if (point == null)
    	{ 
    		postCodeLookupError(); 
    	}
    	else
    	{
    		startLocationLatLng = point;
    		numPostcodesGeocoded++;
    		runSecondPassIfReady();
    	}	    
   	} 
   	
   	// End location
    function endLocationPostcodeCallback()
    {
    	point = postcodeSearchResultsToPoint(endLocationPostcodeSearch.results);    
    	if (point == null)
    	{ 
    		postCodeLookupError(); 
    	}
    	else
    	{   
    		endLocationLatLng = point;
            numPostcodesGeocoded++;
    		runSecondPassIfReady();
    	}
   	} 
   	
   	// Waypoint 1
    function wayPoint1PostcodeCallback()
    {
    	point = postcodeSearchResultsToPoint(wayPoint1PostcodeSearch.results);        
    	if (point == null)
    	{ 
    		postCodeLookupError(); 
    	}
    	else
    	{    
    		wayPoint1LatLng = point;
    		numPostcodesGeocoded++;
    		runSecondPassIfReady();
    	}	    		    
   	} 
   	
   	// Waypoint 2
    function wayPoint2PostcodeCallback()
    {
    	point = postcodeSearchResultsToPoint(wayPoint2PostcodeSearch.results);            
    	if (point == null)
    	{ 
    		postCodeLookupError(); 
    	}
    	else
    	{    
    		wayPoint2LatLng = point;
    		numPostcodesGeocoded++;
    		runSecondPassIfReady();
    	}	    	    
   	} 

	// Waypoint 3   	
    function wayPoint3PostcodeCallback()
    {
    	point = postcodeSearchResultsToPoint(wayPoint3PostcodeSearch.results);            
    	if (point == null)
    	{ 
    		postCodeLookupError(); 
    	}
    	else
    	{    
    		wayPoint3LatLng = point;
    		numPostcodesGeocoded++;
    		runSecondPassIfReady();
    	}	    			    
   	} 
   	
   	// Waypoint 4
    function wayPoint4PostcodeCallback()
    {
    	point = postcodeSearchResultsToPoint(wayPoint4PostcodeSearch.results);            
    	if (point == null)
    	{ 
    		postCodeLookupError(); 
    	}
    	else
    	{    
    		wayPoint4LatLng = point;
    		numPostcodesGeocoded++;
    		runSecondPassIfReady();
    	}	    			    
   	} 
   	
   	// Waypoint 5
    function wayPoint5PostcodeCallback()
    {
    	point = postcodeSearchResultsToPoint(wayPoint5PostcodeSearch.results);            
    	if (point == null)
    	{ 
    		postCodeLookupError(); 
    	}
    	else
    	{    
    		wayPoint5LatLng = point;
    		numPostcodesGeocoded++;
    		runSecondPassIfReady();
    	}	    			    
   	}    	   	   	   	   	   	  
    
    // First pass at directions finds valid post codes and looks up the GLatLng
    // for them using the Google Ajax Local Search API. 
    // Eventually calls directionsSecondPass if sucessful or displays error message 
    // Note: Coded as two passes so we can easily disable one if needed
    function directionsFirstPass()
    {
    	resetVars();
    	
		var startLocation = $('JourneyEmissionsInputStartLocation').value;
		var endLocation = $('JourneyEmissionsInputEndLocation').value;
		
		// Do we have a starnd and endLocation as a minimum?
		if (startLocation == null || startLocation == "" ||
			endLocation == null || endLocation == "")
		{
			alert("Please enter a start and end location");
		}
		else
		{
			showAjaxWait(true);

			/* This is awful, but ... */
			/* First, count the postcodes we have */
			/* ------------------------------------------------------------------------------------*/
			if (containsValidPostcode(startLocation))
			{
				numPostcodesToGeocode++;
			}	

			if (containsValidPostcode(endLocation))
			{
				numPostcodesToGeocode++;
			}				
			
			// Check waypoints
			if($('JourneyEmissionsInputWayPoint1').value != null && $('JourneyEmissionsInputWayPoint1').value != "")
			{
				if (containsValidPostcode($('JourneyEmissionsInputWayPoint1').value))
				{
					numPostcodesToGeocode++;
				}		
			}
			
			if($('JourneyEmissionsInputWayPoint2').value != null && $('JourneyEmissionsInputWayPoint2').value != "")
			{
				if (containsValidPostcode($('JourneyEmissionsInputWayPoint2').value))
				{
					numPostcodesToGeocode++;
				}
			}
			
			if($('JourneyEmissionsInputWayPoint3').value != null && $('JourneyEmissionsInputWayPoint3').value != "")
			{
				if (containsValidPostcode($('JourneyEmissionsInputWayPoint3').value))
				{
					numPostcodesToGeocode++;
				}
			}
			
			if($('JourneyEmissionsInputWayPoint4').value != null && $('JourneyEmissionsInputWayPoint4').value != "")
			{
				if (containsValidPostcode($('JourneyEmissionsInputWayPoint4').value))
				{
					numPostcodesToGeocode++;
				}
			}
			
			if($('JourneyEmissionsInputWayPoint5').value != null && $('JourneyEmissionsInputWayPoint5').value != "")
			{
				if (containsValidPostcode($('JourneyEmissionsInputWayPoint5').value))
				{
					numPostcodesToGeocode++;
				}
			}	
			
			
			/* Then, try to geocode the postcodes if we need to*/
			/* ------------------------------------------------------------------------------------*/			
			if (numPostcodesToGeocode > 0)
			{

				if (containsValidPostcode(startLocation))
				{
					postcodeSearch(startLocation, startLocationPostcodeSearch);
					startLocationPostcode = startLocation;						
				}	
	
				if (containsValidPostcode(endLocation))
				{
					postcodeSearch(endLocation, endLocationPostcodeSearch);
					endLocationPostcode = endLocation;							
				}
				

				
				// Check waypoints
				if($('JourneyEmissionsInputWayPoint1').value != null && $('JourneyEmissionsInputWayPoint1').value != "")
				{
					if (containsValidPostcode($('JourneyEmissionsInputWayPoint1').value))
					{
						postcodeSearch($('JourneyEmissionsInputWayPoint1').value, wayPoint1PostcodeSearch);
						wayPointPostcodes.push($('JourneyEmissionsInputWayPoint1').value);
					}		
				}
				
				if($('JourneyEmissionsInputWayPoint2').value != null && $('JourneyEmissionsInputWayPoint2').value != "")
				{
					if (containsValidPostcode($('JourneyEmissionsInputWayPoint2').value))
					{
						postcodeSearch($('JourneyEmissionsInputWayPoint2').value, wayPoint2PostcodeSearch);	
						wayPointPostcodes.push($('JourneyEmissionsInputWayPoint2').value);												
					}
				}
				
				if($('JourneyEmissionsInputWayPoint3').value != null && $('JourneyEmissionsInputWayPoint3').value != "")
				{
					if (containsValidPostcode($('JourneyEmissionsInputWayPoint3').value))
					{
						postcodeSearch($('JourneyEmissionsInputWayPoint3').value, wayPoint3PostcodeSearch);
						wayPointPostcodes.push($('JourneyEmissionsInputWayPoint3').value);													
					}
				}
				
				if($('JourneyEmissionsInputWayPoint4').value != null && $('JourneyEmissionsInputWayPoint4').value != "")
				{
					if (containsValidPostcode($('JourneyEmissionsInputWayPoint4').value))
					{
						postcodeSearch($('JourneyEmissionsInputWayPoint4').value, wayPoint4PostcodeSearch);	
						wayPointPostcodes.push($('JourneyEmissionsInputWayPoint4').value);												
					}
				}
				
				if($('JourneyEmissionsInputWayPoint5').value != null && $('JourneyEmissionsInputWayPoint5').value != "")
				{
					if (containsValidPostcode($('JourneyEmissionsInputWayPoint5').value))
					{
						postcodeSearch($('JourneyEmissionsInputWayPoint5').value, wayPoint5PostcodeSearch);
						wayPointPostcodes.push($('JourneyEmissionsInputWayPoint5').value);													
					}
				}			
			
			}
			else
			{
				directionsSecondPass();
			}
			
						
		}    
    }
    
    // Second pass at directions uses the Google Directions service to find the 
    // distance of the route  
    function directionsSecondPass() 
    {

		var startLocation = $('JourneyEmissionsInputStartLocation').value;
		var endLocation = $('JourneyEmissionsInputEndLocation').value;
		
		// Do we have a starnd and endLocation as a minimum?
		if (startLocation == null || startLocation == "" ||
			endLocation == null || endLocation == "")
		{
			alert("Please enter a start and end location");
		}
		else
		{
			
			// Array of route locations
			var wayPoints = new Array();
			
			// Add the start location, we know it's not empty
			
			if (startLocationLatLng != null)
			{
				wayPoints.push(startLocationLatLng.lat() + ", " + startLocationLatLng.lng());			
			}
			else
			{			
				wayPoints.push(ukDestinationsHelper(startLocation));
			}
	
			// Add wayPoints as necessary
			if($('JourneyEmissionsInputWayPoint1').value != null && $('JourneyEmissionsInputWayPoint1').value != "")
			{
				if (wayPoint1LatLng != null)
				{
					wayPoints.push(wayPoint1LatLng.lat() + ", " + wayPoint1LatLng.lng());							
				}
				else
				{
					wayPoints.push(ukDestinationsHelper($('JourneyEmissionsInputWayPoint1').value));
				}		
			}
			
			if($('JourneyEmissionsInputWayPoint2').value != null && $('JourneyEmissionsInputWayPoint2').value != "")
			{
				if (wayPoint2LatLng != null)
				{
					wayPoints.push(wayPoint2LatLng.lat() + ", " + wayPoint2LatLng.lng());							
				}			
				else
				{
					wayPoints.push(ukDestinationsHelper($('JourneyEmissionsInputWayPoint2').value));
				}		
			}
			
			if($('JourneyEmissionsInputWayPoint3').value != null && $('JourneyEmissionsInputWayPoint3').value != "")
			{
				if (wayPoint3LatLng != null)
				{
					wayPoints.push(wayPoint3LatLng.lat() + ", " + wayPoint3LatLng.lng());							
				}			
				else
				{
					wayPoints.push(ukDestinationsHelper($('JourneyEmissionsInputWayPoint3').value));
				}		
			}
			
			if($('JourneyEmissionsInputWayPoint4').value != null && $('JourneyEmissionsInputWayPoint4').value != "")
			{
				if (wayPoint4LatLng != null)
				{
					wayPoints.push(wayPoint4LatLng.lat() + ", " + wayPoint4LatLng.lng());							
				}			
				else
				{
					wayPoints.push(ukDestinationsHelper($('JourneyEmissionsInputWayPoint4').value));
				}		
			}
			
			if($('JourneyEmissionsInputWayPoint5').value != null && $('JourneyEmissionsInputWayPoint5').value != "")
			{
				if (wayPoint5LatLng != null)
				{
					wayPoints.push(wayPoint5LatLng.lat() + ", " + wayPoint5LatLng.lng());							
				}			
				else
				{
					wayPoints.push(ukDestinationsHelper($('JourneyEmissionsInputWayPoint5').value));
				}		
			}				
	
			// Add end locatoin, we know it isn't empty
			if (endLocationLatLng != null)
			{
				wayPoints.push(endLocationLatLng.lat() + ", " + endLocationLatLng.lng());
			}
			else
			{
				wayPoints.push(ukDestinationsHelper(endLocation));			
			}
			// Load directions form way points
	    	gdir.loadFromWaypoints(wayPoints, { "locale": "en" });
    	}
    }
   

	// Handle errors that result from GDirections
    function handleErrors()
    {
		showAjaxWait(false);    
		$('error_message').style.display = "block";  
		  
		/*
	   if (gdir.getStatus().code == G_GEO_UNKNOWN_ADDRESS)
	     alert("No corresponding geographic location could be found for one of the specified addresses. This may be due to the fact that the address is relatively new, or it may be incorrect.\nError code: " + gdir.getStatus().code);
	   else if (gdir.getStatus().code == G_GEO_SERVER_ERROR)
	     alert("A geocoding or directions request could not be successfully processed, yet the exact reason for the failure is not known.\n Error code: " + gdir.getStatus().code);
	   
	   else if (gdir.getStatus().code == G_GEO_MISSING_QUERY)
	     alert("The HTTP q parameter was either missing or had no value. For geocoder requests, this means that an empty address was specified as input. For directions requests, this means that no query was specified in the input.\n Error code: " + gdir.getStatus().code);
		*/
		//   else if (gdir.getStatus().code == G_UNAVAILABLE_ADDRESS)  <--- Doc bug... this is either not defined, or Doc is wrong
		//     alert("The geocode for the given address or the route for the given directions query cannot be returned due to legal or contractual reasons.\n Error code: " + gdir.getStatus().code);
		/*	     
	   else if (gdir.getStatus().code == G_GEO_BAD_KEY)
	     alert("The given key is either invalid or does not match the domain for which it was given. \n Error code: " + gdir.getStatus().code);

	   else if (gdir.getStatus().code == G_GEO_BAD_REQUEST)
	     alert("A directions request could not be successfully parsed.\n Error code: " + gdir.getStatus().code);
	    
	   else alert("An unknown error occurred." + gdir.getStatus().code);
	   */
	   
	}

	// Updates the maps with directions
	function onGDirectionsLoad()
	{
		showAjaxWait(false);
    	resetDefaultMap();
    	
		// Distance comes back in m, need to convert to km
		var distanceM = gdir.getDistance().meters;
		var distanceKm = distanceM / 1000;
		distanceKm = distanceKm.toFixed(2);
		
		if (distanceM == 0)
		{

			clearFields();
			showErrorMessage();
			
		} 
		else
		{		
			var locations = new Array();
			
			// The number of locations that make up the route
			var numLocations = gdir.getNumGeocodes();
			
			var startLocation = gdir.getGeocode(0).address;
			locations.push(startLocation);			
	
			var wayPoint1 = "";
			var wayPoint2 = "";
			var wayPoint3 = "";
			var wayPoint4 = "";
			var wayPoint5 = "";
	
			if (numLocations > 2)
			{
				wayPoint1 = gdir.getGeocode(1).address;
				locations.push(wayPoint1);
				
				if (numLocations > 3)
				{
					wayPoint2 = gdir.getGeocode(2).address;
					locations.push(wayPoint2);
							
					if (numLocations > 4)
					{
						wayPoint3 = gdir.getGeocode(3).address;
						locations.push(wayPoint3);	
						
						if (numLocations > 5)
						{
							wayPoint4 = gdir.getGeocode(4).address;
							locations.push(wayPoint4);	
							
							if (numLocations > 6)
							{
								wayPoint5 = gdir.getGeocode(5).address;
								locations.push(wayPoint5);							
							}					
						}			
					}
				}	
			}
			
			var endLocation = gdir.getGeocode(numLocations-1).address;	
			locations.push(endLocation);	
			
			$("JourneyEmissionsInputDistance").value = distanceKm;
			
			if (startLocationPostcode != null)
			{
				$("JourneyEmissionsInputStartLocation").value = startLocationPostcode;			
			}
			else
			{
				$("JourneyEmissionsInputStartLocation").value = startLocation;			
			}
			
			if (endLocationPostcode != null)
			{
				$("JourneyEmissionsInputEndLocation").value = endLocationPostcode;			
			}
			else
			{
				$("JourneyEmissionsInputEndLocation").value = endLocation;			
			}
			
			
			if (wayPointPostcodes[0] != null)
			{
				$("JourneyEmissionsInputWayPoint1").value = wayPointPostcodes[0];			
			}
			else
			{			
				$("JourneyEmissionsInputWayPoint1").value = wayPoint1;
			}
			
			if (wayPointPostcodes[1] != null)
			{
				$("JourneyEmissionsInputWayPoint2").value = wayPointPostcodes[1];			
			}
			else
			{
				$("JourneyEmissionsInputWayPoint2").value = wayPoint2;
			}
			
			
			if (wayPointPostcodes[2] != null)
			{
				$("JourneyEmissionsInputWayPoint3").value = wayPointPostcodes[2];						
			}
			else
			{
				$("JourneyEmissionsInputWayPoint3").value = wayPoint3;			
			}
			
			if (wayPointPostcodes[3] != null)
			{
				$("JourneyEmissionsInputWayPoint4").value = wayPointPostcodes[3];						
			}
			else
			{
				$("JourneyEmissionsInputWayPoint4").value = wayPoint4;			
			}

			if (wayPointPostcodes[4] != null)
			{
				$("JourneyEmissionsInputWayPoint5").value = wayPointPostcodes[4];			
			}
			else
			{
				$("JourneyEmissionsInputWayPoint5").value = wayPoint5;
			}			
			
						
		
	
			renderJourneyOverview(locations, distanceKm);				
			viewJourneyOverview();	
		}		

		
	}
	
	// Shows an extra waypoint
	function showExtraWaypoint()
	{
		var maxWayPoints = 5;
		
		if (($('TravelModeCategoryId').options[$('TravelModeCategoryId').selectedIndex]).value != flyCategoryId)
		{		
			if (wayPointCount < maxWayPoints)
			{
				var wayPointDivName = 'wayPoint' + (wayPointCount+1) + 'Div';		
				$(wayPointDivName).style.display = "block";
				
				// Show the link to remove a waypoint
				$('remove_waypoint_link').style.display = "inline";	
											
				wayPointCount++;
				
				
				if (wayPointCount == maxWayPoints)
				{
					$('add_waypoint_link').style.display = "none";
				}
			}
		}
	}
	
	// Remove waypoint
	function removeWaypoint()
	{
		if (wayPointCount > 0)
		{
			// The waypoint to remove and clear
			var wayPointDivName = 'wayPoint' + (wayPointCount) + 'Div';
			
			var wayPointTextBoxId = "JourneyEmissionsInputWayPoint" + wayPointCount;
			$(wayPointTextBoxId).value = "";
			
			$(wayPointDivName).style.display = "none";
			
			wayPointCount--;
			
			// We've justed removed one, so they must be able to now add another
			$('add_waypoint_link').style.display = "inline";
			
			if (wayPointCount == 0)
			{
				$('remove_waypoint_link').style.display = "none";						
			}		
		}
	}	
	
	
	// Helps Google find uk destinations by suffixing 'uk' on the end of relevant queries
	function ukDestinationsHelper(destination)
	{
		if (destination != null && destination != "")
		{
			if (destination == "newcastle" || destination == "Newcastle")
			{
				destination = "Newcastle Upon Tyne";
			}
			destination += ", UK";
		}
		return destination;
	}
	