// RedAngusFinder, Copyright (c) 2008 Eternity Technologies Pty Limited
// Developed for exclusive use by De Bortoli Wines Pty Limited
//
// Written by Devraj Mukherjee <devraj@etk.com.au>
// Based on original concept code written by Brad McLain
//
// Uses Google maps library, please refer to attached documentation

// Define the namespace and see what we have to do to start with
function RedAngusFinder() {
	// Load Google maps
	this.initGoogleMap();
	// Bind all controls in HTML
	this.bindObservers();
	// Fire off the first event to populate the list boxes	
	google.maps.DownloadUrl("restserver.php?action=getcountrylist", this.populateCountries);
	
	// These constants keep track of what kind of search we executed
	RedAngusFinder._RADIUS_SEARCH				= "0";
	RedAngusFinder._POSTCODE_SEARCH				= "1";
	RedAngusFinder._NEARME_SEARCH				= "2";
	RedAngusFinder._REDIRECTED_RADIUS_SEARCH	= "3";
	
	// No search type to start with
	RedAngusFinder.lastSearchType = null;
	
	// Check the postcode option in the checkbox
	var radioPostCode = document.getElementById("radioPostCode")
	radioPostCode.checked = true;
	google.maps.Event.trigger(radioPostCode, "change");
	
	// Finally lets ask the map to get all markers for Australia, this may take a while
	google.maps.DownloadUrl("restserver.php?action=getmarkers&state=All&city=All", RedAngusFinder.populateMapMakers);
}

// If you see funcitons that are not assigned to the prototype then its because
// they are accessed by XmlHttpRequest handlers

// Common method to populate drop down boxes from Ajax response
RedAngusFinder.populateDropDownList = function(dropdownList, valueArray, selectedValue) {
	dropdownList.options.length = 0;
	for(index = 0; index < valueArray.length; index++) {	
		var aListOption = new Option(valueArray[index], valueArray[index])
		// See if this the selected value
		if(valueArray[index] == selectedValue)
			aListOption.selected = true;
		// Add it to the drop down list
		dropdownList[index] = aListOption;
	}
}

// Returns a custom GIcon object with Angus pointer
RedAngusFinder.getAngusMarker = function() {
	var angusPointerIcon = new google.maps.Icon();
	angusPointerIcon.image = "images/marker/anguspointer.png";
	angusPointerIcon.iconSize = new google.maps.Size(30, 31);
	angusPointerIcon.iconAnchor = new google.maps.Point (15,31);
	angusPointerIcon.infoWindowAnchor = new google.maps.Point(15,1);
	return angusPointerIcon;
}

RedAngusFinder.onNoFlashForStreetView = function(errorCode) {
    if (errorCode == google.maps.FLASH_UNAVAILABLE) {
      alert("Street view requires Adobe Flash installed on your computer");
      return;
    }	
}

RedAngusFinder.renderAddressWindowTab = function(locationInfo, showStreetView) {
	var addressHTML = "<h3>" + locationInfo.name + "</h3>";
	addressHTML += "<p>" + locationInfo.address + "</p>";
	addressHTML += "<p>" + locationInfo.city + " (" + locationInfo.state + ") " + locationInfo.postal + "</p>";
	// Dont display phone number if not available
	if(locationInfo.phone != "N/A")
		addressHTML += "<p>" + "Phone " + locationInfo.phone + "</p>";
	
	// Add a layer that we use to display streetview
	if(showStreetView == "yes")
	{
		addressHTML += "<div class=\"panoramaView\" id=\"StreetViewLayer\">";
		addressHTML += "</div>";
	}
	return addressHTML;
}

// Makes a new marker for the map
RedAngusFinder.createNewMarker = function(point, angusPointer, locationInfo, showStreetView) {
	// Make a new marker that we are going to add to the map
	var marker = new google.maps.Marker(point, angusPointer);
	// Handler to show the HTML window
	google.maps.Event.addListener(marker, "click", function() {
		marker.openInfoWindowHtml(RedAngusFinder.renderAddressWindowTab(locationInfo, showStreetView));
		
		if(showStreetView == "yes") {
			var myPOV = { yaw:parseFloat(locationInfo.pov) };
			var panoramaOptions = { latlng:point, pov:myPOV };
			var panorama = new google.maps.StreetviewPanorama(document.getElementById("StreetViewLayer"), panoramaOptions);
			google.maps.Event.addListener(panorama, "error", RedAngusFinder.onNoFlashForStreetView);
		}
			
	});
	return marker;	
}

// Validate if a string	 is numeric 
RedAngusFinder.prototype.isValidNumber = function(aNumber) {
	var RegExp = /^(0|[1-9][0-9]*)$/;
	var result = aNumber.match(RegExp);
	return result;
}

