$(document).ready(function() {	
	if(GBrowserIsCompatible()) {
		JTagMap.loadMap();
		JTagMap.viewMap();
		JTagMap.startHashPolling();
	}
});

$(document).unload(function() {GUnload();});

JTagMap = function() {};

JTagMap.mapName = 'storesmap';
JTagMap.expectedHash = '';

JTagMap.viewState = 'overall';
JTagMap.currentMetroId = 0;
JTagMap.currentStoreId = 0;

JTagMap.map = null;

JTagMap.storeInfo = new Object();
JTagMap.metroInfo = new Object();

JTagMap.latLngStores = new Object();
JTagMap.storeLatLngs = new Object();
JTagMap.storeMarkers = new Object();
JTagMap.storeScrollers = new Object();
JTagMap.markerNum = 1;

JTagMap.baseIcon = new GIcon();
JTagMap.baseIcon.iconSize = new GSize(20, 34);
JTagMap.baseIcon.iconAnchor = new GPoint(10, 34);
JTagMap.baseIcon.infoWindowAnchor = new GPoint(10, 1);
JTagMap.baseIcon.imageMap = [9,0,6,0,5,1,2,3,1,5,0,7,0,12,1,14,2,16,4,17,6,19,8,21,8,33,11,33,11,21,13,19,15,17,17,16,18,14,19,12,19,7,18,5,17,3,14,1,6,0,12,0,10,0];
JTagMap.baseIcon.transparent = "/images/maps/marker_gray_xparent.png";

JTagMap.blueIcon =  new GIcon(JTagMap.baseIcon);
JTagMap.blueIcon.image = "/images/maps/png/marker_blue.png";
JTagMap.blueIcon.printImage = "/images/maps/gif/marker_blue.gif";
JTagMap.blueIcon.mozPrintImage = "/images/maps/gifmoz/marker_blue.gif";

JTagMap.windowOptions = new Object();
JTagMap.windowOptions.maxWidth = 275;


//This functions loads the map in the div for the first time
JTagMap.loadMap = 
function() {
	JTagMap.map = new GMap2(document.getElementById(JTagMap.mapName));
	if(!JTagMap.map) {
		return;
	}
	JTagMap.map.addControl(new GSmallZoomControl());
};


/*
This helper function performs a modulus
on floating point numbers
*/
JTagMap.modulus = 
function(y, x) {
	var z = y - x * Math.floor((y / x));
	return z;
};


/*
This function returns an array of latitude/longitude pairs,
that lie in circle of radius r (in meters) around the given
latitude/longitude pair
*/
JTagMap.calcPointsAroundLatLng = 
function(lat, lng, radius, numPoints) {
	//had problems with lat being a string, so this is a crude way of forcing it to be a number
	lat = lat * 1;
	lng = lng * 1;
	var latRad = lat * (Math.PI / 180);
	var lngRad = lng * (Math.PI / 180);
	var radiusEarth = 6378.160 * 1000;
	var distanceRad = radius / radiusEarth;
	var degree = 0;
	var degreeRad = 0;
	var degreInterval = 360 / numPoints;
	var points = Array();

	for(var point = 0; point < numPoints; point++) {
		degree = point * degreInterval;
		degreeRad = degree * (Math.PI / 180);
		lat2Rad = Math.asin(Math.sin(latRad) * Math.cos(distanceRad) + Math.cos(latRad) * Math.sin(distanceRad) * Math.cos(degreeRad));
		if(Math.cos(lat2Rad) == 0) {
			lng2Rad = lngRad;
		}
		else {
			lng2Rad = JTagMap.modulus(lngRad + Math.asin(Math.sin(degreeRad) * Math.sin(distanceRad) / Math.cos(latRad)) + Math.PI, 2 * Math.PI) - Math.PI;
		}
		lat2 = lat2Rad * (180 / Math.PI);
		lng2 = lng2Rad * (180 / Math.PI);
		points.push(new Array(lat2, lng2));
	}
	return points;
};


//For internal use only
JTagMap.updateHash = 
function() {
	var hash = '#';
	if(JTagMap.currentMetroId != '') {
		hash += 'm=' + encodeURIComponent(JTagMap.currentMetroId);
		
		if(JTagMap.currentStoreId != 0) {
			hash += '&s=' +encodeURIComponent(JTagMap.currentStoreId.toString());
		}
	}
	
	//cant get this to work in safari, anyway I try it
	if(navigator.userAgent.indexOf('Safari') == -1) {
		window.location.hash = hash;
		JTagMap.expectedHash = hash;
	}
};


