// Code for handling the Google Maps-enabled pages.
// - search page.
// - "pluri" page.

// Load all code for search page.
function InitSearchPage(){

	// Only run the following if we can load Google Maps...
	// and first check that the gmap script has loaded!
	// i.e. check that GBrowserIsCompatible and GMap2 are in scope.
	if ( (window.GBrowserIsCompatible) && (window.GMap2) && (GBrowserIsCompatible()) ){

		// Initialize the map.
		
		// Loading Gmap2 sometimes fails on IE - there's a lot of literature about it, 
		// (google for "'GMap2' is undefined").
		// The only solution seems to be to display some kind of message to the user to 
		// get them to hit F5.
		try {
			var map = new GMap2(document.getElementById("search_home_map_canvas"));
		} catch (e) {
			// No point going any further!
			// At some point I'll dig a bit deeper into this and decide if it's worth 
			// displaying a message for the end user.
			return true;
		}

		map.setCenter(new GLatLng( CountryData['latitude'], CountryData['longitude']), CountryData['zoom_level']);
        map.setUIToDefault();

        // keep an array of all the markers defined on the map. Logically, this info is (should) be in 
        // the map object, but I couldn't find how to access it...
        var markers = []
                       
		function AddMarkers(id){
			// Process table containing exact/fuzzy place matches; iterate over each row.
			// But exclude line that includes a 'th'.
			// And add markers to the map for each row.
			$(id).find("tr").not(":has(th)").each(function(i) {
				var t = $(this).find("td:first");
				var name = t.text();
				var postal_code = t.next().html();
				var l = $(this).find(".latitude");
				var latitude = l.html();
				// I don't have lat/long information for all localities in the database.
				// Skip to next element in this scenario.
				if( latitude == "" ){
					return true;
				}
				var longitude = l.next().html();
				var point = new GLatLng(latitude, longitude);
				var marker = new GMarker(point);
		    	var text = name+'<br />'+gettext('Postal code')+ ': <strong>'+postal_code+'</strong>'
				markers.push([marker, text]);
				// Whenever we click on the marker, we want town details to flash up.
				GEvent.addListener(marker, "click", function() {
					marker.openInfoWindowHtml(text);
				});
				map.addOverlay(marker);
				
				// Whenever we click on a magnifying icon, we want to highlight that marker on the map.
				$(this).find(".magnifier_img").click(function() {
			    	marker.openInfoWindowHtml(text);
			    });
			});
		}

		if( GotSearchResults ){
			// Read through the various results table, and use it to create markers on the map.
		
			AddMarkers("#PlaceExact");
			AddMarkers("#PlaceFuzzy");

			// If only one answer in the results, we zoom straight to it after loading the map.
			if( found_just_one_place ){
				// scroll down page to see the town on map (uses jQuery plugin).
				$.scrollTo( $("#search"), 1000);
				var direct_marker = markers[0][0];
				var direct_text = markers[0][1];
				direct_marker.openInfoWindowHtml(direct_text);
			};

		};

		// Google documents recommend unloading the widget at the end.
		$(document.body).unload(function() {
			if (GBrowserIsCompatible()) {
			GUnload();
			}
		});

	}

};

