/**
 * @fileoverview Venda.Widget.GStoreLocator - allows stores to be searched for using the googlemaps graphical interface
 *
 * Information of all stores is initally imported into a googlemap object. A search is performed which will return stores that are within a specified radius. Results are also displayed in a list which contains links to marker points on the map.
 * 
 * @requires /venda-support/js/Venda.js
 * @requires http://maps.google.com/maps?file=api&amp;v=2&amp;key=[key] - a key can be generated at http://code.google.com/apis/maps/signup.html
 * @requires /venda-support/external/jquery-1.2.2.js or any version above
 * @author Aron San <asan@venda.com>
 * @author Hayley Easton <heaston@venda.com>
 */

// Create gStoreLocator namespace
Venda.namespace('Widget.GStoreLocator');

/**
 * Stub function is used to support JSDoc.
 * @class Venda.Widget.GStoreLocator
 * @constructor
 */
Venda.Widget.GStoreLocator = function(){};

// Global variables 
Venda.Widget.GStoreLocator.storesMap = {};				// Googlemap object

Venda.Widget.GStoreLocator.allStores = []; 				// All store details
Venda.Widget.GStoreLocator.storePoints = []; 			// All store points
Venda.Widget.GStoreLocator.foundStorePoints = []; // Found stores within a radius
Venda.Widget.GStoreLocator.searchMarker = {};			// Search marker
Venda.Widget.GStoreLocator.showSatellite = false;// Disable satellite option as default
Venda.Widget.GStoreLocator.showHybrid = false;// Disable Hybird option as default
// Conversion rate for METERS to MILES 
Venda.Widget.GStoreLocator.METERS_TO_MILES_CONV = 0.000621371192;

	/**
	 * Initilise map.  
	 * @param {string} mapCanvas 					Specify a html container to display the map
	 * @param {string} storeInfoList 			Specify a html list element which contains a list of all stores
	 * @param {obj} startingPos 					Initial map coordinates to display
	 * @param {int} zoomLvl 							Initial map zoom level 
	 * @param {obj} storeMarkerSettings 	Custom settings for store markers
	 * @param {obj} mapType 							Map type - G_NORMAL_MAP, G_SATELLITE_MAP, G_HYBRID_MAP. More can be found at http://code.google.com/apis/maps/documentation/reference.html
	 * @param {string} notSupportedMsg		A message that is displayed if googlemaps is not compatible
	 */
Venda.Widget.GStoreLocator.init = function(mapCanvas, storeInfoList, startingPos, zoomLvl, storeMarkerSettings, mapType, notSupportedMsg, tags) {
		if (GBrowserIsCompatible()) {
			//venda tags for labels - distance and miles
			Venda.Widget.GStoreLocator.tags = tags;
		
			Venda.Widget.GStoreLocator.storesMap = new GMap2(document.getElementById(mapCanvas));
			
			Venda.Widget.GStoreLocator.storesMap.setMapType(mapType);
			Venda.Widget.GStoreLocator.storesMap.enableScrollWheelZoom();
			Venda.Widget.GStoreLocator.storesMap.addControl(new GLargeMapControl());
			Venda.Widget.GStoreLocator.storesMap.addControl(new GMapTypeControl());
			if(!Venda.Widget.GStoreLocator.showSatellite){Venda.Widget.GStoreLocator.storesMap.removeMapType(G_SATELLITE_MAP);}
			if(!Venda.Widget.GStoreLocator.showHybrid){Venda.Widget.GStoreLocator.storesMap.removeMapType(G_HYBRID_MAP);}
			Venda.Widget.GStoreLocator.storesMap.setCenter(new GLatLng(startingPos.lat, startingPos.lng), zoomLvl);
			Venda.Widget.GStoreLocator.allStores = Venda.Widget.GStoreLocator.importStores(storeInfoList);
			Venda.Widget.GStoreLocator.createStorePoints(Venda.Widget.GStoreLocator.allStores, storeMarkerSettings);
		} else {
			document.getElementById(mapCanvas).innerHTML = notSupportedMsg;
		}
	};
	
	/**
	 * Displays stores on the map which are located within a specified radius.
	 * @param {obj} map 									A map object to perform the search on
	 * @param {string} address 						An address/code to base the search on
	 * @param {int} radius 								A radius to restrict the search
	 * @param {obj} searchMarkerSettings 	Custom settings the search marker
	 * @param {array} fStoreList 					An array containing all stores	
	 * @param {string} errContainer				A html element to display error messages
	 * @param {string} isEmptyMsg					Message to be displayed if search box is empty							
	 */