//For internal use only
JTagMap.startHashPolling = 
function() {
	//cant get this to work in safari, anyway I try it
	if(navigator.userAgent.indexOf('Safari') == -1) {
			x = window.setInterval(
			function() {
			var winLocHash = window.location.hash;
			var expectedHash = JTagMap.expectedHash.slice(1);
			if(window.location.hash.charAt(0) == '#') {
				winLocHash = window.location.hash.slice(1);
			}
			if(expectedHash != winLocHash) {
				JTagMap.viewMap();
			}
		}, 200);
	}
};

//Should only be called when class is beign initialized
JTagMap.addStoreInfo = 
function(storeId, metroId, latitude, longitude) {
	var x = Object();
	var point = null;
	var icon = null;
	var marker = null;

	x['storeId'] = storeId;
	x['metroId'] = metroId;
	x['latitude'] = latitude;
	x['longitude'] = longitude;
	JTagMap.storeInfo[storeId] = x;

	JTagMap.metroInfo[metroId]['bounds'].extend(new GLatLng(latitude, longitude)); 
	JTagMap.metroInfo[metroId]['num']++;
	JTagMap.metroInfo[metroId]['stores'].push(storeId);
};


//Should only be called when class is being initialized
//addMetroId should only be called before all addStoreInfo()
//calls are done
JTagMap.addMetroInfo = 
function(metroId, metroCodename, metroName) {
	var metroText = metroName;
	metroText = metroText.replace("&amp;", "&");
	metroText = metroText.replace("&quot;", "\"");
	metroText = metroText.replace("&#039;", "'");
	metroText = metroText.replace("&lt;", "<");
	metroText = metroText.replace("&gt;", ">");
	
	JTagMap.metroInfo[metroId] = new Object();
	JTagMap.metroInfo[metroId]['name'] = metroName;
	JTagMap.metroInfo[metroId]['nameText'] = metroText;
	JTagMap.metroInfo[metroId]['codename'] = metroCodename;
	JTagMap.metroInfo[metroId]['num'] = 0;
	JTagMap.metroInfo[metroId]['bounds'] = new GLatLngBounds();
	JTagMap.metroInfo[metroId]['stores'] = new Array();
}


//For internal use only
JTagMap.addLatLngStore = 
function(latitude, longitude, storeId) {
	if(typeof(JTagMap.latLngStores[latitude]) == 'undefined') {
		JTagMap.latLngStores[latitude] = new Object();
	}
	if(typeof(JTagMap.latLngStores[latitude][longitude]) == 'undefined') {
		JTagMap.latLngStores[latitude][longitude] = new Array();
	}
	JTagMap.latLngStores[latitude][longitude].push(storeId);
};


//For internal use only
JTagMap.createStoreMarker =
function(latitude, longitude, storeId) {
	var store = JTagMap.storeInfo[storeId];
	var point = new GLatLng(latitude, longitude);
	var storeIcon =  new GIcon(JTagMap.baseIcon);
	var markerOptions = new Object();

	if(JTagMap.markerNum < 131) {
		iconSuffix = '_' + JTagMap.markerNum;
		JTagMap.markerNum++;
	}
	else {
		iconSuffix = '_gray';
	}

	storeIcon.image = "/images/maps/png/marker" + iconSuffix + ".png";
	storeIcon.printImage = "/images/maps/gif/marker" + iconSuffix + ".gif";
	storeIcon.mozPrintImage = "/images/maps/gifmoz/marker" + iconSuffix + ".gif";
	markerOptions.icon = storeIcon;
	markerOptions.clickable = true;
	markerOptions.title = $('#storebubbledesc'+storeId+' h3').html();

	var marker = new GMarker(point, markerOptions);

	GEvent.addListener(marker, "click", 
	function() {
		var infoTabs = new Array();

		$('#storebubbledesc'+storeId+' .photo').attr('src', $('#storebubbledesc'+storeId+' .imageSrc').html());
		html = $('#storebubbledesc'+storeId).html();
		infoTabs.push(new GInfoWindowTab('Description','<div class="storesmapbubbexcerpt">'+html+'</div>'));

		html = $('#storebubbledetails'+storeId).html();
		infoTabs.push(new GInfoWindowTab('Details', html));
		
		offset = $('#storesmapstores').offset();
		topHeight = offset.top;

		$('#storesmapstores').animate({scrollTop: JTagMap.storeScrollers[storeId] - topHeight}, 1000, "easeOutExpo");

		marker.openInfoWindowTabsHtml(infoTabs, JTagMap.windowOptions);

		JTagMap.currentStoreId = storeId;

		JTagMap.updateHash();

		window.scrollTo(0, 0);
	});

	return marker;
};