// Load all code for pluri page.
// NOTE: this only works if ExternalGoogleMaps = True.
function InitPluriPage(){
	
	// Set focus on the input box.
	$('#pluri_form input[type=text]')[0].focus();

	$("#pluri_error_box").css("visibility", "hidden" );
	
	// Only run the following if we can load Google Maps...
	// and first check that the gmap script has loaded!
	if ( (window.GBrowserIsCompatible) && (GBrowserIsCompatible()) ){

		// Initialize the map.

		// Loading Gmap2 sometimes fails on IE - there's a lot of literature about it, 
		// (google for "'GMap2' is undefined").
		// The only solution seems to be to display some kind of message to the user to 
		// get them to hit F5.
		// I'm trying to catch these errors and decide what to do with them.
		try {
			var map = new GMap2(document.getElementById("pluri_map_canvas"));
		} catch (e) {
			var msg = '(Ignore these errors for now - will count them in a few weeks time and decide if need to do something about them). Gmap2 load error ' + e.name + ' ' + e.message + ' ' + PlaceData['slug'];
			jQuery.post("/common/javascript_errors/", {msg: msg, uri: '', line: ''})
			// bomb out; later I will add a message to the user?
			return false;
		}

		map.setCenter(new GLatLng( PlaceData['latitude'], PlaceData['longitude']), 12);
        map.setUIToDefault();

		var geocoder = new GClientGeocoder();

		// Define user input as a global variable; it needs to be accessible from the addAddressToMap
		// callback function, and I can't think of a cleaner way to pass this information.
		var UserInput = '';

		// Display an error message above the input box.
		function ErrorMessage(msg) {
			var elem = $("#pluri_error_box");
			elem.html(msg);
			elem.css("visibility", "visible" );
		}

		function ShowMarker(data) {
			if ( 'info_window_text' in data ) {
				// We've got enough data to place a marker on the map.
				point = new GLatLng(data.coordinates[1],
									data.coordinates[0]);
				// Center the map on the street and zoom in.
				map.setCenter(point, 15);
				marker = new GMarker(point);
				map.addOverlay(marker);
				// And add an info window.
				marker.openInfoWindowHtml(data.info_window_text);
			}
			if ( 'error_message' in data ) {
				// Display an error message above the input box.
				ErrorMessage(data['error_message']);
			}
		}
		
		function DisplayAddress(place) {
			
			// Now the fun starts. The place objects returned by Google is a JSON object whose
			// structure changes slightly :-( according to the town.
			// Feed it back to the server which will strip it down, log it, and return the correct action
			// to perform in the browser.
			// By doing it on the server I can add stick to tried-and-tested unit test methods!
			jQuery.post("parse_gmaps/",
					{SearchText: UserInput,
					json_place: $.toJSON(place)},
					ShowMarker, // function to process data returned by server.
					"json"); // type of data returned by server.
			return true;
		}

		function addAddressToMap(response) {
			map.clearOverlays();
			if (!response || response.Status.code != 200) {
				// Google could not Geocode this address.
				// Send a slightly different message that will not get parsed - just logged.
				jQuery.post("parse_gmaps/",
						{SearchText: UserInput,
						cannot_geocode: 'true'},
						ShowMarker, // function to process data returned by server.
						"json"); // type of data returned by server.
						
			} else {
				// TODO: handle scenario where Google returns more than one Placemark.
				DisplayAddress(response.Placemark[0]);
			}
		}
		
		$("#pluri_form").submit(function() {
			// User has clicked on submit button, let's process what he has typed in
			// and display the address.

			// Scroll down page to bring page content into focus (uses jQuery plugin).
			// This may scroll the header/menu out of page, which is fine, I want the users
			// to see the input box/map... and also the adsense skyscraper!
			$.scrollTo( $("#main"), duration=1000, {axis:'y'});

			// If previously the user typed in a bad address, the error box will be present.
			// Remove it.
			$("#pluri_error_box").css("visibility", "hidden" );
		
			// Grab contents of input box.
			UserInput = $('#pluri_form input[type=text]')[0].value;

			// Cleanup the user input
			UserInput = UserInput.toLowerCase().replace(/^\s+|\s+$/g, '');

			if( UserInput == "" ){
				ErrorMessage(gettext('Please type something into the input box below.'));
				document.forms[0][0].focus();
				return false;
			}

			if( UserInput == PlaceData['name_lowercase'] ) {
				ErrorMessage(gettext('Please enter a street number and name - the name of the city is not enough on its own.'));
				document.forms[0][0].focus();
				return false;
			}

			if( !(isNaN(UserInput) ) ) {
					ErrorMessage(gettext('Please enter a street number and name - not a postcode.'));
					document.forms[0][0].focus();
					return false;
			}

			if( UserInput == "10, downing street" ) {
				ErrorMessage(gettext('That was just an example!<br />Please enter a street number and name.'));
				document.forms[0][0].focus();
				return false;
			}

			// Some people type in the name of the city at the start or at the end of the search string - redundant,
			// and it confuses the Geocoder.
			UserInput = UserInput.replace( RegExp("^"+PlaceData['name_lowercase']) , "")
			UserInput = UserInput.replace( RegExp(PlaceData['name_lowercase']+"$") , "")
			
			// Use Google Maps to 'Geocode' address, that is, convert the address into 
			// lat/long coordinates.
			// This is not the most basic function to Geocode an address; however, this one
			// returns full address information... including the postal code!
			var address = UserInput + ', ' + PlaceData['name'] + ', ' + PlaceData['admin2'] + ', ' + PlaceData['country'];
			geocoder.getLocations(address, addAddressToMap);

			return false; // Prevent the default form action, as defined in the HTML.
		});
		
		// Google documents recommend unloading the widget at the end.
		$(document.body).unload(function() {
			if (GBrowserIsCompatible()) {
				GUnload();
			}
		});

	}

};