Venda.Widget.GStoreLocator.storeSearch = function(map, address, radius, searchMarkerSettings, fStoreList, errContainer, isEmptyMsg, storeType, service1, service2, service3) {
		//geocoder to convert address to coords
		var geocoder = new GClientGeocoder();

		if (address != '') {
			document.getElementById(errContainer).innerHTML = '';
      if (geocoder) {
        geocoder.getLatLng ( address, function(point) {
            if (!point) {
              document.getElementById(errContainer).innerHTML = address + " not found";
            } else {
							Venda.Widget.GStoreLocator.prepareSearch(Venda.Widget.GStoreLocator.storesMap, Venda.Widget.GStoreLocator.foundStorePoints);
							Venda.Widget.GStoreLocator.searchMarker = Venda.Widget.GStoreLocator.createMarker(point, address, searchMarkerSettings);						
							
							var searchQuery = {};
							searchQuery.addr = address;
							searchQuery.radius = radius;
							searchQuery.storeType = storeType;
							searchQuery.service1 = service1;
							searchQuery.service2 = service2;
							searchQuery.service3 = service3;
							
							Venda.Widget.GStoreLocator.foundStorePoints = Venda.Widget.GStoreLocator.collateFoundStores(Venda.Widget.GStoreLocator.storePoints, Venda.Widget.GStoreLocator.searchMarker, searchQuery.radius, searchQuery.storeType, searchQuery.service1, searchQuery.service2, searchQuery.service3);
							Venda.Widget.GStoreLocator.zoomToStores(map, Venda.Widget.GStoreLocator.foundStorePoints, Venda.Widget.GStoreLocator.searchMarker);						
							Venda.Widget.GStoreLocator.showResults(map, Venda.Widget.GStoreLocator.foundStorePoints); // display markers
							Venda.Widget.GStoreLocator.storesMap.addOverlay(Venda.Widget.GStoreLocator.searchMarker); // display here so that it is placed on top of store markers							
							Venda.Widget.GStoreLocator.showResultsList(Venda.Widget.GStoreLocator.foundStorePoints, searchQuery, fStoreList); //display external list
						}
          }
        );
      }
		} else {
			document.getElementById(errContainer).innerHTML = isEmptyMsg;
			document.mapSearch.srchAddress.focus();
		}
   };		

	/**
	 * Import store information into a array of objects.
	 * @param {string} storeList		Specify a html list element which contains a list of all stores
	 * @returns {array} storeInfo 	An array contain all stores, each store is an object
	 */
Venda.Widget.GStoreLocator.importStores = function(storeList) {	 
	 var storeCount = 0;
	 var storeInfo = [];
	 var elemAttr;
	 
	 var jq = jQuery;
	  
	 jq(storeList + ' li').each(function() {
			storeInfo[storeCount] = {};
			jq(this).find('span').each(function() {
				elemAttr = jq(this).attr('class');
				switch(elemAttr) {				
				case 'sName':
					storeInfo[storeCount].sName = jq(this).html();
					break;
				case 'addr1':
					storeInfo[storeCount].addr1 = jq(this).html();
					break;
				case 'addr2':
					storeInfo[storeCount].addr2 = jq(this).html();
					break;
				case 'addr3':
					storeInfo[storeCount].addr3 = jq(this).html();
					break;
				case 'addr4':
					storeInfo[storeCount].addr4 = jq(this).html();
					break;
				case 'addr5':
					storeInfo[storeCount].addr5 = jq(this).html();
					break;
				case 'phone':
					storeInfo[storeCount].phone = jq(this).html();
					break;
				case 'storeLink':
					storeInfo[storeCount].storeLink = jq(this).html();
					break;
				case 'storeType':
					storeInfo[storeCount].storeType = jq(this).html();
					break;
				case 'service1':
					storeInfo[storeCount].service1 = jq(this).html();
					break;
				case 'service2':
					storeInfo[storeCount].service2 = jq(this).html();
					break;
				case 'service3':
					storeInfo[storeCount].service3 = jq(this).html();
					break;
				case 'lat':
					storeInfo[storeCount].lat = jq(this).html();
					break;
				case 'lng':
					storeInfo[storeCount].lng = jq(this).html();
					break;
				default:
					storeInfo[storeCount] = 'Error - class'+ elemAttr +'is unknown';
					break;
				}
			});
			storeCount++;
	 });
	 return storeInfo;
	 
};
	 
	/**
	 * Create all store points.
	 * @param {obj} allStores							An array containing all stores
	 * @param {obj} storeMarkerSettings 	Custom settings for store markers
	 */
