// Google Maps

Number.prototype.toRad = function() {  // convert degrees to radians
  return this * Math.PI / 180;
}

var centreSearch;
var multiSearch;
google.load("maps", "2");
google.load("search", "1");
google.setOnLoadCallback(googleLoaded);

/**
 *	googleLoaded
 *	------------
 *	Called after the google AJAX API has loaded the
 *	required sections
 */
function googleLoaded()
{
	google.search.LocalSearch.prototype.uuid = 0;
	
	$A(document.getElementsByTagName("script")).findAll( function(s) {
      return (s.src && s.src.match(/maps_search\.js(\?.*)?$/))
    }).each( function(s) {
      var includes = unescape(s.src).match(/\?.*postcode=([a-zA-Z0-9 ]*)/);
      if (includes.length > 1) {
		
		centreSearch = new google.search.LocalSearch();
		centreSearch.setNoHtmlGeneration();
		centreSearch.setSearchCompleteCallback(searchHelper, searchHelper.centreComplete);
		centreSearch.execute(includes[1]);
	  }
    });
}

/**
 *	searchHelper
 *	------------
 *	An object for handling the results of the search,
 *	used in looking up a map postcode.
 */
var searchHelper = {
	
	centreMarker: {},
	extendedMarkers: [],
	customIcon: null,
	closeCount: 4,
	currentClose: [],
	baseLatLng: null,
	map: {},
	lastSearch: '',
	initialised: false,
	directions: null,
	
	init: function(lat,lng) {
		this.map = new google.maps.Map2($("map"));
		this.map.setCenter(new google.maps.LatLng(lat, lng), 13);
		
		this.centreMarker = new GMarker(new GLatLng(lat, lng));
		this.map.addOverlay(this.centreMarker);
		
		this.applyBorder();
		
		this.customIcon = new GIcon();
		this.customIcon.image = '/local/images/google_marker.png';
		this.customIcon.iconSize = new GSize(16,28);
		this.customIcon.iconAnchor = new GPoint(8,28);
		this.customIcon.infoWindowAnchor = new GPoint(8,0);
		
		this.placeLocations();
		
		//Delay needed for some browsers, hope 1/2second is enough
		if (get_search) setTimeout(function(){centreSearch.execute(get_search);},500);
		
		this.initialised = true;
	},
	
	searchLocations: function() {
		if (!$('search_area')) return;
		
		lastSearch = $('search_area').value;
		
		if (!isValidPostcode(lastSearch,true)) {
		  return;
		}
		
		centreSearch.execute(lastSearch);
	},
	
	centreComplete: function() {
		if (GBrowserIsCompatible()) {
			for (var i = 0; i < centreSearch.results.length; i++) {
				
				var result = centreSearch.results[i];
				var wasInit = this.initialised;
				
				if (!this.initialised)
					this.init(result.lat, result.lng);
				
				this.centreMarker.setLatLng(new GLatLng(result.lat, result.lng));
				
				if (wasInit) {
					this.baseLatLng = new GLatLng(result.lat, result.lng);
					this.calculateDistances();
				}
				
				return;
      		}
		}	
	},
	
	displayDistances: function() {
		//alert("Called display distances");
		
		this.currentClose = [];
		
		for (var i=0; i<this.extendedMarkers.length; i++) {
			//alert("Checking marker "+i);
			
			this.extendedMarkers[i].marker.hide();
			var index = this.getSuggestedIndex(this.extendedMarkers[i].distance);
			if (index == -1) continue;
			
			this.currentClose[index] = this.extendedMarkers[i];
		}
		
		for(var k=0; k<this.currentClose.length; k++) {
			this.currentClose[k].marker.show();	
		}
		
		this.moveScope();
		this.showDivs();
	},
	
	goto: function(postcode) {
		for (var i=0; i<this.extendedMarkers.length; i++) {
			if (this.extendedMarkers[i].postcode == postcode) {
				this.map.setCenter(this.extendedMarkers[i].marker.getLatLng());
				this.map.setZoom(13);
				return;
			}
		}
	},
	
	showDivs: function() {
		for (var i=0; i<locations.length; i++) {
			
			var found = false;
			
			if (!$('office_'+i)) continue;
			
			$('office_'+i).style.display = 'none';
			
			for (var k=0; k<this.extendedMarkers.length; k++) {
				if (locations[i].postcode == this.extendedMarkers[k].postcode){
					found = true;
					break;
				}
			}
			
			if (found) {
				var pc = this.extendedMarkers[k].postcode;
				var hidden = this.extendedMarkers[k].marker.isHidden();
			
				var disSpan = $('office_'+i).getElementsByClassName('distance');
				disSpan[0].innerHTML = '(' + this.extendedMarkers[k].distance.toFixed(2) + 'km)';
				
				$('office_'+i).style.display = hidden ? 'none' : 'block';
			}
		}
	},
	
	moveScope: function() {
		//alert ("Called current scope with currentClose length = "+this.currentClose.length);
		
		if (this.currentClose.length < 1) return;
		
		var bounds = new GLatLngBounds(this.centreMarker.getLatLng(),this.centreMarker.getLatLng());
		for (var i=0; i<this.currentClose.length; i++) {
			bounds.extend(this.currentClose[i].marker.getLatLng());	
		}
		this.map.setCenter(bounds.getCenter());
		this.map.setZoom(this.map.getBoundsZoomLevel(bounds));
	},
	
	getSuggestedIndex: function(distance) {
		if (this.currentClose.length < this.closeCount) 
			return this.currentClose.length;
		
		var currentHighVal = 0;
		var currentHighIndex = 0;
		
		for (var i=0; i<this.currentClose.length; i++) {
			if (this.currentClose[i].distance > currentHighVal) {
				currentHighIndex = i;
				currentHighVal = this.currentClose[i].distance;
			}
		}
		
		if (currentHighVal > distance)
			return currentHighIndex;
		
		return -1;
	},
	
	calculateDistances: function() {
		for (var i=0; i<this.extendedMarkers.length; i++) {
			
			var lat1 = this.baseLatLng.lat();
			var lon1 = this.baseLatLng.lng();
			var lat2 = this.extendedMarkers[i].marker.getLatLng().lat();
			var lon2 = this.extendedMarkers[i].marker.getLatLng().lng();
			
			var R = 6371; // km
			var dLat = (lat2-lat1).toRad();
			var dLon = (lon2-lon1).toRad(); 
			var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
					Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) * 
					Math.sin(dLon/2) * Math.sin(dLon/2); 
			var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
			var d = R * c;
			
			this.extendedMarkers[i].distance = d;
		}
		this.displayDistances();
	},
	
	multiComplete: function(uuid) {
		for (var i = 0; i < multiSearch.results.length; i++) {
			
			var result = multiSearch.results[i];
			var postcode = (result.url.substring(result.url.indexOf("q=")+2)).replace("+"," ");
			
			if (this.centreMarker.getLatLng().lat() == result.lat && this.centreMarker.getLatLng().lng() == result.lng) {
				return;
			}
			
			var newMark = new GMarker(new GLatLng(result.lat, result.lng),{icon: this.customIcon, title: postcode});
			this.extendedMarkers.push({marker:newMark,distance:10000,lastQuery:'',postcode:postcode});
			this.map.addOverlay(newMark);
			
			return;
		}
	},
	
	placeLocations: function() {
		multiSearch = new google.search.LocalSearch();
		multiSearch.setNoHtmlGeneration();
		multiSearch.setSearchCompleteCallback(this, this.multiComplete);
		
		for (var i=0; i<locations.length; i++) {
			if (locations[i].postcode) {
				var uuid = locations[i].uuid;
				multiSearch.execute(locations[i].postcode);	
			}
		}
	},
	 
	applyBorder: function() {
		if ($('map')) $('map').style.border = '1px solid #c3c8cd';	
	}
	
}