var map           = false;
var geocoder      = false;
var gdir          = false;
var selectedStore = false;
var resultLat     = false;
var resultLng     = false;
var address       = false;
var myaddress     = false;
var reasons		  = [];
var storeIcon = new GIcon();
storeIcon.image = "/images/store-icon.png";
storeIcon.iconSize = new GSize(32, 32);
storeIcon.iconAnchor = new GPoint(16, 13);							
storeIcon.infoWindowAnchor = new GPoint(16, 4);

// attach the functionality to the form submission
window.addEvent('domready', function() {
	var myGLS  = new GoogleLocalSearch();
	$('mapForm').addEvent('submit', function(e){
		e.preventDefault();
		address = $('addressInput').get('value');
		if(address){
			var my_geocode = myGLS.addressToGeocode(address, function(result){
				if(result){
					resultLat = result.lat;
					resultLng = result.lng;
					myaddress = new GLatLng(resultLat,resultLng);
					searchLocations();					
				}else{
					alert("Sorry, we weren't able to find that address.");
				}
			});
		}
	});		
});

GoogleLocalSearch = new Class({
	search:false,
	initialize: function(){},
	addressToGeocode:function(search, callbackFunc){
		if(!this.search) {
			this.search = new GlocalSearch();
		}
		localSearch = this.search;
		localSearch.setSearchCompleteCallback(null, function(){
			if(localSearch.results[0]) {
				callbackFunc(localSearch.results[0]);
			}else{
				callbackFunc(false);
			}
		});
		localSearch.execute(search);
	}
});

function load(){
	if (GBrowserIsCompatible()) {
		geocoder = new GClientGeocoder();
		map = new GMap2(document.getElementById('map'));
		map.addControl(new GSmallMapControl());
		map.addControl(new GMapTypeControl());
		map.setCenter(new GLatLng(defaultlat, defaultlng), defaultzoom);		
		
		// ====== Array for decoding the failure codes ======
		reasons[G_GEO_SUCCESS]            = "Success";
		reasons[G_GEO_MISSING_ADDRESS]    = "Missing Address: The address was either missing or had no value.";
		reasons[G_GEO_UNKNOWN_ADDRESS]    = "Unknown Address:  No corresponding geographic location could be found for the specified address.";
		reasons[G_GEO_UNAVAILABLE_ADDRESS]= "Unavailable Address:  The geocode for the given address cannot be returned due to legal or contractual reasons.";
		reasons[G_GEO_BAD_KEY]            = "Bad Key: The API key is either invalid or does not match the domain for which it was given";
		reasons[G_GEO_TOO_MANY_QUERIES]   = "Too Many Queries: The daily geocoding quota for this site has been exceeded.";
		reasons[G_GEO_SERVER_ERROR]       = "Server error: The geocoding request could not be successfully processed.";
	}
}

function searchLocations(){
	geocoder.getLocations(address, function(result){
		map.clearOverlays(); 
		if(result.Status.code == G_GEO_SUCCESS){
			if(result.Placemark.length > 1) { 
				places = "";
			    for(var i=0; i<result.Placemark.length; i++){
					var p = result.Placemark[i].Point.coordinates;
					var add = result.Placemark[i].address;
					places += "<li>"
					places += "<a href=\"javascript:searchLocationsNear("+p[1]+","+p[0]+", '"+add+"')\">"+ add +"</a>";
					places += "</li>";
			    }
				document.getElementById("sidebar").innerHTML = "<strong>Did you mean:</strong><ol>" + places + "</ol>";
			}else{
				document.getElementById("sidebar").innerHTML = "";
				searchLocationsNear(resultLat, resultLng, address);
			}
		}else{
	  		var reason="Code "+result.Status.code;
		  	if(reasons[result.Status.code]){
		    	reason = reasons[result.Status.code];
		  	} 
	  		alert('Could not find "'+ address + '" ' + reason);
		}
	});
}
   
function showDirections(to) {   		
	gdir = new GDirections(map, document.getElementById("sidebar"));
	document.getElementById("sidebar").innerHTML = '<a href="javascript:searchLocations();">Back to stores</a><hr/>';        
	setDirections(resultLat+","+resultLng, to, "en_GB");
}
   