Venda.Widget.GStoreLocator.createStorePoints = function(allStores, storeMarkerSettings) {	 	
	for (var i = 0; i < allStores.length; i++) {
		var point = new GLatLng(allStores[i].lat, allStores[i].lng);
		var marker = Venda.Widget.GStoreLocator.createMarker(point,'<div id="storeInfoBub'+i+'" class="storeInfoBub"><span class="sName">'+ allStores[i].sName +' </span><span class="storeType">'+ allStores[i].storeType +'</span><div><span class="addr1">'+ allStores[i].addr1 +' </span><span class="addr2">'+ allStores[i].addr2 +' </span><span class="addr3">'+ allStores[i].addr3 +' </span><span class="addr4">'+ allStores[i].addr4 +' </span><span class="addr5">'+ allStores[i].addr5 +' </span></div><span class="phone">'+ allStores[i].phone +' </span><span class="storeLink">'+ allStores[i].storeLink +' </span>', storeMarkerSettings);
	
		Venda.Widget.GStoreLocator.storePoints[i] = marker;
		Venda.Widget.GStoreLocator.storePoints[i].sName = allStores[i].sName;
		Venda.Widget.GStoreLocator.storePoints[i].addr1 = allStores[i].addr1;
		Venda.Widget.GStoreLocator.storePoints[i].addr2 = allStores[i].addr2;
		Venda.Widget.GStoreLocator.storePoints[i].addr3 = allStores[i].addr3;
		Venda.Widget.GStoreLocator.storePoints[i].addr4 = allStores[i].addr4;
		Venda.Widget.GStoreLocator.storePoints[i].addr5 = allStores[i].addr5;
		Venda.Widget.GStoreLocator.storePoints[i].phone = allStores[i].phone;
		Venda.Widget.GStoreLocator.storePoints[i].storeType = allStores[i].storeType;
		Venda.Widget.GStoreLocator.storePoints[i].service1 = allStores[i].service1;
		Venda.Widget.GStoreLocator.storePoints[i].service2 = allStores[i].service2;
		Venda.Widget.GStoreLocator.storePoints[i].service3 = allStores[i].service3;
		Venda.Widget.GStoreLocator.storePoints[i].storeLink = allStores[i].storeLink;
		Venda.Widget.GStoreLocator.storePoints[i].lat = allStores[i].lat;
		Venda.Widget.GStoreLocator.storePoints[i].lng = allStores[i].lng;
	}
};

	/**
	 * Create a map marker with an information bubble.
	 * @param {obj} mPoint 			a point where the marker will be placed on the map
	 * @param {string} mInfo 		information that will be displayed in the marker's information bubble
	 * @param {obj} mSetting 		settings for a customised marker - default google marker is used if a object is not passed (shadowImg, iconSizeW, iconSizeH, shadowSizeW, shadowSizeH, iconAnchorW, iconAnchorH, infoWindowAnchorW, infoWindowAnchorH, infoShadowAnchorW, infoShadowAnchorH, markerImg). 
	 * @returns {obj} marker 		a marker object with coordinates and information bubble
	 */