// Google map start status
RedAngusFinder.prototype.initGoogleMap = function() {

	// Please take note that the map object is available on the RedAngusFinder 
	// namespace so its accessible by the callbacks
	RedAngusFinder.map = new google.maps.Map2(document.getElementById("map"));

	//Adding Map Types
	RedAngusFinder.map.addMapType(G_NORMAL_MAP);
	RedAngusFinder.map.addMapType(G_SATELLITE_MAP);
	RedAngusFinder.map.addMapType(G_HYBRID_MAP);
	RedAngusFinder.map.addMapType(G_PHYSICAL_MAP);

	//Set default map centre
	RedAngusFinder.map.setCenter(new google.maps.LatLng(-34.2734, 146.1382), 16);

	//Add map controls
	RedAngusFinder.map.addControl(new google.maps.LargeMapControl());
	RedAngusFinder.map.addControl(new google.maps.MapTypeControl());

}

// Add observers to buttons and checkboxes
RedAngusFinder.prototype.bindObservers = function() {
	
	// Hide or show the various divs
	google.maps.Event.bindDom(document.getElementById("radioSuburb"), "click", this, function(){
		document.getElementById("suburbSearchBox").style.display = "block";
		document.getElementById("postcodeSearchBox").style.display = "none";
		document.getElementById("radiusSearchBox").style.display = "none";
	});
	google.maps.Event.bindDom(document.getElementById("radioRadius"), "click", this, function(){
		document.getElementById("suburbSearchBox").style.display = "none";
		document.getElementById("postcodeSearchBox").style.display = "none";
		document.getElementById("radiusSearchBox").style.display = "block";
	});
	google.maps.Event.bindDom(document.getElementById("radioPostCode"), "click", this, function(){
		document.getElementById("suburbSearchBox").style.display = "none";
		document.getElementById("postcodeSearchBox").style.display = "block";
		document.getElementById("radiusSearchBox").style.display = "none";
	});

	// Register buttons with the event handler
	google.maps.Event.bindDom(document.getElementById("buttonSearchByRadius"), "click", this, this.onFindByRadius);
	google.maps.Event.bindDom(document.getElementById("buttonSearchByPostCode"), "click", this, this.onFindByPostCode);
	google.maps.Event.bindDom(document.getElementById("buttonSearchBySuburb"), "click", this, this.onFindBySuburb);
	
	// Register drop downs with the event handler
	google.maps.Event.bindDom(document.getElementById("dropdownCountries"), "change", this, this.onCountryListChanged);
	google.maps.Event.bindDom(document.getElementById("dropdownStates"), "change", this, this.onStateListChanged);
		
}

// GeoCode search event handler 
RedAngusFinder.onGeoCodeFound = function(response) {

	// If the response is not 200 then something went wrong
	if(response.Status.code != 200) {
		alert("We couldn't find that address on the map!");
		return;
	}
		
	// Lets get a place mark and display some markers
	place = response.Placemark[0];
	var localityName = "UNKNOWN";
	var lat = place.Point.coordinates[1];
	var lon = place.Point.coordinates[0];
	
	var radius = 20;
	if(RedAngusFinder.lastSearchType == RedAngusFinder._RADIUS_SEARCH) {
		radius = document.getElementById("textboxRadius").value;
		localityName = place.AddressDetails.Country.AdministrativeArea.Locality.LocalityName;
	}

	var restCallString = "restserver.php?action=getmarkers&lat=" + lat + "&lon=" + lon + "&distance=" + radius + "&city=" + localityName;
	google.maps.DownloadUrl(restCallString, RedAngusFinder.populateMapMakers);
}

// When the Country List changes this is what happens
RedAngusFinder.prototype.onCountryListChanged = function() {
	var countryName = document.getElementById("dropdownCountries").value;
	var postCode = document.getElementById("textboxPostCode").value;
	var restUrl = "restserver.php?action=getstatelist&country=" + countryName;
	
	// Add the postcode var if required
	if(this.isValidNumber(postCode))
		restUrl = restUrl + "&postcode=" + postCode;

	google.maps.DownloadUrl(restUrl, this.populateStates);	
}

// OnStateListChanged we repopulate the values of cities
RedAngusFinder.prototype.onStateListChanged = function() {
	var stateName = document.getElementById("dropdownStates").value;
	var postCode = document.getElementById("textboxPostCode").value;
	var restUrl = "restserver.php?action=getcitylist&state=" + stateName;
	
	// Add the postcode var if required
	if(this.isValidNumber(postCode))
		restUrl = restUrl + "&postcode=" + postCode;
	
	google.maps.DownloadUrl(restUrl, this.populateCities);	
}

// Button event handlers
RedAngusFinder.prototype.onFindByRadius = function() {	
	RedAngusFinder.lastSearchType = RedAngusFinder._RADIUS_SEARCH;
	var radius = document.getElementById("textboxRadius").value;
	var customerAddress = document.getElementById("textboxAddress").value;
	if(!this.isValidNumber(radius)) {
		alert("Please enter a valid distance in kilometers");
		document.getElementById("textboxRadius").value = "";
		return;
	}	
	// Customer must enter an address
	if(customerAddress.length == 0) {
		alert("Please enter a valid address for us to perform the search");
		return
	}
	
	var geocoder = new google.maps.ClientGeocoder();
	geocoder.getLocations(customerAddress, RedAngusFinder.onGeoCodeFound);
}