//For internal use only
JTagMap.createMetroMarker =
function(metroId) {
	var bounds = JTagMap.metroInfo[metroId]['bounds'];
	var lat = (bounds.getNorthEast().lat() + bounds.getSouthWest().lat())/2;
	var lng = (bounds.getNorthEast().lng() + bounds.getSouthWest().lng())/2;
	var markerOptions = new Object();
	markerOptions.icon = JTagMap.blueIcon;
	markerOptions.clickable = true;
	markerOptions.title = JTagMap.metroInfo[metroId]['nameText'] + ": "+ 
		JTagMap.metroInfo[metroId]['num'] + " store(s)";
	var point = new GLatLng(lat, lng);	
	var marker = new GMarker(point, markerOptions);

	GEvent.addListener(marker, "click",
	function() {
		JTagMap.viewMetro(metroId, false);
	});

	return marker;
};


//Here we zoom in on a store from any other state
JTagMap.viewStore = 
function(storeId) {
	var store = JTagMap.storeInfo[storeId];
	if(typeof(JTagMap.storeInfo[storeId]) == 'undefined' || 
		(JTagMap.viewState !== 'overall' && typeof(JTagMap.storeMarkers[storeId]) == 'undefined')) {
		return;
	}

	if(JTagMap.viewState == 'overall') {
		JTagMap.viewMetro(store['metroId'], false);
	}	

	GEvent.trigger(JTagMap.storeMarkers[storeId], "click");
};


//This shows all the stores in a metro
JTagMap.viewMetro = 
function(metroId, shouldUpdateHash) {
	var metro = JTagMap.metroInfo[metroId];
	if(typeof(metro['name']) == 'undefined') {
		JTagMap.viewMetros(false);
		return;
	}

	var lat = (metro['bounds'].getNorthEast().lat() + 
		metro['bounds'].getSouthWest().lat()) / 2;
	var lng = (metro['bounds'].getNorthEast().lng() + 
		metro['bounds'].getSouthWest().lng())/2;
	var marker;
	var x;
	var y;

	JTagMap.map.clearOverlays();

	JTagMap.map.setCenter(new GLatLng(lat,lng));
	JTagMap.map.setZoom(JTagMap.map.getBoundsZoomLevel(metro['bounds']));

	JTagMap.latLngStores = new Object();
	JTagMap.storeLatLngs = new Object();
	JTagMap.storeMarkers = new Object();
	JTagMap.storeScrollers = new Object();
	JTagMap.markerNum = 1;

	for(i in metro['stores']) {
		x = JTagMap.storeInfo[metro['stores'][i]];
		JTagMap.storeLatLngs[x.storeId] = new Array(x.latitude, x.longitude);
		JTagMap.addLatLngStore(x.latitude, x.longitude, x.storeId);
	}

	for(i in JTagMap.latLngStores) {
		for(j in JTagMap.latLngStores[i]) {
			if(JTagMap.latLngStores[i][j].length > 1) {
				if(JTagMap.latLngStores[i][j].length < 5) {
					x = JTagMap.calcPointsAroundLatLng(i, j, 4, JTagMap.latLngStores[i][j].length);
				}
				else {
					x = JTagMap.calcPointsAroundLatLng(i, j, 8, JTagMap.latLngStores[i][j].length);
				}
				for(k in JTagMap.latLngStores[i][j]) {
					JTagMap.storeLatLngs[JTagMap.latLngStores[i][j][k]][0] = x[k][0];
					JTagMap.storeLatLngs[JTagMap.latLngStores[i][j][k]][1] = x[k][1];
				}
			}
		}
	}

	for(i in JTagMap.storeLatLngs) {
		marker = JTagMap.createStoreMarker(JTagMap.storeLatLngs[i][0], JTagMap.storeLatLngs[i][1], i);
		JTagMap.storeMarkers[i] = marker;
		JTagMap.map.addOverlay(marker);
	}

	JTagMap.viewState = 'metro';
	JTagMap.currentMetroId = metroId;
	JTagMap.currentStoreId= 0;

	//Begin Window/Document work
	x = document.getElementById('storesmapintro');
	x.style.display = 'none';
	y = document.getElementById('storesmapstores');
	y.style.display = 'block';
	
	for(i in JTagMap.metroInfo) {
		x = JTagMap.metroInfo[i];
		y = document.getElementById('metro' + i);
		if(y) {
			y.className = 'inactive';
		}
	}

	y = document.getElementById('metro' + metroId);
	if(y) {
		y.className = 'active';
	}

	for(i in JTagMap.storeInfo) {
		x = document.getElementById('store' + i);
		if(x) {
			x.style.display = 'none';
			x.style.visibility = 'hidden';
		}
	}

	for(i in metro['stores']) {
		x = document.getElementById('store' + metro['stores'][i]);
		if(x) {
			x.style.display = 'block';
			x.style.visibility = 'visible';
		}
	}

	x = document.getElementById('storesmapstores');
	x.scrollTop = 0;

	for(i in JTagMap.storeMarkers) {
		x = JTagMap.storeMarkers[i].getIcon();
		y = document.getElementById('storeMarker' + i);
		if(y) {
			y.src = x.printImage;
			y.width = 20;
			y.height = 34;
			offset = $('#storeMarker'+i).offset();
			JTagMap.storeScrollers[i] = offset.top;
		}
	}
	
	x = document.getElementById('storesmapfiltername');
	x.innerHTML = ' &raquo; ' + '<a href="#" onclick="JTagMap.viewMetro(\'' + metroId+ '\', false); return false;">' + metro['name'] + '</a>';

	if(shouldUpdateHash) {
		JTagMap.updateHash();
	}

	window.scrollTo(0, 0);
};