Venda.Widget.GStoreLocator.createMarker = function (mPoint, mInfo, mSetting) {	
		//use default marker if mSettings is not passed
		if (mSetting) {
			var baseIcon = new GIcon();
			baseIcon.shadow = mSetting.shadowImg;
			baseIcon.iconSize = new GSize(mSetting.iconSizeW, mSetting.iconSizeH);
			baseIcon.shadowSize = new GSize(mSetting.shadowSizeW, mSetting.shadowSizeH);
			baseIcon.iconAnchor = new GPoint(mSetting.iconAnchorW, mSetting.iconAnchorH);
			baseIcon.infoWindowAnchor = new GPoint(mSetting.infoWindowAnchorW, mSetting.infoWindowAnchorH);
			baseIcon.infoShadowAnchor = new GPoint(mSetting.infoShadowAnchorW, mSetting.infoShadowAnchorH);
	
			var foundMakerIcon = new GIcon(baseIcon);
			foundMakerIcon.image = mSetting.markerImg;
			var markerOpts = { icon: foundMakerIcon};
			
			var marker = new GMarker(mPoint, markerOpts);
		} else {
			var marker = new GMarker(mPoint);
		}
	
		GEvent.addListener(marker, "click", function() {
			marker.openInfoWindowHtml(mInfo);
		});
		return marker;
	};

	/**
	 * Display found store markers on map.
	 * @param {obj} map							A map object to display results from
	 * @param {array} foundStores		An array of found stores returned from search
	 */
Venda.Widget.GStoreLocator.showResults = function(map, foundStores)	{
		for (var i=0; i < foundStores.length; i++) {
			var point = new GLatLng(foundStores[i].lat, foundStores[i].lng);
			foundStores[i].mapLink = '<a href="#" onclick="Venda.Widget.GStoreLocator.showMarker(Venda.Widget.GStoreLocator.foundStorePoints[' + i + '] )">'+ Venda.Widget.GStoreLocator.tags.showOnMapTxt +'</a>';
			var marker = Venda.Widget.GStoreLocator.createMarker(point);
			map.addOverlay(foundStores[i]);
		}
};

	/**
	 * Show list of stores found and distance from the entered address.
	 * @param {array} foundStores		An array of stores
	 * @param {obj} query						Specifiy query information - address (.addr) and radius(.radius)
	 * @param {string} container		An html element to hold the list of stores
	 * @param {string} storeList		list of found stores  
	 */
	Venda.Widget.GStoreLocator.showResultsList = function(foundStores, query, container) {
		var storeList =''; 
		
		for (var i=0; i < foundStores.length; i++) {
			storeList += '<li id="gStoreResult'+ i +'" class="gStoreResult"><span class="sName">'+ foundStores[i].sName +' </span><span class="storeType">'+ foundStores[i].storeType +'</span><div><span class="distLabel">'+ Venda.Widget.GStoreLocator.tags.distanceLbl +'</span><span class="distValue">'+ foundStores[i].dist + Venda.Widget.GStoreLocator.tags.milesLbl +'</span></div><span class="addr1">'+ foundStores[i].addr1 +' </span><span class="addr2">'+ foundStores[i].addr2 +' </span><span class="addr3">'+ foundStores[i].addr3 +' </span><span class="addr4">'+ foundStores[i].addr4 +' </span><span class="addr5">'+ foundStores[i].addr5 +' </span><span class="phone">'+ foundStores[i].phone +' </span><span class="storeLink">'+ foundStores[i].storeLink +' </span><span class="showOnMap">'+foundStores[i].mapLink+' </span></li>';
		}
		document.getElementById(container).innerHTML = '<p id="queryTxt">There are <span class="numResults">' + foundStores.length + '</span> stores within a   <span class="radius">' + query.radius + '</span> mile radius of <a href="#" onclick="Venda.Widget.GStoreLocator.showMarker(Venda.Widget.GStoreLocator.searchMarker)" id="addrQuery">'+ query.addr +'</a></p><ol id="allStoreResults">' + storeList + '</ol>';
		document.getElementById(container).style.display = 'block';
		return storeList;
	};
	
	/**
	 * Hightlight a marker and its associated information bubble on the map when it is clicked.
	 * @param {obj} marker 	A html element to hold the list of 
	 */
Venda.Widget.GStoreLocator.showMarker = function(marker) {
		GEvent.trigger(marker, "click");
	};
	
	/**
	 * Prepare search by clearing all markers and results array.
	 * @param {obj} map							A map which will be used search for stores
	 * @param {array} foundStores		An array of stores
	 */