// When the Find button is clicked this is what happens
RedAngusFinder.prototype.onFindBySuburb = function() {
	RedAngusFinder.lastSearchType = RedAngusFinder._SUBURB_SEARCH;
	var stateName = document.getElementById("dropdownStates").value;
	var cityName = document.getElementById("dropdownCities").value;
	google.maps.DownloadUrl("restserver.php?action=getmarkers&state=" + stateName + "&city=" + cityName, RedAngusFinder.populateMapMakers);
}

// If the user wants to find by suburb
RedAngusFinder.prototype.onFindByPostCode = function() {
	RedAngusFinder.lastSearchType = RedAngusFinder._POSTCODE_SEARCH;
	var postCodeValue = document.getElementById("textboxPostCode").value;
	if(!this.isValidNumber(postCodeValue)) {
		alert("Please enter a valid postcode");
		document.getElementById("textboxPostCode").value = "";
		return;
	}
		
	var restfulUrl = "restserver.php?action=getmarkers&postcode=" + postCodeValue;
	google.maps.DownloadUrl(restfulUrl, RedAngusFinder.populateMapMakers);

	// Trigger a drop down countries change event, this will cause the state and city to update
	// with the selected value of the current city by post code
	var dropdownCountries = document.getElementById("dropdownCountries");
	google.maps.Event.trigger(dropdownCountries, "change");	
}

// Populate markers for map search
RedAngusFinder.populateMapMakers = function(responseObject) {
	var jsonData = eval('(' + responseObject + ')');
	var angusPointer = RedAngusFinder.getAngusMarker();
	var locationBounds = new google.maps.LatLngBounds();
	
	// If it's postcode search and no results try again as a radius search
	if(jsonData.markers.length == 0 && RedAngusFinder.lastSearchType == RedAngusFinder._POSTCODE_SEARCH) {
		RedAngusFinder.lastSearchType = RedAngusFinder._REDIRECTED_RADIUS_SEARCH;
		var geocoder = new google.maps.ClientGeocoder();
		geocoder.getLocations(document.getElementById("textboxPostCode").value + ", Australia", RedAngusFinder.onGeoCodeFound);
		return;
	}	
	
	if(jsonData.markers.length == 0) {
		alert("We couldn't find any stockers near your desired area!")
		return;
	}

	RedAngusFinder.map.clearOverlays();
	RedAngusFinder.markerManager = new google.maps.MarkerManager(RedAngusFinder.map, { borderPadding: 50, maxZoom: 15, trackMarkers: true });

	// Add each maker recd from the REST service
	for (var index = 0; index < jsonData.markers.length; index++) {
		var point = new google.maps.LatLng(jsonData.markers[index].lat, jsonData.markers[index].lon);
		locationBounds.extend(point);
		var locationInfo = jsonData.markers[index].info;

		var aMarker = RedAngusFinder.createNewMarker(point, angusPointer, locationInfo, jsonData.markers[index].showStreetView);
		RedAngusFinder.markerManager.addMarkers(aMarker, 0, 17);

		RedAngusFinder.map.addOverlay(aMarker);
	}
	
	RedAngusFinder.markerManager.refresh();
	
	// Figured out the acceptable zoom level based on the markers
	var acceptableZoomLevel = RedAngusFinder.map.getBoundsZoomLevel(locationBounds);
	// Pan to the part that has markers and set the center
	RedAngusFinder.map.setCenter(locationBounds.getCenter(), acceptableZoomLevel);
	RedAngusFinder.map.panTo(locationBounds.getCenter());
}

// Populates countries using a RESTful call
RedAngusFinder.prototype.populateCountries = function(responseObject) {
	var jsonData = eval('(' + responseObject + ')');
	var dropdownCountries = document.getElementById("dropdownCountries");
	RedAngusFinder.populateDropDownList(dropdownCountries, jsonData.country);
	google.maps.Event.trigger(dropdownCountries, "change");	
}

// Populates states from JSON data
RedAngusFinder.prototype.populateStates = function(responseObject) {
	var jsonData = eval('(' + responseObject + ')');
	var dropdownStates = document.getElementById("dropdownStates");
	RedAngusFinder.populateDropDownList(dropdownStates, jsonData.state, jsonData.selectedValue);
	google.maps.Event.trigger(dropdownStates, "change");
}

// Populates Cities from JSON data
RedAngusFinder.prototype.populateCities = function(responseObject) {
	var jsonData = eval('(' + responseObject + ')');
	var dropdownCities = document.getElementById("dropdownCities");
	RedAngusFinder.populateDropDownList(dropdownCities, jsonData.city, jsonData.selectedValue);
	google.maps.Event.trigger(dropdownCities, "change");
}

// Use Google.load to get the new Maps2 object and fire the init method
google.load("maps", "2.x");
google.setOnLoadCallback(function(){
	var application = new RedAngusFinder();
});		

