// 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();
				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( $("#scroll_target"), 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.
function InitPluriPage(){
	
	// Set focus on the input box.
	$('#pluri_form input[type=text]')[0].focus(); 
	
	// 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 = '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("display", "block" );
		}

		function DisplayAddress(place) {
			// Google has found the address, let's display it.
			point = new GLatLng(place.Point.coordinates[1],
								place.Point.coordinates[0]);
								
			// Center the map on the street and zoom in.
			map.setCenter(point, 15);
											
			marker = new GMarker(point);
			map.addOverlay(marker);
			//console.debug(place);
			
			var SearchStatus = 2; // no match
			
			// Now the fun starts. The place objects returned by Google is a JSON object whose
			// structure changes slightly :-( according to the town.
			// JSON objects are basically embedded hash arrays, so I can test if a specific keyword
			// is present - if yes, them I know how to handle the object for that town.
			try {
				if ( 'AddressLine' in place.AddressDetails ) {
					// Fairly generic response from Google Maps, corresponding to oddball objects like
					// train stations. These SEEM to have postal codes in them.
					marker.openInfoWindowHtml('<strong>' + place.address + '</strong>');
					// Give this a custom search status so that I can track it.
					SearchStatus = 6; // uncertain answer (type 2).
				}
				else if ( 'AddressLine' in place.AddressDetails.Country ) {
					// Fairly generic response from Google Maps.
					// These don't seem to have postal codes.
					marker.openInfoWindowHtml('<strong>' + place.address + '</strong><br />'+
					gettext('Please try to be more precise.'));
					// Give this a custom search status so that I can track it.
					SearchStatus = 7; // uncertain answer (type 3).
				}
				else if ( 'Thoroughfare' in place.AddressDetails.Country ) {
					// Another generic response from Google Maps.
					// These don't seem to have postal codes.
					marker.openInfoWindowHtml('<strong>' + place.address + '</strong><br />'+
					gettext('Please try to be more precise.'));
					var msg = gettext("I'm sorry, but the information is not precise enough to find a postal code. Try entering a house number and a street name.")
					ErrorMessage(msg);
					// Give this a custom search status so that I can track it.
					SearchStatus = 8; // uncertain answer (type 4).
				}
				else if ( 'Locality' in place.AddressDetails.Country.AdministrativeArea ) {
					var PostalCode = place.AddressDetails.Country.AdministrativeArea.Locality.DependentLocality.PostalCode.PostalCodeNumber;
//					var Locality = place.AddressDetails.Country.AdministrativeArea.Locality.LocalityName;
//					marker.openInfoWindowHtml('<strong>' + UserInput + '</strong> '+gettext('in')+' ' 
//					+ Locality + '<br>'+gettext('Postal code')+': <strong>' + PostalCode + '</strong>');
					marker.openInfoWindowHtml(place.address + '<br>'+gettext('Postal code')+': <strong>' + PostalCode + '</strong>');
					SearchStatus = 1; // Success
				}
				else if ( 'SubAdministrativeArea' in place.AddressDetails.Country.AdministrativeArea ) {
					var SubAdministrativeArea = place.AddressDetails.Country.AdministrativeArea.SubAdministrativeArea;
					if ( !( 'Locality' in SubAdministrativeArea ) ) {
						var msg = gettext("I'm sorry, but the information is not precise enough to find a postal code. Try entering a house number and a street name.")
						ErrorMessage(msg);
						marker.openInfoWindowHtml('<strong>' + UserInput + '</strong>');
						SearchStatus = 4; // uncertain answer.
					}
					else if ( !( 'PostalCode' in SubAdministrativeArea.Locality ) ) {
						// User has not provided enough information (for example, only a thoroughfare name).
						// Google can geocode it, but not provide a postal code.
						var msg = gettext("I'm sorry, but the information is not precise enough to find a postal code. Try entering a house number and a street name.")
						ErrorMessage(msg);
						marker.openInfoWindowHtml('<strong>' + UserInput + '</strong>');
						SearchStatus = 4; // uncertain answer.
					}
					else {
						var PostalCode = SubAdministrativeArea.Locality.PostalCode.PostalCodeNumber;
//						var Locality = SubAdministrativeArea.Locality.LocalityName;
//						var SubAdministrativeAreaName = SubAdministrativeArea.SubAdministrativeAreaName;
//						if ( Locality == SubAdministrativeAreaName ) {
//							// The SubAdministrativeAreaName is (roughly) the Admin2.
//							// In some cases, like Paris, it's the same as the name of the city,
//							// so not much point in displaying it.
//							var loc = Locality;
//						} else {
//							var loc = Locality + ', ' + SubAdministrativeArea.SubAdministrativeAreaName;
//						}
//						marker.openInfoWindowHtml('<strong>' + UserInput + '</strong> '+gettext('in')+' ' 
//						+ loc + '<br>'+gettext('Postal code')+': <strong>' + PostalCode + '</strong>');
						marker.openInfoWindowHtml(place.address + '<br>'+gettext('Postal code')+': <strong>' + PostalCode + '</strong>');
						SearchStatus = 1; // Success
					}
				}
				else {
					jQuery.post("/shared/log_pluri_searches/", {SearchText: UserInput,
															status: 5,
															slug: PlaceData['slug'],
															country_code: PlaceData['country_code']
															});
					var msg = gettext("I'm sorry, but there's been a technical problem. The webmaster has been informed and will be fixing it as soon as possible.");
					ErrorMessage(msg);
					return;
				}
	
				// Log the search with the server.
				jQuery.post("/shared/log_pluri_searches/", {SearchText: UserInput,
															status: SearchStatus,
															slug: PlaceData['slug'],
															country_code: PlaceData['country_code']
															});
			} catch (e) {
				// Note the $.dump; this is a jQuery plugin that dumps the contents of any object (here, the GoogleMaps json object).
				var msg = 'PLACE BUG ' + e.name + ' ' + e.message + ' ' + PlaceData['slug'] + ' ' + UserInput + ' ' + $.dump(place);
				jQuery.post("/common/javascript_errors/", {msg: msg, uri: '', line: ''})
			}
		}


		function addAddressToMap(response) {
			map.clearOverlays();
			if (!response || response.Status.code != 200) {
				// Google could not Geocode this address.
				var msg = gettext("I'm sorry, but I cannot find an address at")+": "+ UserInput + '<br />'+gettext('Please check and try again.');
				ErrorMessage(msg);
				// Log the search with the server.
				jQuery.post("/shared/log_pluri_searches/", {SearchText: UserInput,
														status: 2, // no match
														slug: PlaceData['slug'],
														country_code: PlaceData['country_code']
														});
						
			} else {
				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.

			// If previously the user typed in a bad address, the error box will be present.
			// Remove it.
			$("#pluri_error_box").css("display", "none" );
		
			// 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;
			}

			// 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();
			}
		});

	}

};