function setDirections(fromAddress, toAddress, locale) {
	gdir.load("from: " + fromAddress + " to: " + toAddress, { "locale": locale });
}

function searchLocationsNear(lat, lng, title){
	myaddress = new GLatLng(lat,lng);
	if(title){ 
		document.getElementById('addressInput').value = title;
	}
	var radius = document.getElementById('radiusSelect').value;
	var searchUrl = './index:locateStoresJson?lat=' + lat + '&lng=' + lng + '&radius=' + radius;
    GDownloadUrl(searchUrl, function(data){
		if(!data || data.clean() == ''){
			return false;
		}
		var my_markers = JSON.decode(data);
		if(!my_markers || my_markers.length < 1){
			return false;
		}
		var mlen = my_markers.markers.length;
        
        if(mlen){
			map.clearOverlays();
			var bounds = new GLatLngBounds();
			var sidebar = document.getElementById('sidebar');
			sidebar.innerHTML = '';
			if(mlen == 1){
				sidebar.innerHTML = 'Sorry, no stores were found.';
				if(defaultlat && defaultlng && defaultzoom){
					map.setCenter(new GLatLng(defaultlat, defaultlng), defaultzoom);
				}
				return;
			}
			var mi=0;
			for(mi=0;mi<mlen;mi++){
				var mmarker = my_markers.markers[mi].marker;
				var title = mmarker.title;
				var address = mmarker.address;
				var telephone = mmarker.telephone;
				var description = mmarker.description;
				var distance = (parseFloat(mmarker.distance)) ? parseFloat(mmarker.distance) : 0;
				var point = new GLatLng(parseFloat(mmarker.lat), parseFloat(mmarker.lng));
				if(typeof distance == 'undefined' || !distance || distance == 0) {
					distance = 0.0;
				}
				var marker = createMarker(point, title, address, description);
				map.addOverlay(marker);
				bounds.extend(point);
				var sidebarEntry = createSidebarEntry(marker, title, address, description, distance);
				sidebar.appendChild(sidebarEntry);
			}
			map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));
		}
	});
}

function createMarker(point, title, address, description) {
	if(title == 'Your Location'){
		var marker = new GMarker(myaddress);
		var html = '<p><strong>' + title + '</strong></p>';
	}else{
		var marker = new GMarker(point, storeIcon);
		if(description){
			var html = '<p><strong>' + title + '</strong><br/>' + description + '<br/>' + address + '</p>';
		}else{
			var html = '<p><strong>' + title + '</strong><br/>' + address + '</p>';
		}
	}
	GEvent.addListener(marker, 'click', function() {
		marker.openInfoWindowHtml(html);
	});
	return marker;
}

function createSidebarEntry(marker, title, address, description, distance) {
	var div = document.createElement('div');
	var html = '';
	
	var coor = marker.getLatLng();
	var lat = coor.y;
	var lng = coor.x;
	if(title != 'Your Location'){
		if(description){
			html += '<strong>' + title + '</strong> (' + distance.toFixed(1) + ' miles)<br/>' + description + '<br/>' + address;
		}else{
			html += '<strong>' + title + '</strong> (' + distance.toFixed(1) + ' miles)<br/>' + address;
		}
		html += "<br/><a href=\"javascript:showDirections('"+lat+","+lng+"')\">Directions</a>";
	}else{
		html += '<strong>' + title + '</strong>';
	}
	div.className = "storeLocation";  
	div.innerHTML = html;
	div.style.cursor = 'pointer';
	GEvent.addDomListener(div, 'click', function() {
		GEvent.trigger(marker, 'click');
	});
	GEvent.addDomListener(div, 'mouseover', function() {
		div.className = "storeLocationOver";
	});
	GEvent.addDomListener(div, 'mouseout', function() {
		div.className = "storeLocation";
	});
	return div;
}

function toHtml(str) {
	str = str.replace(/&lt;/gi, '<');
	str = str.replace(/&gt;/gi, '>');
	str = str.replace(/&quot;/gi, '"');
	str = str.replace(/&#39;/gi, '\'');
	str = str.replace(/&amp;/gi, '&');    	
	return str;
}