Venda.Widget.GStoreLocator.prepareSearch = function(map, foundStores) {
		foundStores.length  = 0; 	// empty found stores array
		map.clearOverlays(); 			// clear all overlay objects
	};
	
	/**
	 * Set a zoom level that will fit all stores found on the map. 
	 * @param {obj} map							A map set zoom level
	 * @param {array} foundStores 	An array of stores
	 * @param {obj} sMarker 				Search marker to be included in the zoom range
	 */
Venda.Widget.GStoreLocator.zoomToStores = function (map, foundStores, sMarker) {
		var bounds = new GLatLngBounds();
		for (var i=0; i < foundStores.length; i++) {
			bounds.extend(foundStores[i].getPoint());
		}
		bounds.extend(sMarker.getPoint());
		map.setZoom(map.getBoundsZoomLevel(bounds));
		map.panTo(bounds.getCenter());
	};
	
	/**
	 * Collate all found stores by calculating the distance between entered address and surrounding stores. The returned stores are then sorted by distance - in ascending order. 
	 * @param {array} sPoints 				Array of store points (coordinates)
	 * @param {obj} sMarker						search marker 	
	 * @param {float} sRadius 				search radius
	 * @param {obj} sType						Store Type dropdown value
	 * @param {obj} sServ1						Service 1 checkbox value
	 * @param {obj} sServ2						Service 2 checkbox value
	 * @param {obj} sServ3						Service 3 checkbox value
	 * @returns {array}	fStorePoints	An array of all found stores which have been sorted by proximity from the search marker 	
	 */
Venda.Widget.GStoreLocator.collateFoundStores = function (sPoints, sMarker, sRadius, sType, sServ1, sServ2, sServ3) {
	Venda.Widget.GStoreLocator.collateFoundStores.i = 0;
	Venda.Widget.GStoreLocator.collateFoundStores.j = 0;
	fStorePoints = [];
	
	for (var i=0; i < sPoints.length; i++) {
		var meters = sMarker.getPoint().distanceFrom(sPoints[i].getPoint());
		miles = meters * Venda.Widget.GStoreLocator.METERS_TO_MILES_CONV;
		serv1 = sPoints[i].service1;
		serv2 = sPoints[i].service2;
		serv3 = sPoints[i].service3;
		
		Venda.Widget.GStoreLocator.collateFoundStores.i = i;
		
		if (miles <= sRadius) {
			if (sType == "All" || sType == ""){ // if the store type dropdown was not selected, show all stores
				Venda.Widget.GStoreLocator.filterStores(sPoints, sType, sServ1, sServ2, sServ3);
			}
			else if(sPoints[i].storeType == sType){ // show stores where the store type dropdown value equals the Store Type value in the story
				Venda.Widget.GStoreLocator.filterStores(sPoints, sType, sServ1, sServ2, sServ3);
			}
		}
	}
		
		//sort array in ascending distance order 
		fStorePoints.sort(function(a, b) {
			var aFloat = parseFloat(a.dist);
			var bFloat = parseFloat(b.dist);
  		return aFloat > bFloat ? 1 : aFloat < bFloat ? -1 : 0;
		});

		return fStorePoints;
		
	};

	/**
	 * Filter all found stores according to the selections made in the form. 
	 * @param {array} sPoints 				Array of store points (coordinates)
	 * @param {obj} sMarker					search marker 	
	 * @param {float} sRadius 				search radius
	 * @param {obj} sType					Store Type dropdown value
	 * @param {obj} sServ1					Service 1 checkbox value
	 * @param {obj} sServ2					Service 2 checkbox value
	 * @param {obj} sServ3					Service 3 checkbox value
	 * @returns {array}	fStorePoints		An array of all found stores which have been sorted by proximity from the search marker 	
	 */
