function numOnly(num) {
	if (num) {
		return num.replace(/[^\d]/g,'');
	} else {
		return 0;
	}
}

function pad(number, length) {
    var str = '' + number;
    while (str.length < length) {
        str = '0' + str;
    }
    return str;
}


function addSpan(obj,text,className) {
	var span = document.createElement('span');
	span.appendChild(document.createTextNode(text));
	span.className = className;
	obj.appendChild(span);
}

function numberedMarker(index) {
	markerIndex = index+1;
	if (markerIndex>99) markerIndex = '';
	return '/images/pins/marker' + markerIndex + '.png';
}

function isOpen(store) {
	if (store.open_date) {
		var now = new Date();
		var dateArray = store.open_date.replace(/[^\d-]/g,'').split('-');
		// format date to js
		var d = new Date(dateArray[0],dateArray[1]-1,dateArray[2]);
		return (d<=now);
	} else {
		return true;
	}
}

// Create a base icon for all of our markers that specifies the shadow, icon dimensions, etc.
if (GBrowserIsCompatible()) {
	var baseIcon = new GIcon(G_DEFAULT_ICON);
	
	var arrowIcon = new GIcon();
	arrowIcon.image = "/images/pins/arrow.png";
	arrowIcon.shadow = "http://maps.google.com/mapfiles/arrowshadow.png";
	arrowIcon.iconSize = new GSize(20,34);
	arrowIcon.shadowSize = new GSize(39,34);
	arrowIcon.iconAnchor = new GPoint(9,34);
	arrowIcon.infoWindowAnchor = new GPoint(9,2);
	arrowIcon.infoShadowAnchor = new GPoint(18,25);

	var openingSoonIcon = new GIcon();
	openingSoonIcon.image = "/images/pins/coming-soon.png";
	openingSoonIcon.shadow = "/images/pins/coming-soon-shadow.png";
	openingSoonIcon.iconSize = new GSize(20,34);
	openingSoonIcon.shadowSize = new GSize(39,34);
	openingSoonIcon.iconAnchor = new GPoint(9,34);
	openingSoonIcon.infoWindowAnchor = new GPoint(9,2);
	openingSoonIcon.infoShadowAnchor = new GPoint(18,25);

	var stateIcon = new GIcon();
	stateIcon.image = "/images/pins/state-icon.png";
	stateIcon.iconSize = new GSize(40,30);
	stateIcon.iconAnchor = new GPoint(20,15);
}
// define a jmmap object
var jmmap = {
	map: null,
	centerpoint: new GLatLng(37,-96.5	), //center of US
	zoom: 4,
	minMapScale: 4,
	maxMapScale: 14, 
	bounds: new GLatLngBounds(),
	markers: [],
	searchZip: null,
	autoRefresh: true,
	geocoder: null,
	msgBox: null,
	setup: function(div_id) {
		// set map as active
		$('#store-picker').addClass('active');
		// create map object
		this.map = new GMap2(document.getElementById(div_id));
		this.map.setMapType(G_PHYSICAL_MAP);
		this.map.setCenter(this.centerpoint,this.zoom);
		this.map.addControl(new GSmallMapControl(),new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(10,10)));
//		this.map.setUIToDefault();
		this.geocoder = new GClientGeocoder();
		this.msgBox = $('#map-message');

		// refresh map on move
		GEvent.addListener(this.map, 'moveend', function() {
			if (jmmap.autoRefresh) {
				// is the current view within last rendered bounds
				isInBounds = jmmap.bounds.containsBounds(jmmap.map.getBounds());
				// refresh if at state level, otherwise show state breakdown
				if (jmmap.map.getZoom() >=7 ) {
					// if we're outside current bounds, refresh
					if (isInBounds == false) {
						jmmap.refresh();
					}
				} else {
					jmmap.showByState();
				}
			}
		});
/*
		// refresh map if zoomed out
		GEvent.addListener(this.map, 'zoomend', function(oldLevel,newLevel) {
			if (newLevel < oldLevel && jmmap.autoRefresh) jmmap.refresh();
		});
*/
	},
	showByState: function() {
		$.ajax({
			url: '/locations/store-finder.php',
			type: 'get',
			data: 'statecount=1',
			dataType: 'json',
			success: function(statelist){
				// clear map
				jmmap.map.clearOverlays();
				// clear list
				if ($('#locations-list ul.locations').get(0)) {
					$('#locations-list').children().remove();
				}
				// make state markers
				$.each(statelist, function(key,val){
					var marker = new LabeledMarker(new GLatLng(val.lat, val.lng),{
						icon: stateIcon,
						labelText: val.count,
						labelClass: 'state-count',
						labelOffset: new GSize(-20,-15) 
					});
					marker.count = val.count;
					marker.state = val.state;
					
					// show state stores if clicked
					GEvent.addListener(marker,'click', function() {
						jmmap.showStoresInCityState('',this.state);
					});
					jmmap.map.addOverlay(marker);
				});
				jmmap.showMessage('Click on a state count in or search above to see stores.','done');
			}
		})
	},
	refresh: function(pickClosest) {
		jmmap.autoRefresh = false;
		querystring = this.getBoundsQueryString();
		// set loading icon
		$('#map-message').addClass('loading');
		$.ajax({
			url: '/locations/store-finder.php',
			type: 'get',
			data: querystring,
			dataType: 'json',
			success: function(storelist){
				// clear list
				$('#locations-list').children().remove();
				if (storelist.length > 0) {
					// got a list of stores, show on map
					jmmap.markers = [];
					// clear map
					jmmap.map.clearOverlays();
					// reset bounds
					jmmap.bounds = new GLatLngBounds();
					// get current fav store to highlight
					favStore = numOnly($('#storeno').val());
					// loop thorugh stores
					for (var i=0;i<storelist.length;i++) {
						var icon = null;
						// create the maker for map
						if (storelist[i].storeno == favStore) {
							icon = 'arrow';
						}
						// place marker
						jmmap.createMarker(storelist[i],icon,i);
					}
					// update store list
					jmmap.storeListFromBounds();
					// choose closest automatically
					if (pickClosest) {
						$('#locations-list li').eq(0).trigger('click');
						// only do it once per zip update, not for drag refresh
						pickClosest = false;
					}
				} else {
					// no list, show error
					jmmap.showMessage(storelist.error + ' Drag and zoom the map to find stores.','alert');
				}
//				$('#map-message').removeClass('loading');
				jmmap.autoRefresh = true;
	     	}
	     });
	},
	storeListFromBounds: function(zoom) {
		// clear list
		$('#locations-list').children().remove();
		// make text box list
		var storeUL = document.createElement('ul');
		storeUL.className = 'locations';
		for (var i=0;i<jmmap.markers.length;i++) {
			var li = jmmap.createStoreListItem(jmmap.markers[i],i);
			storeUL.appendChild(li);
		}
		if (zoom) jmmap.zoomToBounds();
		// create store list
		$('#locations-list').append(storeUL);
		// done loading
		jmmap.showMessage(jmmap.markers.length + ' Stores found, zoom or drag and pan to see more stores.','done');
	},
	zoomToBounds: function() {
		var oldAutoRefresh = jmmap.autoRefresh;
		jmmap.autoRefresh = false;
		var clat = (jmmap.bounds.getNorthEast().lat() + jmmap.bounds.getSouthWest().lat())/2;
		var clng = (jmmap.bounds.getNorthEast().lng() + jmmap.bounds.getSouthWest().lng())/2;
		jmmap.map.setCenter(new GLatLng(clat,clng),jmmap.map.getBoundsZoomLevel(jmmap.bounds));
		jmmap.autoRefresh = oldAutoRefresh;
	},
	createStoreListItem: function(store,i) {
		// create li for list
		var li = document.createElement('li');
		// store actions ul
		var ul = document.createElement('ul');
		// link
		var a = document.createElement('a')
		if ($('body').hasClass('locations')) {
			ul.className = 'store-actions';
			// set class and don't show actions if it's not open yet
			if (isOpen(store)) {
				// order
				if (store.online_ordering) {
					var order_li = li.cloneNode(false);
					order_li.className = 'order';
					var order_a = a.cloneNode(false);
					var order_text = 'Order Online';
					order_a.href = 'http://order.jerseymikes.com/Menu.aspx?StoreNum=' + store.storeno;
					order_a.appendChild(document.createTextNode(order_text));
					order_a.title = order_text;
					order_li.appendChild(order_a);
					ul.appendChild(order_li);
				}
				// directions
				var dir_li = li.cloneNode(false);
				dir_li.className = 'dir';
				var dir_a = a.cloneNode(false);
				var dir_text = 'Get Directions';
				dir_a.href = 'http://maps.google.com/maps?daddr=' + store.lat + ',' + store.lng;
				if (jmmap.directions) {
					dir_a.onclick = jmmap.directions.show;
				}
				dir_a.appendChild(document.createTextNode(dir_text));
				dir_a.title = dir_text;
				dir_li.appendChild(dir_a);
				ul.appendChild(dir_li);
				// Email CLub
				var email_li = li.cloneNode(false);
				email_li.className = 'email';
				var email_a = a.cloneNode(false);
				var email_text = 'Join Email Club';
				email_a.href = '/emailclub/?storeno=' + store.storeno;
				email_a.appendChild(document.createTextNode(email_text));
				email_a.title = email_text;
				email_li.appendChild(email_a);
				ul.appendChild(email_li);
				// Comment Card
				var cc_li = li.cloneNode(false);
				cc_li.className = 'comment';
				var cc_a = a.cloneNode(false);
				var cc_text = 'Comment Card';
				cc_a.href = '/comment-card.php?storeno=' + store.storeno;
				cc_a.appendChild(document.createTextNode(cc_text));
				cc_a.title = cc_text;
				cc_li.appendChild(cc_a);
				ul.appendChild(cc_li);
				// Gift Card
				if (store.giftcard) {
					var gc_li = li.cloneNode(false);
					gc_li.className = 'gc';
					var gc_a = a.cloneNode(false);
					var gc_text = 'Gift Cards Accepted';
					gc_a.href = '/gift-cards/';
					gc_a.appendChild(document.createTextNode(gc_text));
					gc_a.title = gc_text;
					gc_li.appendChild(gc_a);
					ul.appendChild(gc_li);
				}
			} else {
				li.className = 'coming-soon';
				// add Coming Soon text
				var cs_li = li.cloneNode(false);
				cs_li.className = 'open_date';
				var cs_text = 'Opening '+ store.open_date;
				cs_li.appendChild(document.createTextNode(cs_text));
				ul.appendChild(cs_li);
			}
			// add store actions
			li.appendChild(ul);
		}
		// show distance
		if (store.dist) {
			addSpan(li,store.dist + ' miles away','dist');
			li.appendChild(document.createElement('br'));
		}
		// show title
		if (store.title) {
			addSpan(li,store.title,'title');
			li.appendChild(document.createElement('br'));
		}
		if (store.alt_name) {
			addSpan(li,'('+store.alt_name+' Area)','alt_name');
			li.appendChild(document.createElement('br'));
		}
		addSpan(li,store.address1,'address1');
		if (store.address2) {
			li.appendChild(document.createElement('br'));
			addSpan(li,store.address2,'address2');
		}
		// show tel/fax if it's open
		li.appendChild(document.createElement('br'));
		addSpan(li,store.city + ', ' + store.state + ' ' + pad(store.zip,5),'');
		li.appendChild(document.createElement('br'));
		addSpan(li,'Tel: ' + store.tel,'tel');
		if (store.fax)	{
			li.appendChild(document.createElement('br'));
			addSpan(li,'Fax: ' + store.fax,'fax');
		}
		addSpan(li,store.lat,'lat');
		addSpan(li,store.lng,'lng');

		li.storeno = store.storeno;
		li.coop = store.coop;
		li.index = i;
		li.onclick = jmmap.setStore;
		// highlight if current
		if (store.storeno == $('#storeno').val()) {
			li.className = 'active';
		}
		return li;
	},
	createMarker: function(store,icon,index) {
		var icon;
		lat = store.lat;
		lng = store.lng;

		var point = new GLatLng(lat,lng);
		//numbered markers or arrow if needed
		if (icon == 'arrow') {
			icon = new GIcon(arrowIcon);
		} else if (!isOpen(store)) {
			icon = new GIcon(openingSoonIcon);
		} else {
			icon = new GIcon(baseIcon);
			if (store.dist > 0) {
				icon.image = numberedMarker(index);
			}
		}
		var marker = new GMarker(point, icon);
		// add attributes
		for (param in store) {
			marker[param] = store[param];
		}
		marker.index = index;

		GEvent.addListener(marker,'click', this.setStore);

		this.bounds.extend(point);
		this.markers.push(marker);
		//show marker
		this.map.addOverlay(marker);
	},
	getBoundsQueryString: function() {
   	 	var mapBounds = jmmap.map.getBounds();
   	 	lat_hi = mapBounds.getNorthEast().y;
   	 	lat_lo = mapBounds.getSouthWest().y;
   	 	lng_hi = mapBounds.getNorthEast().x;
   	 	lng_lo = mapBounds.getSouthWest().x;
   	 	var q = 'lat_hi=' + lat_hi + '&lat_lo=' + lat_lo + '&lng_hi=' + lng_hi + '&lng_lo=' + lng_lo;
   	 	// if we have a zip code, send zip lat/lng
   	 	if (jmmap.searchZip) {
   	 		q += "&zlat=" + jmmap.searchZip.point.lat() + "&zlng=" + jmmap.searchZip.point.lng() + "&zip=" + jmmap.searchZip.code
   	 	}
   	 	return q;
	},
	setStore: function() {
		var title = '';
		var storeObj;
		var locationLIs = $('#locations-list .locations>li');
		if (this.tagName == 'LI') {
			// clicked on list
			storeObj = jmmap.markers[this.index];
			//show in map
			jmmap.autoRefresh = false;
			jmmap.map.panTo(new GLatLng(storeObj.lat,storeObj.lng));
			setTimeout('jmmap.autoRefresh = true',1500);
		} else {
			// clicked on pin
			storeObj = this;
			// show in list
			$('#locations-list').scrollTo(locationLIs.eq(storeObj.index),200);
		}
		//set hidden fields
		if (storeObj.storeno) $('#storeno').val(storeObj.storeno);
		if (storeObj.coop)    $('#coop').val(storeObj.coop);
		// set title if supplied
		if (storeObj.title) {
			title = storeObj.title + ' - ';
		}
		// set address label
		$('#store-address').html('#' + storeObj.storeno + ' - ' + title + storeObj.address1 + ', ' + storeObj.city + ', ' + storeObj.state);
		//reset all icons
		$.each(jmmap.markers,function(index,value) {
			if (value.dist > 0) {
				newImg = numberedMarker(index);
			} else if (!isOpen(value)) {
				newImg = '/images/pins/coming-soon.png';
			} else {
				newImg = '/images/pins/marker.png';
			}
			value.setImage(newImg);
		});
		// change current pin icon
		storeObj.setImage(arrowIcon.image);
		// set this li as active, remove active class from all others
		locationLIs.each(function(index) {
			$(this).removeClass('active');
		});
		locationLIs.eq(storeObj.index).addClass('active');
	},
	showStoresInDBZip: function(zip,pickClosest) {
		zip = numOnly(zip);
		$.ajax({
			url: '/locations/zip-finder.php',
			type: 'get',
			data: 'zip='+zip,
			dataType: 'json',
			success: function(statelist) {
				if (statelist.length == 0) {
					// can't find zip
					jmmap.showMessage("Couldn't find that zip code, please enter a valid zip code.",'alert');
				} else {
					point = new GLatLng(statelist[0].lat, statelist[0].lng);
					jmmap.searchZip = {
						'code': zip,
						'point': point
					};
					jmmap.map.setCenter(point, 10);
					jmmap.refresh(pickClosest); // (autopick)
				}
			}
		})
	},
	showStoresInZip: function(zip,pickClosest) {
		jmmap.showStoresInDBZip(zip,pickClosest);
/*
		zip = numOnly(zip);
		this.geocoder.getLatLng(zip,function(point) {
			if (!point) {
				jmmap.showMessage("Couldn't find that zip code, please enter a valid zip code.",'alert');
				// jmmap.map.centerAndZoom(null,6);
			} else {
				//fix bad google maps geocoder for 07719
				if (zip == '07719') point = new GLatLng(40.178447,-74.021802);
				jmmap.searchZip = {
					'code': zip,
					'point': point
				};
				jmmap.map.setCenter(point, 10);
				jmmap.refresh(pickClosest); // (autopick)
			}
		});
*/
	},
	showStoresInCityState: function(city,state) {
		jmmap.searchZip = null;
		// set loading icon
		$('#map-message').addClass('loading');
		$.ajax({
			url: '/locations/store-finder.php',
			type: 'get',
			data: "city=" + city + "&state=" + state,
			dataType: 'json',
			success: function(storelist){
				// clear list
				$('#locations-list').children().remove();
				if (storelist.length > 0) {
					// got a list of stores, show on map
					jmmap.markers = [];
					// clear map
					jmmap.map.clearOverlays();
					// reset bounds
					jmmap.bounds = new GLatLngBounds();
					// get current fav store to highlight
					favStore = numOnly($('#storeno').val());
					// loop thorugh stores
					for (var i=0;i<storelist.length;i++) {
						var icon = null;
						// create the maker for map
						if (storelist[i].storeno == favStore) {
							icon = 'arrow';
						}
						// place marker
						jmmap.createMarker(storelist[i],icon,i);
					}
					// update store list
					jmmap.storeListFromBounds(true);
				} else {
					// no list, show error
					jmmap.showMessage('No Stores Found. Drag and zoom the map to find stores.','alert');
				}
				jmmap.autoRefresh = true;
	     	}
	     });
	},
	showSingleStore : function(storeno) {
		$.ajax({
			url: '/locations/store-finder.php',
			type: 'get',
			data: "storeno=" + storeno,
			dataType: 'json',
			success: function(storelist){
				// clear list
				if (storelist.length > 0) {
					// got a list of stores, show on map
					jmmap.markers = [];
					// clear map
					jmmap.map.clearOverlays();
					// reset bounds
					jmmap.bounds = new GLatLngBounds();
					// place marker
					jmmap.createMarker(storelist[0],'arrow',0);
					// update store list
					jmmap.storeListFromBounds(true);
				} else {
					// no list, show error
					jmmap.showMessage('Store Not Found.','alert');
				}
	     	}
	     });
		// turn off auto-refresh
		jmmap.autoRefresh = false;
	},
	//show stores displayed in list from search
	showStoresFromList: function() {
		var storeList = $('#locations-list > .locations > li');
		$.each(storeList,function(index,theLi) {
			$(theLi).click(jmmap.setStore);
			$(theLi).find('.dir a').click(jmmap.directions.show);
			var store = {
				dist: numOnly($(theLi).find('.dist').html()),
				storeno: numOnly($(theLi).find('.storeno').html()),
				lat: $(theLi).find('.lat').html(),
				lng: $(theLi).find('.lng').html()
			}
			if ($(theLi).find('.open_date')) {
				store.open_date = $(theLi).find('.open_date').html();
			} else {
				store.open_date = null;
			}
			// set index
			$(theLi).context.index = index;
			jmmap.createMarker(store,'',index);
		});
		// zoom to bounds
		jmmap.zoomToBounds();
		// done loading
		jmmap.showMessage(storeList.length + ' Stores found.','done');
	},
	directions: {
		obj: null,
		toLatLng: null,
		startbox: '<label for="saddr">Enter Your Starting Address or Zip:</label> <input type="text" id="saddr" name="" size="25" /> <button onclick="jmmap.directions.show(true);">Get Directions</button>',
		setup: function(divid) {
			this.obj = new GDirections(jmmap.map, document.getElementById(divid));
			GEvent.addListener(jmmap.directions.obj, 'error', jmmap.directions.error);
			GEvent.addListener(jmmap.directions.obj, 'load', jmmap.directions.done);
		},
		show: function(getDir) {
			if (jmmap.msgBox.length > 0) {
				if (getDir === true) {
					start_address = $('#saddr').val();
					if (start_address) {
						// turn off auto-refresh
						jmmap.autoRefresh = false;
						jmmap.directions.obj.clear();
						dirString = start_address + " to " + jmmap.directions.toLatLng[0] + "," + jmmap.directions.toLatLng[1];
						jmmap.showMessage('Getting Directions','loading');
						if (dirString)	jmmap.directions.obj.load(dirString);
					}
				} else {
					jmmap.directions.toLatLng = this.href.substr(this.href.indexOf('=')+1).split(',');
					jmmap.showMessage(jmmap.directions.startbox,'alert');
				}
				return false;
			}
		},
		done: function() {
			jmmap.showMessage('Directions are below','done');
		},
		error: function() {
			if (jmmap.directions.obj.getStatus().code == G_GEO_UNKNOWN_ADDRESS)
				jmmap.showMessage("Your starting address could not be found, please try again with using zip code or another address.",'alert');
			else if (jmmap.directions.obj.getStatus().code == G_GEO_SERVER_ERROR)
				jmmap.showMessage("A geocoding or directions request could not be successfully processed, yet the exact reason for the failure is not known.\n Error code: " + jmmap.directions.obj.getStatus().code,'alert');
			else if (jmmap.directions.obj.getStatus().code == G_GEO_MISSING_QUERY)
				jmmap.showMessage("The HTTP q parameter was either missing or had no value. For geocoder requests, this means that an empty address was specified as input. For directions requests, this means that no query was specified in the input.\n Error code: " + jmmap.directions.obj.getStatus().code,'alert');
			else if (jmmap.directions.obj.getStatus().code == G_GEO_BAD_KEY)
				jmmap.showMessage("The given key is either invalid or does not match the domain for which it was given. \n Error code: " + jmmap.directions.obj.getStatus().code,'alert');
			else if (jmmap.directions.obj.getStatus().code == G_GEO_BAD_REQUEST)
				jmmap.showMessage("A directions request could not be successfully parsed.\n Error code: " + jmmap.directions.obj.getStatus().code,'alert');
			else jmmap.showMessage("An unknown error occurred.");
			if (jmmap.roadtrip) GEvent.removeListener(jmmap.roadtrip.dirListener);
		}
	},
	showMessage: function(msg,note) {
		this.msgBox.removeClass();
		this.msgBox.addClass(note);
		this.msgBox.html(msg);
	}
}
