/*
TODOs
act canberra shown on NSW
test in IE
*/ 


var map, geocoder = '';
var filePath = '/tggweb/public/';

// IE Compaibility - Array.indexOf() - START
if (!Array.prototype.indexOf)
{
  Array.prototype.indexOf = function(elt /*, from*/)
  {
    var len = this.length;

    var from = Number(arguments[1]) || 0;
    from = (from < 0)
         ? Math.ceil(from)
         : Math.floor(from);
    if (from < 0)
      from += len;

    for (; from < len; from++)
    {
      if (from in this &&
          this[from] === elt)
        return from;
    }
    return -1;
  };
}
// IE Compaibility - Array.indexOf() - END

var locator = {

	userMarker: '',
	storeDetailsTimer: '',
	hoverDuration: 300, // delay in ms
	locationLookupTable: {},

	defaultLocation: {
		latitude  : "-26.980828590472107",
		longitude : "133.681640625",
		zoomLevel : 3
	},
	
	init: function() { 
		if (GBrowserIsCompatible()) {
			
			map = new GMap2(document.getElementById('map'));
      
      // add map control
      map.addControl(new GSmallMapControl());
      map.addControl(new GMenuMapTypeControl());
      
      // attach click event on zoom button
      var setZoomIn = setInterval(function(){
        var zoomInJQ = jQuery('#smc>div[title="Zoom In"]');
        
        if(zoomInJQ.length!=0){
          clearInterval(setZoomIn);
          delete(setZoomIn);
        }
        
        zoomInJQ.click(function(e){
          if(locator.currentLocation){
            try{
              map.setCenter(locator.currentLocation.latLng);
            }catch(err){}
          }
        });
      }, 1000);

			map.setCenter(
				locator.locationToLatlng(locator.defaultLocation),
				locator.defaultLocation.zoomLevel
			);
			
			geocoder = new GClientGeocoder();
			geocoder.setBaseCountryCode('au');
			
			locator.controls.configure();
			
			locator.createLocationLookupTable();
			locator.addLocationMarkers(locations.locations);

			if(gup('postcode')) {
				jQuery('#postcode').attr('value', gup('postcode'));
			} else if (gup('state')) {
				jQuery('#state').attr('value', gup('state'));
				if (gup('metropolitan')) {
					jQuery('#state_level').attr('value', 'true');
				} else {
					jQuery('#state_level').attr('value', '');
				}
			}

			var postcode = jQuery('#postcode').attr('value');
			var state = jQuery('#state').attr('value');

			if (postcode) {
				locator.findLocationsByPostCode(postcode);
			} else if (state) {
				locator.goToState(state);
			} else {
				// NOTE - Do nothing for now, stay at default location
			}

			return true;
		}
	},
	

	controls: {
	
		configure: function() {
			jQuery('#find_stores').bind('click',
				function(){locator.findLocationsByPostCode(jQuery('#postcode').attr('value'));}
			);
			jQuery('#regional').bind('click',
				function(){locator.setStateView('regional');}
			);
			jQuery('#metropolitan').bind('click',
				function(){locator.setStateView('metropolitan');}
			);
		},
	
		update: function() {
			var state = locator.getCurrentState();
			jQuery('#store-locator-title').text('Store locator - ' + states[state].regional.title);
			jQuery('#regional').html('View ' + states[state].regional.title);
			jQuery('#state').attr('value', state);
			jQuery('#metropolitan').html('View ' + states[state].metropolitan.title);
			jQuery('#state_level').attr('value', state);
			return true;
		}

	},
	
	displayLocationDetails: function(storeLocations) {
		locator.clearCurrentLocation();
		var output = '';
		output += '<table cellpadding="0" class="store">';
		output += '<thead>';
		output += '<tr>';
		output += '<th class="g_e43_smallTableHead capleft">Store</th>';
		output += '<th class="g_e43_smallTableHead">Your Local Good Guy</th></tr></thead>';
		output += '<tbody>';
		
		var testBallina = false;
		var displayedStores = Array();
		
		for (var i=0; i<storeLocations.length; i++) {
		  var storeName = storeLocations[i].storeName.replace(/[\']+/gi, "\\\'");
		  if ( displayedStores.indexOf(storeName) != -1 ) {
		      continue;
		  }
		  else {
        displayedStores.push(storeName);
      }
			i % 2 ? rowClass = 'odd' : rowClass = 'alt';
			output += '<tr class="' + rowClass + '" id="' + stringToId(storeLocations[i].storeName) + '">';
			output += '<td>';
			if(storeLocations[i].distance) {
				output += ' <div class="store-info-detail"> &nbsp;' + storeLocations[i].distance + 'km</div>';
			}
			output += '<a href="' + storeLocations[i].storeUrl + '" class="trigger"';

      output += 'onmouseover="locator.select(\'' + storeName + '\')"';
      output += 'onmouseout="locator.cancelSelection(\'' + storeName + '\')"';

			output += '>' + storeLocations[i].description + '</a> ';
			output += '</td>';
			output += '<td>' + storeLocations[i].jvpName + '</td>';
			output += '</tr>';
			output += '<tr id="' + stringToId(storeLocations[i].storeName) + '-details" class="store-details"><td colspan="2">';
			output += '<div><span>';
			output += locator.createLocationDetailsHTML(storeLocations[i]);
			output += '</span></div>';
			output += '</td></tr>';
		}
		
		output += '</tbody></table>';
		
		jQuery('#local-store-list').html(output);

	},

	/*
	--- Location handling
	*/
	
	clearCurrentLocation: function() {
		if (locator.currentLocation) {
			locator.highLightLocationMarker(locator.currentLocation.marker , false);
			locator.currentLocation = '';
		}
	},
	
	createLocationLookupTable: function() {
		for (var i=0; i < locations.locations.length; i++) {
			if(locations.locations[i]) {
				locator.locationLookupTable[locations.locations[i].storeName] = locations.locations[i];
			}
		}
	},

	select: function(sLocationName) {
		locator.storeDetailsTimer = setTimeout(function(){
			var location = locator.getLocationByName(sLocationName);
			storeId = stringToId(location.storeName);
			if(!jQuery('#' + storeId).hasClass('selected')) {
				locator.clearCurrentLocation();
				jQuery('.store-details.selected div').slideUp('slow');
				jQuery('.selected').removeClass('selected');
				jQuery('#' + storeId).addClass('selected');
				jQuery('#' + storeId + '-details').addClass('selected');
				jQuery('#' + storeId + '-details div').slideDown('slow');
				locator.highLightLocationMarker(location.marker , true);
				locator.currentLocation = location;
			}
		}, locator.hoverDuration);
	},

	cancelSelection: function(sLocationName) {
		clearTimeout(locator.storeDetailsTimer);
	},

	createLocationDetailsHTML: function(location) {
		var html = '';
		html += '<a href="' + location.storeUrl + '" title="View Location Home">Location home page</a>';
		html += location.address + '<br />';
		html += location.suburb + ' ' + location.state + ' ' + location.postcode + '<br />';
		return html;
	},

	getLocationByName: function(sLocationName) {
		return locator.locationLookupTable[sLocationName];
	},

	getLocationsByState: function(sState) {
		var locationsInState = [];
		for (var i=0; i < locations.locations.length; i++) {
			if (locations.locations[i] && locations.locations[i].state.toLowerCase() == sState) {
				locationsInState[locationsInState.length++] = locations.locations[i];
			}
		}
		return locationsInState;
	},

	getLocationsInView: function() {
		var viewLatLngBounds = map.getBounds();
		var locationsInView = [];
		for (var i=0; i < locations.locations.length; i++) {
			if (locations.locations[i] != null) {
				var location = locations.locations[i];
				if (viewLatLngBounds.containsLatLng(location.latLng)) {
					locationsInView[locationsInView.length++] = location;
				}
			}
		}
		return locationsInView;
	},

	showLocalLocations: function(userMarker) {
		var latLngs = [];
		var storeLocations = [];
		latLngs[latLngs.length++] = userMarker.getLatLng();
		storeLocations = locator.getNearestLocations(locator.userMarker.getLatLng());
		for (var i=0; i<storeLocations.length; i++) {
			latLngs[latLngs.length++] = new GLatLng(storeLocations[i].latitude, storeLocations[i].longitude);
		}

		locator.centerAndZoomOnLatlngs(latLngs);
		locator.displayLocationDetails(locator.getLocationsInView());

		return true;
	},

	getNearestLocations: function(userLatLng) {
		var nearestLocationLocations = [];
		locator.recalculateLocationDistances(userLatLng); // TODO move this to address serach

		for (var i=0; i<locations.locations.length; i++) {
			if (locations.locations[i] && locations.locations[i].distance < 50 && i<3 || i == 0) {
				nearestLocationLocations[nearestLocationLocations.length++] = locations.locations[i];
			}
		}
		return nearestLocationLocations;
	},

	recalculateLocationDistances: function(latLng) {
		for (var i=0; i < locations.locations.length; i++) {
			if (locations.locations[i] != null) {
				locations.locations[i].distance = Math.round(locations.locations[i].latLng.distanceFrom(latLng)/1000);
			}
		}
		locations.locations.sort(locator.sortLocationsByDistance);
		return true;
	},

	/*
	--- Searching
	*/

	findLocationsByPostCode: function(postcode) {
		if (locator.validatePostCode(postcode)) {
			locator.findLocalLocationsByAddress(postcode);
		} else {
			alert("Please enter a valid postcode");
			return false;
		}
	},

	findLocalLocationsByAddress: function(address) {
		var latLng;
		if (geocoder) {
			address = 'Australia ' + address; // Append Australia to give googlemaps more context
			geocoder.getLatLng(
				address,
				function(point) {
					if (!point || !locator.isInAustralia(point)) {
						alert(address + " could not be found");
					} else {
						if (locator.userMarker) {map.removeOverlay(locator.userMarker);};
						
						// 'true' added as last argument to make user - you are here icon "inert"
						// Removed true - since the hover - events are not fired if set to true
						var g_m = new GMarker(point, locator.createUserIcon());
						
						g_m.disableDragging();
						
						// Events for mouse on Home marker icon
						GEvent.addListener(g_m, "mouseover", function() {
              g_m.setImage(filePath + "images/icon_home_over.gif");
            });
						
						GEvent.addListener(g_m, "mouseout", function() {
              g_m.setImage(filePath + "images/icon_home.gif");
            });
						
						
						locator.userMarker = g_m; 
						
						map.addOverlay(locator.userMarker);
						locator.showLocalLocations(locator.userMarker);
						locator.controls.update();
						return true;
					}
				}
			);
		}
	},

	/*
	--- Marker and tooltip createion
	*/

	createLocationMarkers: function(location) {

		var marker = new GMarker(location.latLng, locator.createLocationIcon());
		location.marker = marker;

		GEvent.addListener(marker, "mouseover", function() {
			locator.select(location.storeName);
		});

		GEvent.addListener(marker, "mouseout", function() {
			locator.cancelSelection(location.storeName);
		});

		GEvent.addListener(marker, "click", function() {
			window.location.href = location.storeUrl;
		});

	},

	addLocationMarkers: function(locations) {
		for (var i=0; i < locations.length; i++) {
			if (locations[i] != null) {
				var location = locations[i];
				location.latLng = locator.locationToLatlng(location);
				locator.createLocationMarkers(location);
				map.addOverlay(location.marker);
			}
		}
	},

	highLightLocationMarker: function(marker, state) {
		if (state) {
			marker.setImage(filePath + 'images/store_marker_highlight.png');
		} else {
			marker.setImage(filePath + 'images/store_marker.png');
		}
	},

	createLocationIcon: function() {
		var icon = new GIcon();
		icon.image = filePath + "images/store_marker.png";
		icon.iconSize = new GSize(41, 39);
		icon.iconAnchor = new GPoint(20, 32);
		icon.infoWindowAnchor = new GPoint(25, 0);
		return icon;
	},

	createUserIcon: function() {
		var icon = new GIcon();
		icon.image = filePath + "images/icon_home.gif";
		icon.iconSize = new GSize(39, 64);
		icon.iconAnchor = new GPoint(19, 64);
		icon.infoWindowAnchor = new GPoint(9, 5);
		return icon;
	},
	
	/*
	--- Change view
	*/

	goToState: function(state) {
		var level;
		if(jQuery('#state_level').attr('value')) {
			level = true;
		}
		level ? level = 'metropolitan' : level = 'regional';
		if (states[state]) {
			var location = states[state][level];
			map.setCenter(locator.locationToLatlng(location), location.zoomLevel);
			if ( level == 'metropolitan' ) {
			   locator.displayLocationDetails(locator.getLocationsInView()); // getLocationsByState(state)
			}
			else {
			   locator.displayLocationDetails(locator.getLocationsByState(state));
			}
			locator.controls.update();
			return true;
		} else {
			alert('Please enter a valid state');
			return false;
		}
	},

	setStateView: function(viewLevel) {
		if (viewLevel == 'regional') {
			jQuery('#state_level').attr('value', '');
		} else {
			jQuery('#state_level').attr('value', 'x');
		}
		locator.goToState(jQuery('#state').attr('value'));
		return true;
	},

	/*
	--- Utility functions
	*/

	centerAndZoomOnLatlngs: function(latlngs) {
		var bounds = new GLatLngBounds();
		for (var i=0; i<latlngs.length; i++) {
			bounds.extend(latlngs[i]);
		}
		
		map.setZoom(map.getBoundsZoomLevel(bounds));
		map.setCenter(bounds.getCenter());
		return true;
	},

	sortLocationsByDistance: function(a, b) {
	    var x = a.distance;
	    var y = b.distance;
	    return ((x < y) ? -1 : ((x > y) ? 1 : 0));
	},

	locationToLatlng: function(location) {
		return new GLatLng(location.latitude, location.longitude);
	},

	validatePostCode: function(postcode) {
		if (postcode && postcode.match(/\d{4}/)) {
			return true;
		}
		return false;
	},

	whereAmI: function() {
		var location = map.getCenter() + ' zoomLevel ' + map.getBoundsZoomLevel(map.getBounds());
		console.debug(location);
		var bounds = map.getBounds();
		console.debug(bounds);
		return true;
	},

	getCurrentState: function() {
		var visibleLocations = locator.getLocationsInView();
		var storesInStates = [];
		var probableState = '';
		var mostStores = 0;

		if (visibleLocations) {
			for (var i=0; i<visibleLocations.length; i++) {
				var state = visibleLocations[i].state;
				storesInStates[state] ? storesInStates[state] = storesInStates[state] + 1 : storesInStates[state] = 1;
			}
			for (property in storesInStates) {
				if(storesInStates[property] > mostStores) {
					mostStores = storesInStates[property];
					probableState = property.toLowerCase();
				}
			}
			return probableState;
		} else {
			return false;
		}
	},


	isInAustralia: function(latLng) {
		var nw = new GLatLng('-60.15244221438077', '95.09765625');
		var se = new GLatLng('-5.441022303717974', '165.41015625');
		var australianBounds = new GLatLngBounds();
		australianBounds.extend(nw);
		australianBounds.extend(se);
		if (australianBounds.contains(latLng)) {
			return true;
		} else {
			return false;
		}
	}

};

function stringToId(sString) {
	var sId = sString.toLowerCase();
	sId = sId.replace(/[\s]+/gi, '-');
	sId = sId.replace(/[\']+/gi, '-');
	return sId;
}

function gup(name)	{
  name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
  var regexS = "[\\?&]"+name+"=([^&#]*)";
  var regex = new RegExp( regexS );
  var results = regex.exec( window.location.href );
  if( results == null )
    return "";
  else
    return results[1];
}

jQuery(document).ready(function(){locator.init();});