Venda.Widget.GStoreLocator.filterStores = function (sPoints, sType, sServ1, sServ2, sServ3) {
	Venda.Widget.GStoreLocator.returnStores = function(){
		fStorePoints[Venda.Widget.GStoreLocator.collateFoundStores.j] = sPoints[Venda.Widget.GStoreLocator.collateFoundStores.i];
		fStorePoints[Venda.Widget.GStoreLocator.collateFoundStores.j].dist = miles.toFixed(2);
		Venda.Widget.GStoreLocator.collateFoundStores.j++;
	};
	
	if (sServ1 == true && serv1 != ""){ //first checkbox ticked and first service available
		if (sServ2 == true && serv2 != ""){ //second checkbox ticked and second service available
			if (sServ3 == true && serv3 != ""){ //third checkbox ticked and third service available
			Venda.Widget.GStoreLocator.returnStores();
			}
			else if (sServ3 == false && serv3 != ""){ //third checkbox not ticked and third service available
			Venda.Widget.GStoreLocator.returnStores();
			}
			else if (sServ3 == false && serv3 == ""){ //third checkbox not ticked and third service not available
			Venda.Widget.GStoreLocator.returnStores();
			}
		}
		else if (sServ2 == false && serv2 == ""){ //second checkbox not ticked and second service not available
			if (sServ3 == true && serv3 != ""){
			Venda.Widget.GStoreLocator.returnStores();
			}
			else if (sServ3 == false && serv3 != ""){
			Venda.Widget.GStoreLocator.returnStores();
			}
			else if (sServ3 == false && serv3 == ""){
			Venda.Widget.GStoreLocator.returnStores();
			}
		}
		else if (sServ2 == false && serv2 != ""){ //second checkbox notticked and second service available
			if (sServ3 == true && serv3 != ""){
			Venda.Widget.GStoreLocator.returnStores();
			}
			else if (sServ3 == false && serv3 != ""){
			Venda.Widget.GStoreLocator.returnStores();
			}
			else if (sServ3 == false && serv3 == ""){
			Venda.Widget.GStoreLocator.returnStores();
			}
		}
	}
	else if (sServ1 == false && serv1 != ""){ //first checkbox not ticked and first service available
		if (sServ2 == true && serv2 != ""){ //second checkbox ticked and second service available
			if (sServ3 == true && serv3 != ""){
			Venda.Widget.GStoreLocator.returnStores();
			}
			else if (sServ3 == false && serv3 != ""){
			Venda.Widget.GStoreLocator.returnStores();
			}
			else if (sServ3 == false && serv3 == ""){
			Venda.Widget.GStoreLocator.returnStores();
			}
		}
		else if (sServ2 == false && serv2 != ""){ //second checkbox not ticked and second service available
			if (sServ3 == true && serv3 != ""){
			Venda.Widget.GStoreLocator.returnStores();
			}
			else if (sServ3 == false && serv3 != ""){
			Venda.Widget.GStoreLocator.returnStores();
			}
			else if (sServ3 == false && serv3 == ""){
			Venda.Widget.GStoreLocator.returnStores();
			}
		}
		else if (sServ2 == false && serv2 == ""){ //second checkbox not ticked and second service not available
			if (sServ3 == true && serv3 != ""){
			Venda.Widget.GStoreLocator.returnStores();
			}
			else if (sServ3 == false && serv3 != ""){
			Venda.Widget.GStoreLocator.returnStores();
			}
			else if (sServ3 == false && serv3 == ""){
			Venda.Widget.GStoreLocator.returnStores();
			}
		}
	}
	else if (sServ1 == false && serv1 == ""){ //first checkbox not ticked and first service not available
		if (sServ2 == true && serv2 != ""){
			if (sServ3 == true && serv3 != ""){
			Venda.Widget.GStoreLocator.returnStores();
			}
			else if (sServ3 == false && serv3 != ""){
			Venda.Widget.GStoreLocator.returnStores();
			}
			else if (sServ3 == false && serv3 == ""){
			Venda.Widget.GStoreLocator.returnStores();
			}
		}
		else if (sServ2 == false && serv2 != ""){
			if (sServ3 == true && serv3 != ""){
			Venda.Widget.GStoreLocator.returnStores();
			}
			else if (sServ3 == false && serv3 != ""){
			Venda.Widget.GStoreLocator.returnStores();
			}
			else if (sServ3 == false && serv3 == ""){
			Venda.Widget.GStoreLocator.returnStores();
			}
		}
		else if (sServ2 == false && serv2 == ""){
			if (sServ3 == true && serv3 != ""){
			Venda.Widget.GStoreLocator.returnStores();
			}
			else if (sServ3 == false && serv3 != ""){
			Venda.Widget.GStoreLocator.returnStores();
			}
			else if (sServ3 == false && serv3 == ""){
			Venda.Widget.GStoreLocator.returnStores();
			}
		}
	}
};