//This is overall view, with markers at each metro area
JTagMap.viewMetros = 
function(shouldUpdateHash) {
	var bounds = new GLatLngBounds();
	var marker;
	var x;
	var y;

	JTagMap.viewState = 'overall';
	JTagMap.currentMetroId = 0;
	JTagMap.currentStoreId = 0;

	JTagMap.map.clearOverlays();
	JTagMap.map.setCenter(new GLatLng(0, 0), 0);

	for(i in JTagMap.metroInfo) {
		marker = JTagMap.createMetroMarker(i);
		bounds.extend(marker.getPoint());		
		JTagMap.map.addOverlay(marker);		
	}

	JTagMap.map.setZoom(JTagMap.map.getBoundsZoomLevel(bounds));
	var lat = (bounds.getNorthEast().lat() + bounds.getSouthWest().lat())/2;
	var lng = (bounds.getNorthEast().lng() + bounds.getSouthWest().lng())/2;
	JTagMap.map.setCenter(new GLatLng(lat,lng));

	//Begin Window/Document work
	x = document.getElementById('storesmapintro');
	x.style.display = 'block';
	y = document.getElementById('storesmapstores');
	y.style.display = 'none';
	
	for(i in JTagMap.metroInfo) {
		x = JTagMap.metroInfo[i];
		y = document.getElementById('metro' + i);
		if(y) {
			y.className = 'inactive';
		}
	}

	for(i in JTagMap.storeInfo) {
		x = JTagMap.storeInfo[i];
		y = document.getElementById('store' + i);
		z = document.getElementById('storeMarker' + i);
		if(y) {
			y.style.display = 'block';
			y.style.visibility = 'visible';
		}
		if(z) {
			z.src = '/images/maps/marker_blank.gif';
			z.width = 1;
			z.height = 1;
		}
	}

	x = document.getElementById('storesmapfiltername');
	x.innerHTML = '';

	x = document.getElementById('storesmapstores');
	x.scrollTop = 0;

	if(shouldUpdateHash) {
		JTagMap.updateHash();
	}

	window.scrollTo(0, 0);
};


//This function looks at the current map URL and decides
//which specific map (city/store) to display
JTagMap.viewMap = 
function() {
	var metroDrawn = false;
	var storeDrawn = false;
	//cant get this to work right in safari, anyway I try it
	if(navigator.userAgent.indexOf('Safari') == -1) {
		if(window.location.hash.length > 1) {
			var hash = window.location.hash.slice(1);
			var hashParts = hash.split('&');
			var i;
			for(i = 0; i < hashParts.length && i < 2; i++) {
				hashPart = hashParts[i].split('=');
				if(hashPart.length > 1) {
					if(hashPart[0] == 'm' && i == 0 && !metroDrawn) {
						JTagMap.viewMetro(hashPart[1], false);
						metroDrawn = true;
					}
					else if(hashPart[0] == 's' && i == 1 && metroDrawn && !storeDrawn) {
						JTagMap.viewStore(hashPart[1]);
						storeDrawn = true;
					}
				}
			}
		}
	}

	if(!metroDrawn && !storeDrawn) {
		JTagMap.viewMetros(false);
	}
	if(navigator.userAgent.indexOf('Safari') == -1) {
		JTagMap.expectedHash = window.location.hash;
	}
};
