(function($){
$(function() {
	
//this code will initiate a different map if only a state is passed and zip/city are blank
//pending items with this are
// -- currently using "SetPoint" to place Pois, which is iterating through MQAPointInfo for the LatLngs / StoreIds
// -- needs to use Poi object to create the overlays, but Poi object currently only accepts Results from MQ

//	 if ($("#mapDiv").get(0) != null && $("#searchCity").val().length == 0 && $("#searchZip").val().length == 0 && $("#searchState").val().length > 0) {
//			var myAltMap = new MapLib.Map('#mapDiv');
//			myAltMap.applySettings({
//				'controlList': ['LargeZoom', 'View'],
//				'hasPMap': false,
//				'hovers': true
//			}).setStateOnlySearch(true).init();
//				
//			
//		} else */

		if ($("#mapDiv").get(0) != null) {
			var myMap = new MapLib.Map('#mapDiv');
			myMap.applySettings({
				'controlList': ['LargeZoom', 'View'],
				'hasPMap': false,
				'hovers': true
			}).init();
			myMap.defaultMapEvents(true, true, true);
			myMap.searchOnAddr('#search', 'val');
			$('.doNewSearch a img').click(function(){
				myMap.search(myMap.getCenter());
			});
	
	} else if ($("#eventDetailMap").get(0) != null) {
		var myEventMap=new MapLib.Map('#eventDetailMap');
		myEventMap.isDraggable(false).init();
		myEventMap.setPrintStatic();
	} else if ($("#storeDetailMapDiv").get(0) != null) {
		var myStoreMap=new MapLib.Map('#storeDetailMapDiv');
		myStoreMap.defineControls(['Zoom','View']).isDraggable(false).hasPrintMap(false).init();
	} else if ($("#drivingDirectionsMap").get(0) != null && $("#searchCity").val().length == 0 && $("#searchZip").val().length == 0 && $("#searchState").val().length == 0) {
		var myRouteStartMap = new MapLib.Map('#drivingDirectionsMap');
		myRouteStartMap.isDraggable(false).init();
	} else if ($("#drivingDirectionsMap").get(0) != null) {
		var ddMap = new MapLib.Route('#drivingDirectionsMap','#routeDirections');
		ddMap.addAddressSource('#search','val');
		ddMap.addAddressSource('#bnStore','text');
		ddMap.buildRoute();
	}


	$('.getDrivingDirections').click(function(){

		var validateRoute = new MapLib.RouteValidation($('#searchStreet').val(), $('#searchCity').val(), $('#searchState').val(), $('#searchZip').val(), $('#dirStoreId').html())
		validateRoute.checkInputs();

	});
	
	if ($('#pStat').html() == 'print') {
		window.print();
		return false;
	}
	
});
	


var MapLib={};

MapLib.mqConnection=function(server){
	var proxyServerName = "";
	var proxyServerPort = "";
	var proxyServerPath = "/storelocator/proxy.aspx";

	var mapServerName = $("#MapServ").text();
	var mqServerPort = $("#MQServPort").text();
	var mqServerPath = $("#MQServPath").text();
	
	if(server=='spatial'){
		server=$("#SpatServ").text();
	}else if(server == 'route'){
		server=$("#RtServ").text();
	}else{
		server=$("#GeoServ").text();
	}

	var exec=new MQExec(server, mqServerPath, mqServerPort, proxyServerName, proxyServerPath, proxyServerPort);

	var geocode=function(add){
		var geoExec;
		var dump = new MQLocationCollection("MQGeoAddress");
		if(server.indexOf('geocode.')!= -1){
			geoExec=exec;
		}else{
			geoExec=new MQExec($("#GeoServ").text(), mqServerPath, mqServerPort, proxyServerName, proxyServerPath, proxyServerPort);
		}
		geoExec.geocode(add, dump);
		return dump.get(0);
	}
	
	
	//geocode
	// myGcColl = new MQLocationCollection("MQGeoAddress");
	if(server.indexOf('route') != -1){
		//returns .box and .res 
		var mySessObj=new MQSession();
		var mySessID = exec.createSessionEx(mySessObj);
		var getSessionID=function(){
			return mySessID;
		}
		
		var getRoute=function(points,options){
			pointGeoColl = new MQLocationCollection("RoutePoints");
			for(var i in points){
				pointGeoColl.add(points[i]);
			}
			var results=new MQRouteResults();
			var boundingBox =new MQA.RectLL(new MQA.LatLng(), new MQA.LatLng());
			exec.doRoute(pointGeoColl,options,results,mySessID,boundingBox);
			return {res:results,box:boundingBox,sessID:mySessID};
		}
	}else{
		var getRoute=function(){
			throw "function invalid for server "+server;
		}
		var getSessionID = getRoute;
	}

	var search=function(crit, res, unkn, dbq){
		var searchExec;
		if(server.indexOf('spatial.')!= -1){
			 searchExec=exec;
		}else{
			 searchExec=new MapLib.mqConnection('spatial');
		}
		return  searchExec.search(crit, res, unkn, dbq);
	}

	var makeAddress=function(add,cit,stat,zip){
		
		var addObj=new MQAddress();
		if (add) {
			addObj.setStreet(add);
		}
		if (cit) {
			addObj.setCity(cit);
		}
		if(stat){
			addObj.setState(stat);			
		}
		if(zip){
			addObj.setPostalCode(zip);	
		}

		return addObj;
	}
	
	var makeAddressFromSel=function(sel,datAccess){
		var a=($(sel+'Street').get().length)?$(sel+'Street')[datAccess]():null;
		var c=($(sel+'City').get().length)?$(sel+'City')[datAccess]():null;
		var s=($(sel+'State').get().length)?$(sel+'State')[datAccess]():null;
		var z=($(sel+'Zip').get().length)?$(sel+'Zip')[datAccess]():null;
		return makeAddress(a,c,s,z);
	}

	//only works for default(geocode) server	
	var geoAddress=function(add,cit,stat,zip){
		return geocode(makeAddress(add,cit,stat,zip));
	}
	
	var geoAddressFromSel=function(sel,datAccess){
		return geocode(makeAddressFromSel(sel, datAccess));
	}
	
	return {'getRoute':getRoute,
		'getSessionID':getSessionID,		
		'search':search,		
		'makeAddress':makeAddress,		
		'makeAddressFromSel':makeAddressFromSel,		
		'geoAddress':geoAddress,
		'geoAddressFromSel':geoAddressFromSel}
}

MapLib.RouteValidation = function(str, cit, st, zip, storeId) {
	var valStr = str;
	var valCit = cit;
	var valSt = st;
	var valZip = zip;
	var thisStoreId = storeId;
	
	var checkInputs=function() {
		if (valCit.length != 0 && valSt.length != 0) {
			clearErrorMsg();
			checkJSONInputs();			
			// call Json response to validate
		} else if (valZip.length != 0) {
			clearErrorMsg();
			checkJSONInputs();
			// call Json ersponse to validate
		} else {
			$($("#directionsOverlay")).css({'height':'225px'});
			$($(".detailDirections")).css({'height':'385px'});
			$($("#searchCity, #searchState, #searchZip")).css({'border':'red 2px solid'});
			$(".ddErrorMsg").html("<strong>Please fill in the City, State or ZIP to get directions.</strong>");
		}
	}
	
	var checkJSONInputs=function() {
		$.get(StoreLocator.location +'/StoreLocator/Stores.aspx', {
					'uiaction': 'getstoresjs',
					'street': valStr,
					'city': valCit,
					'state': valSt,
					'zip': valZip
				}, function(data){
					validateInputs(data);
				}, 'json');
		
		}
	var validateInputs=function(data) {
		//sr = store results
		var sr = data;
	
		if (sr.ZipError) { 
			clearErrorMsg();
			$($("#directionsOverlay")).css({'height':'225px'});
			$($(".detailDirections")).css({'height':'385px'});
			$(".ddErrorMsg").html("<strong>Please enter a valid City, State or ZIP to get directions.</strong>");
			} else if (!sr.ZipError && sr.StoreDetails == null && sr.EventList == null && sr.Ambiguous == null && sr.NearestStores == null) {
				clearErrorMsg();
				$($("#directionsOverlay")).css({'height':'225px'});
			$($(".detailDirections")).css({'height':'385px'});
				$(".ddErrorMsg").html("<strong>We can't find a match for that address. Please try another.</strong>");
			} else if (sr.Ambiguous != null) {
				var ambiguousResults = '';
				
				var ambigData = sr.Ambiguous;
							
				for (var x = 0; x < ambigData.EventicatorAmbiguousResults.length && x < 5; x++){
					ambiguousResults +=	"<a href='"+ StoreLocator.location +"/store/" + thisStoreId + "?subtype=detailDirections&amp;city=" +  ambigData.EventicatorAmbiguousResults[x].City  + "&amp;state=" + ambigData.EventicatorAmbiguousResults[x].State +"'>" +ambigData.EventicatorAmbiguousResults[x].City + ", " + ambigData.EventicatorAmbiguousResults[x].State + "</a><br/>";
				}
				$($("#directionsOverlay")).css({'height':'280px'});
				$($(".detailDirections")).css({'height':'400px'});
				$(".ddErrorMsg").html("<strong>We can't find a match for that address. Did you mean:<br/>" + ambiguousResults);
			} else if (sr.NearestStores != null || sr.EventList != null) {
				window.location = "" +StoreLocator.location+ "/store/" + thisStoreId + "?subtype=detailDirections&amp;city=" +  valCit + "&amp;street=" +valStr+ "&amp;state=" +valSt+ "&amp;zip=" +valZip+ "";
			}
		
	}

	var clearErrorMsg=function() {
		$(".ddErrorMsg").html('');
		$($("#directionsOverlay")).css({'height':'200px'});
		$($(".detailDirections")).css({'height':'350px'});
		$($("#searchCity, #searchState, #searchZip")).css({'border':'2px inset'});
	}
	
	return {'checkInputs':checkInputs}
}


MapLib.Route = function(mapSel,dirSel) {
	var myMap=new MapLib.Map(mapSel);
	var mqExec=new MapLib.mqConnection('route');
	var points=[];
	var selCons={};
	selCons.brand='#bnStoreCorpName';
	selCons.storeName='#bnStoreNickname';
	
	var modifyDSource=function(name,sel){
		selCons[name]=sel;
		return this;
	}

	var addAddressSource = function(sel, typ){
		addToPoints(mqExec.geoAddressFromSel(sel, typ));
		return this;
	}

	var addAddress=function(a,c,s,z){
		addToPoints(mqExec.geoAddress(a,c,s,z));	
		return this;
	}
	
	var addToPoints=function(geoObj){
		points[points.length]=geoObj;
		return this;
	}
	
	var clearPoints=function(){
		points.length=0;
		return this;
	}
	//returns .box and .res 
	var getRouteResultsObj=function(){
		var myOptions = new MQRouteOptions();
		myOptions.setMaxShapePointsPerManeuver(1000); //max number of steps
		return mqExec.getRoute(points,myOptions);		
	}
	
	var getRouteTime=function(res){
		var minutes=res.getTime()/60;
		var textResult='';
		if(minutes > 60){
			if(minutes/60==1){
				textResult+="1 hr ";
			}else{
				textResult+= Math.round((minutes/60)*100)/100 + " hrs";
			}
		}else{
			textResult+= minutes + " min";
		}
		return textResult;
	}
	
	
	var getDistance = function(res){
		return Math.round(res.getDistance()*100)/100;
	}
	
	var buildDirStepMarkup=function(coll){
		var directionsMarkup = '';
		
		//directionsMarkup was overwriting itself while iterating through, thus defined outside of for loop and += at the start
		for (var x = 0; x < coll.getSize();  x++){
			directionsMarkup += "<span class='listPos'>" + (x+1) + "</span>" 
			directionsMarkup +="<span class='directions'>" + coll.get(x).getNarrative() + "</span>";
	 		directionsMarkup +="<span class='miles'>" + getDistance(coll.get(x)) + "</span>";
			directionsMarkup += "<br/><div class='dottedLine'>&#160;</div>";
		}
		return directionsMarkup;	
	}
	
	var buildDirCloseMarkup=function(coll){
		var close="<span class='listPos'>" + (coll.getSize()+1) +"</span>"
		close+="<span class='directions'>Arrive at " + $(selCons.brand).html() + " " + $(selCons.storeName).html() + "</span>"
		return close;
	}
		

	var buildFullDirMarkup = function(res){
		var ret="<div class='routeDirecHdr'>Step-by-Step Directions</div><div class='routeDirecSubHdr'>";
		ret+="<span class='leftSubHdr'>Estimated travel time: about " + getRouteTime(res) + " for " + getDistance(res) + " miles of travel</span>";
		ret+="<span class='rightSubHdr'>Miles</span></div>"
		ret+="<div class='dottedLine'>&#160;</div>";
		var coll = res.getTrekRoutes().get(0).getManeuvers();
		ret+=buildDirStepMarkup(coll);
		ret+=buildDirCloseMarkup(coll);
		return ret;
	}

	var buildRoute=function(){
		var r=getRouteResultsObj();
		myMap.defineControls(['Zoom','View']).isDraggable(true).hasPrintMap(true).init();
		$(dirSel).html(buildFullDirMarkup(r.res));
		myMap.routeHighlight(r.box,mqExec.getSessionID());
		myMap.setPrintStatic();
	}

	return {'modifyDSource':modifyDSource,
		'addAddressSource':addAddressSource,
		'addAddress':addAddress,
		'clearPoints':clearPoints,
		'buildRoute':buildRoute}
}

MapLib.Map = function(sel, zoom){
	var s = {};
	s.iZoom = (zoom) ? zoom : 14;
	s.hasPMap = true;
	s.stateOnlySearch = false;
	s.hovers = false;
	s.controlList = [];
	s.shadow = "True";
	s.draggable = true;
	
	
	var virgin = true; //a search has not been done yet, currently  for text display
	var currentMapRadius = "50";
	
	var mainMap = null;
	var printMap = null;
	var bnIconSolid = new MQA.Icon("http://images.barnesandnoble.com/presources/storelocator/images/bn-button.gif", 27, 45);
	var bnIconTrans = new MQA.Icon("http://images.barnesandnoble.com/presources/storelocator/images/bn-button-unselected.png", 27, 45);
	
	//default icon is usually solid
	var mainIcon = bnIconSolid;
	//hover icon is usually solid,because it usually exists when main is non-default;
	var hoverIcon = bnIconSolid;
	var printIcon = bnIconSolid;
	
	var countDisplay = $('#storesInMapView span');
	var buttonDisplay = $('#storesInMapView div');
	
	var poiList = [];
	
	var applySettings=function(obj){;
	 	for(var x in obj){
			if(s[x]!=undefined){
				s[x]=obj[x];
			}
		}
		return this;
	}

	var routeHighlight = function(box, sessId){
		//MQA.STATICRESOURCES = "http://btileprint.dev.mapquest.com/tileprint.php";
		mainMap.addRouteHighlight(box, "http://map.access.mapquest.com", sessId, true);
		if (s.hasPMap) {
			printMap.addRouteHighlight(box, "http://map.access.mapquest.com", sessId, true);
		}
	}
	
	var getGeocode=function(sel, typ) {
		var exec=new MapLib.mqConnection();
		return exec.geoAddressFromSel(sel,typ).getMQLatLng();
	}
	
	var searchOnAddr=function(sel,typ){
		var exec=new MapLib.mqConnection();
		this.search(exec.geoAddressFromSel(sel,typ).getMQLatLng());
	}
		
	var resetRadius = function(){
		currentMapRadius = "50";
	}
	
	var defaultMapEvents = function(drEndBool, zoomBool, drStartBool){
		var updateControls = function(){
			var cnt = getVisiblePoiCount();
			updateCountDisplay(cnt);
			if (cnt == 0) {
				buttonDisplay.show();
			}else{
				buttonDisplay.hide();
			}
		}
		
		if (drEndBool) {
			this.addEvent('dragend', updateControls);
		}
		if (zoomBool) {
			this.addEvent('zoomend', updateControls);
		}
		if (drStartBool) {
			this.addEvent('dragstart', function(){
				$("#bnStoreOverlay").remove();
			});
		}
		return this;
	}
	
	var getVisiblePoiCount = function(){
		var cnt = 0;
		
		var ULBoundsArray = mainMap.getBounds().getUpperLeft().toString().split(',');
		var upperLeftLat = ULBoundsArray[0];
		var upperLeftLng = ULBoundsArray[1];
		
		var LRBoundsArray = mainMap.getBounds().getLowerRight().toString().split(',');
		var lowerRightLat = LRBoundsArray[0];
		var lowerRightLng = LRBoundsArray[1];
		
		
		for (var i = 0; i < poiList.length; i++) {
			poiLat = poiList[i].lat();
			poiLng = poiList[i].lon();
			if (upperLeftLat > poiLat && poiLat > lowerRightLat && upperLeftLng < poiLng && poiLng < lowerRightLng) {
				cnt++;
			}
		}
		return cnt;
	}
	
	var updateCountDisplay = function(cnt){
		var zoomMsg;
			if (cnt < poiList.length) {
				zoomMsg = "<span class='zoomOutMsg'>(Zoom out or drag map to view more stores)</span>";
			} else {
				zoomMsg = "";
		}	
		
		if (cnt == 0) {
			if (!virgin) {
				countDisplay.html("There are no stores within a " + currentMapRadius + " mile radius. " + zoomMsg);
			}
		}
		else {
			countDisplay.html("You are currently viewing " + cnt + " out of " + poiList.length + " stores in a " + currentMapRadius + " mile radius. " + zoomMsg);
		}
	}
	
	var doSearch= function(LLobj, searchRadius){
		//set up the SearchCriteria - centerLL, radius, # results
		var sCriteria = new MQRadiusSearchCriteria();
		sCriteria.setMaxMatches('1000');
		sCriteria.setRadius(searchRadius);
		// sCriteria.setRadius(document.getElementById('radius').value);
		sCriteria.setCenter(LLobj);
		//Setup search source - in this case, the Test DB table
		var dbLayerQueryCollection = new MQDBLayerQueryCollection();
		var dbLayerQuery = new MQDBLayerQuery();
		dbLayerQuery.setDBLayerName($("#DBLayer").text());
		//MQA.MQ_34507_BNStore
		//MQA.MQ_76725_BNStore (dev)
		dbLayerQueryCollection.add(dbLayerQuery);
		//empty FeatureCollection to hold the search results
		var searchResults = new MQFeatureCollection();
		//Search!
		var exec=new MapLib.mqConnection('spatial');
		exec.search(sCriteria, searchResults, '', dbLayerQueryCollection);
		//return the featurecollection
		return searchResults;
	}

	var search = function(orgnLLObj){
		virgin = false;
		var searchRes = doSearch(orgnLLObj, currentMapRadius);
		if (searchRes.getSize() <= 1) {
			//expand search radius if no results come back
			currentMapRadius = '100';
			searchRes = doSearch(orgnLLObj, currentMapRadius);
		}
		// - this is the shapecollection which may/not be required to be added to map 
		//var myBnStores = new MQA.ShapeCollection(); 
		//myBnStores.setName("BnStorePOIs");
		clearMap();
		poiList.length = 0;
		for (var i = 0; i < searchRes.getSize(); i++) {
			poiList[i] = new Poi(searchRes.get(i));
			poiList[i].makeExpandable();
			if ((searchRes.getSize() - 1 == i && searchRes.getSize() < 11) || i == 10) {
				var myPoint = new MQA.Poi(orgnLLObj);
				myPoint.setValue('infoTitleHTML', 'Search Origin');
				myPoint.setValue('key', 'Origin');
				mainMap.addShape(myPoint);
				mainMap.bestFit();
			}
		}
		updateCountDisplay(getVisiblePoiCount());
		
		if (searchRes.getSize() == 1) {
			poiList[0].getStore();
 		}
		
	}
	
	var getCenter = function(){
		return mainMap.getCenter();
	}
	
	var addEvent = function(str, func){
		MQA.EventManager.addListener(mainMap, str, func);
	}
	
	var hasHover = function(bool){
		hoverSet(bool);
		return this;
	}

	var hoverSet = function(bool){ 
		//default of call sets hover to true hence following line
		var val = (bool == undefined) ? true : bool;
		s.hovers = val;
		if (val) {
			mainIcon = bnIconTrans;
		}
		else {
			mainIcon = bnIconSolid;
		}
	}
	
	
	var hasShadow = function(bool){
		s.shadow = bool;
		return this;
	}
	
	var isDraggable = function(bool){
		s.draggable = bool;
		return this;
	}
	
	var hasPrintMap = function(bool){
		s.hasPMap = bool;
		return this;
	}
	
	var setStateOnlySearch = function(bool) {
		s.stateOnlySearch = bool;
		return this;
	}
	
	var setInitZoom = function(z){
		s.iZoom = z;
		return this;
	}
	
	var defineControls = function(arr){
		s.controlList = arr;
		return this;
	}

	var clearMap = function(){
		mainMap.removeRouteHighlight();
		mainMap.removeAllShapes();
		//mainMap.removeShapeCollection('BnStorePOIs')
		if (s.hasPMap) {
			printMap.removeRouteHighlight();
			printMap.removeAllShapes();
		}
		
	}
	
	var setPrintStatic = function(){
		if (s.hasPMap) {
			printMap.showStaticMap();
		}
	}
	
	var init = function(){
		mainMap = makeMap();
		mainMap.setMapShadowState(s.shadow);
		mainMap.enableDragging(s.draggable);
		if (s.hasPMap) {
			printMap = makeMap('#printMap');
		}
		
		//selector always exists... but no content when not used
		if ($("#MQAPointInfo").html().length != 0) {
			if (s.stateOnlySearch) {
				var tArr = $("#MQAPointInfo").html().split("**");
				for (var i in tArr) {
					var sArr = tArr[i].split("|");
					setPoint(sArr[0],sArr[1],sArr[2]);
				}
				mainMap.bestFit();
			}
			else {
				var tArr = $("#MQAPointInfo").html().split("|");
				setCenter(tArr[0], tArr[1]);
				setPoint(tArr[0], tArr[1], '');
			}
		}

		//set controls iterates through list(if empty, nothing will happen).
		hoverSet(s.hovers);
		setControls();
	}
	
	
	var makeMap = function(mapParSel, nZoom){
		var mySel = (mapParSel) ? mapParSel : sel;
		var nZoom = (nZoom) ? nZoom : s.iZoom;
		var mapElement = $(mySel);
		return new MQA.TileMap(mapElement.get(0), nZoom);
	}
	
	var setCenter = function(latOrObj, lng, pan){
		var storeLoc = (typeOf(latOrObj) == 'object') ? latOrObj : new MQA.LatLng(latOrObj, lng);
		var func = ((typeOf(latOrObj) == 'object' && lng) || pan) ? 'panToLatLng' : 'setCenter';
		mainMap[func](storeLoc);
		if (s.hasPMap) {
			printMap.setCenter(storeLoc);
		}
		if (poiList.length != 0) {
			updateCountDisplay(getVisiblePoiCount());
		}
	}
	
	var setControls = function(){
		for (var i = 0; i < s.controlList.length; i++) {
			mainMap.addControl(new MQA[s.controlList[i] + "Control"]());
		}
	}
	
	
	var setPoint = function(latOrObj, lng, storeId){
		var storeID = storeId
		var storeLoc = (typeOf(latOrObj) == 'object') ? latOrObj : new MQA.LatLng(latOrObj, lng);
		var poi = new MQA.Poi(storeLoc, mainIcon);
		mainMap.addShape(poi);
		
		if (s.stateOnlySearch) {
			poi.setValue('key', storeID);
			MQA.EventManager.addListener(poi, 'click', getStore);
			
		MQA.EventManager.addListener(poi, "mouseover", function(){
		poi.setIcon(hoverIcon);
		
		});
		MQA.EventManager.addListener(poi, "mouseout", function(){
			poi.setIcon(mainIcon);
		});
			
			
		}
		
		if (s.hasPMap) {
			printPoi = new MQA.Poi(storeLoc, printIcon);
			printMap.addShape(printPoi);
		}
	}
	
	var addPoiEvent = function(str, func){
		for (var i in poiList) {
			poiList[i].addEvent(str, func);
		}
	}
	
	//executes on all constructor
	hoverSet(s.hovers);
	var Poi = function(resPointObj){
		var expandable = false;
		var mqPoi = new MQA.Poi(resPointObj.getCenterLatLng(), mainIcon);
		var storeId = resPointObj.getName().split(": ")[0];
		mqPoi.setValue('key', storeId);
		mainMap.addShape(mqPoi);

		MQA.EventManager.addListener(mqPoi, "mouseover", function(){
			mqPoi.setIcon(hoverIcon);
		});
		MQA.EventManager.addListener(mqPoi, "mouseout", function(){
			mqPoi.setIcon(mainIcon);
		});
		
		var stashPoi = function(id, dat){
			if (!MapLib.cache) {
				MapLib.cache = {};
			}
			MapLib.cache['storeIds_' + id] = dat;
		}
		
		var retrievePoi = function(id){
			if (MapLib.cache && MapLib.cache['storeIds_' + id]) {
				return MapLib.cache['storeIds_' + id];
			}
			else {
				return false;
			}
		}

		var makeExpandable = function(){
			if (!expandable) {
				MQA.EventManager.addListener(mqPoi, 'click', getStore);
			}
		}
		
		var center = function(pan){
			setCenter(resPointObj.getCenterLatLng(), pan);
		}
		
		var lat = function(){
			return resPointObj.getCenterLatLng().getLatitude();
		}
		
		var lon = function(){
			return resPointObj.getCenterLatLng().getLongitude();
		}
		
		
		var addEvent = function(str, func){
			MQA.EventManager.addListener(mqPoi, str, func);
		}
		
		var getMQ = function(){
			return mqPoi;
		}
		
		var getStore = function(){
			var x;
			// One = is not an accident
		
		/*	if (x = retrievePoi(storeId)) {
				displayStore(x);
			}
			else { */
				$.get(StoreLocator.location +'/StoreLocator/Stores.aspx', {
					'uiaction': 'getstore',
					'storeid': storeId
				}, function(data){
				//	stashPoi(storeId, data);
					displayStore(data);
				}, 'json');
			//}
		}
		
		var displayStore = function(data){
			$("#bnStoreOverlay").remove();
			var markup=buildDisplayStoreMarkup(data);
			setCenter(resPointObj.getCenterLatLng(), true);
			var cnt=getVisiblePoiCount();
			updateCountDisplay(cnt);
			if (cnt == 0) {
				buttonDisplay.show();
			}else{
				buttonDisplay.hide();
			}
			$(sel).append(markup);
			
			//need to call for bnstore once relevant markup is in place
			Profile.Stores.setEvents();
			$('.dismissOverlay').click(function(){$("#bnStoreOverlay").remove()});
		}
		
		var buildDisplayStoreMarkup=function(data){
			var sd = data.StoreDetails;
			var storeHours = sd.HourDesc.split("~");
			
			var favShow = (sd.IsFavorite) ? 'block' : 'none';
			var favHide = (sd.IsFavorite) ? 'none' : 'block';
			
			var isBtoB = (data.IsBtoB) ? 'none' : 'block';
	
			var myStoreOverlay = "<div id='bnStoreOverlay' style='top:320px;left:285px;height:auto;'><table class='storeList'><tr id='" + sd.StoreNumber + "'><td class='storeImage' style='height:205px;'>";
			myStoreOverlay += "<span class='myBNImage' style='display:" + favShow + ";'> </span><img alt='Store Image' class='storeImage' src='http://images.barnesandnoble.com/pimages/store/photo/s3/" + sd.StoreNumber + ".jpg'/>";
			//store events and driving directions link
			myStoreOverlay += "<div class='overlayLinks'><a class='controlLink' href='"+StoreLocator.location +"/store/" + sd.StoreNumber + "?subtype=detailList'>See all events at this store</a><br/>";
			myStoreOverlay += "<a class='controlLink' href='"+ StoreLocator.location +"/store/" + sd.StoreNumber + "?subtype=detailDirections'>Get driving directions</a><br/>";
			//close div and td
			myStoreOverlay += "</div></td>";
			//open second cell and div for its contents
			myStoreOverlay += "<td class='storeDetails'><div class='storeInfo'>";
			//store name and wifi icon
			myStoreOverlay += "<span class='storeNickname'><a href='"+ StoreLocator.location +"/store/" + sd.StoreNumber + "'>" + sd.Nickname + "</a></span>";
			if (sd.HasWifi === true) {
				myStoreOverlay += "<img alt='AT&amp;T Store WiFi' src='http://images.barnesandnoble.com/presources/storelocator/images/icon_WiFi.gif' class='wifiIcon'/>";
			}
			
			//full address and phone
			if (sd.Line1Addr != sd.Nickname) {
				myStoreOverlay += "<br/>" + sd.Line1Addr;
			}
			if (sd.Line2Addr != '') {
				myStoreOverlay += "<br/>" + sd.Line2Addr;
			}
			
			myStoreOverlay += "<br/>" + sd.City + ", " + sd.State + " " + sd.Zip + "<br/> " + sd.PhoneStore + "<br/>";
			//store hours
			myStoreOverlay += "<div class='storeHours'><strong><br/>Store Hours</strong>";
			for (var i in storeHours) {
				myStoreOverlay += "<br/>" + storeHours[i];
			}
			myStoreOverlay += "</div></div>";
			
			//favShow is for style="display: that are shown when fav==true, favHide is ... hide when fav==false		 
			myStoreOverlay += "<div class='btob' style='display:" + isBtoB + "'>";
			myStoreOverlay += "<div class='addToMyBNStores' style='display:" + favHide + ";height:30px;'><img class='addToMyBN' alt='Add To My B&amp;N Stores' src='http://images.barnesandnoble.com/presources/storelocator/images/btn_AddToMyBN.gif'/>";
			myStoreOverlay += "<br/><br/><span class='controlLink'>What's This?</span></div>";
			myStoreOverlay += "<div class='modifyMyBNStores' style='display:" + favShow + ";height:30px;'><span class='controlLink'>Remove</span>|<span class='controlLink'>Edit</span></div>";
			myStoreOverlay += "</div>";
			
			myStoreOverlay += "</td></tr></table>";
			myStoreOverlay += "<a class='dismissOverlay xDismissBtn'><span>Close</span></a></div>";
			return myStoreOverlay;

		}
		
		//myBnStores.add(poi); - this is the adding to shapecollection which may/not be required to be added to map 
		
		return {'makeExpandable':makeExpandable,
			'center':center,  
			'lat':lat, 
			'lon':lon, 
			'getStore':getStore,
			'addEvent':addEvent, 
			'getMQ':getMQ
			}
	}
	
	return {'routeHighlight':routeHighlight,
		'applySettings':applySettings,
		'searchOnAddr':searchOnAddr,
		'getGeocode':getGeocode,
		'resetRadius':resetRadius,
		'defaultMapEvents':defaultMapEvents,
		'search':search,	
		'getCenter':getCenter,
		'addEvent':addEvent, 
		'hasHover':hasHover, 
		'hasShadow':hasShadow,
		'isDraggable':isDraggable, 
		'hasPrintMap':hasPrintMap,
	    'setInitZoom':setInitZoom,
		'setStateOnlySearch':setStateOnlySearch,
		'defineControls':defineControls, 
		'setPrintStatic':setPrintStatic, 
		'init':init, 
		'addPoiEvent':addPoiEvent
		}
	
};


})(jQuery);
