/*
 * REI Store Locator JavaScript v1.1
 *
 * 1.1 Update provides functionality for the following:
 *		Store Hours
 *		Store Picture
 *		Terrain Maps
 *		Zoom level better for state view
 *		Store list formated better
 *
 * http://www.rei.com/
 *
 * Copyright (c) 2009 REI
 *
 * Author: Caleb Tonn
 *
 */

var map;
var gdir;
var geocoder;
var locations = new Array();
var sortedLocations = new Array();
var addressMarker;
	
function load() {
	if (GBrowserIsCompatible()) {
		geocoder = new GClientGeocoder();
		downloadGeoRss();
		
		$("#addressInput").keydown(function(event){
			if (event.keyCode == "13"){
				searchLocations();
			}
		});
		$("#stateInput").keydown(function(event){
			if (event.keyCode == "13"){
				searchLocations();
			}
		});
		$("#zipInput").keydown(function(event){
			if (event.keyCode == "13"){
				searchLocations();
			}
		});
	}
}

function downloadGeoRss() {
	var url = "/maps/reiStores";
	GDownloadUrl(url, function(data, responseCode) {
		var xml = GXml.parse(data);
		var titles = xml.documentElement.getElementsByTagName("title");
		var descriptions = xml.documentElement.getElementsByTagName("description");
		var street = xml.documentElement.getElementsByTagName("street");
		var city = xml.documentElement.getElementsByTagName("city");
		var state = xml.documentElement.getElementsByTagName("state");
		var zip = xml.documentElement.getElementsByTagName("zip");
		var link = xml.documentElement.getElementsByTagName("link");
		var phone = xml.documentElement.getElementsByTagName("phone");
		var lat = xml.documentElement.getElementsByTagName("lat");
		var long = xml.documentElement.getElementsByTagName("long");
		var storeHours = xml.documentElement.getElementsByTagName("storeHours");
		var stateRadius = xml.documentElement.getElementsByTagName("stateRadius");
		var html = new Array();
		var j = 0
		$(titles).each(function(i){
			var location = new Object();
			location.title = titles[i].childNodes[0].nodeValue;
			location.description = descriptions[i].childNodes[0].nodeValue;
			location.link = link[i].childNodes[0].nodeValue;
			location.phone = phone[i].childNodes[0].nodeValue;
			location.lat = lat[i].childNodes[0].nodeValue;
			location.lng = long[i].childNodes[0].nodeValue;
			location.street = street[i].childNodes[0].nodeValue;
			location.city = city[i].childNodes[0].nodeValue;
			location.state = state[i].childNodes[0].nodeValue;
			location.zip = zip[i].childNodes[0].nodeValue;
			location.storeHoursMF = storeHours[j].childNodes[0].nodeValue;
			location.storeHoursSat = storeHours[j+1].childNodes[0].nodeValue;
			location.storeHoursSun = storeHours[j+2].childNodes[0].nodeValue;
			location.stateRadius = stateRadius[i].childNodes[0].nodeValue;
			locations.push(location);
			j = j+3;
		});
		matchHash();
	});
}

function getStaticMap() {
	web = web = 'http://' + window.location.hostname + window.location.pathname;
	window.location = web;
}

function staticMapSelected(alt) {
	var Idaho = 'Idaho';
	var address = null;
	$('#staticMap').css('display','none');
	$('#staticMapTitle').css('display','none');
	$('#mapTitle').css('display','block');
	sortedLocations = new Array();
	map = new GMap2(document.getElementById('map'));
	map.addControl(new GLargeMapControl3D());
	map.addControl(new GMapTypeControl());
	map.setCenter(new GLatLng(40, -100), 3);
	//map.addMapType(G_PHYSICAL_MAP);
	map.removeMapType(G_HYBRID_MAP);
	map.removeMapType(G_SATELLITE_MAP);
	map.enableContinuousZoom();
	if (alt == 'ID') {
		address = Idaho;
	}
	else {
		address = alt;
	}
	geocoder.getLatLng(address, function(latlng) {
		if (!latlng) {
			alert(address + ' not found');
		} 
		else {
			showState(address, latlng.y, latlng.x, alt);
		}
	});
}

function showState(address, lat, lng, alt) {
	var searchedLocations = sortLocations(lat, lng, locations);
	searchedLocations.sort(compareTitle);
	var searchUrl = searchedLocations
	map.clearOverlays();
	var sidebar = document.getElementById('sidebar');
	sidebar.innerHTML = '';
	var radius = $('#radiusSelect').val();
	if (locations[0].distance > radius) {
		sidebar.innerHTML = 'No results found. You might try a larger search radius.';
		map.setCenter(new GLatLng(40, -100), 3);
		return;
	}
	var clickedState = alt;
	var bounds = new GLatLngBounds();
	var j = 0;
	$(searchedLocations).each(function(i){
		var name = searchedLocations[i].title;
		var address = searchedLocations[i].description;
		var distance = searchedLocations[i].distance;
		var link = searchedLocations[i].link;
		var phone = searchedLocations[i].phone;
		var street = searchedLocations[i].street;
		var city = searchedLocations[i].city;
		var state = searchedLocations[i].state;
		var zip = searchedLocations[i].zip;
		var storeHoursMF = searchedLocations[i].storeHoursMF;
		var storeHoursSat = searchedLocations[i].storeHoursSat;
		var storeHoursSun = searchedLocations[i].storeHoursSun;
		var point = new GLatLng(parseFloat(searchedLocations[i].lat),
		parseFloat(searchedLocations[i].lng));
		var marker = createMarker(point, name, address, link, phone, street, city, state, zip, storeHoursMF, storeHoursSat, storeHoursSun, j);
		if (address.match(clickedState) != null) {
			j+1;
			map.addOverlay(marker);
			var sidebarEntry = createSidebarEntryStatic(marker, name, address, phone, street, city, state, zip, j, link);
			sidebar.appendChild(sidebarEntry);
			bounds.extend(point);
		}
		else if (clickedState == 'DC') {
			map.addOverlay(marker);
			var sidebarEntry = createSidebarEntryStatic(marker, name, address, phone, street, city, state, zip, j, link);
			sidebar.appendChild(sidebarEntry);
			bounds.extend(point);
			j+1;
		}
		
	});
	bounds.extend(new GLatLng(lat, lng));
	map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds)), map.zoomOut();
}

function compareTitle(a, b) {
	var titleA = a.title.toLowerCase( );
	var titleB = b.title.toLowerCase( );
	if (titleA < titleB) {return -1}
	if (titleA > titleB) {return 1}
	return 0;
}

function searchLocations() {
	$('#staticMap').css('display','none');
	$('#staticMapTitle').css('display','none');
	$('#mapTitle').css('display','block');
	sortedLocations = new Array();
	map = new GMap2(document.getElementById('map'));
	map.addControl(new GLargeMapControl3D());
	map.addControl(new GMapTypeControl());
	map.setCenter(new GLatLng(40, -100), 3);
	//map.addMapType(G_PHYSICAL_MAP);
	map.removeMapType(G_HYBRID_MAP);
	map.removeMapType(G_SATELLITE_MAP);
	map.enableContinuousZoom();
	var address = null;
	var street = $('#addressInput').val();
	var state = $('#stateInput').val();
	var zip = $('#zipInput').val();
	if (!street==true && !state==true && !zip==false){
		geocoder.getLatLng(zip, function(latlng) {
			if (!latlng) {
				alert(zip + ' not found');
			} 
			else {
				if ($('#radiusSelect').val() < 50){
					$('#radiusSelect').val(50);
				}
				address = zip;
				showDistances(address, latlng.y, latlng.x);
			}
		});
	}
	else if (!street==true && !state==false && !zip==true){
		if ($('#radiusSelect').val() < 200){
			$('#radiusSelect').val(319);
		}
		geocoder.getLatLng(state, function(latlng) {
			if (!latlng) {
				alert(zip + ' not found');
			} 
			else {
				address = state;
				showDistances(address, latlng.y, latlng.x);
			}
		});
	}
	else {
		geocoder.getLatLng(street +' '+ state +' '+ zip, function(latlng) {
			if (!latlng) {
				alert(street +' '+ state +' '+ zip + ' not found');
			} 
			else {
				address = street +' '+ state +' '+ zip;
				showDistances(address, latlng.y, latlng.x);
			}
		});
	}

	
}

function showDistances(address, lat, lng) {
	var searchedLocations = sortLocations(lat, lng, locations);
	var searchUrl = searchedLocations
	map.clearOverlays();
	var sidebar = document.getElementById('sidebar');
	sidebar.innerHTML = '';
	var radius = $('#radiusSelect').val();
	if (locations[0].distance > radius) {
		sidebar.innerHTML = 'No results found. You might try a larger search radius.';
		map.setCenter(new GLatLng(40, -100), 3);
		return;
	}
	var bounds = new GLatLngBounds();
	var j = 0;
	for (var i = 0; i < searchedLocations.length; i++) {
		var name = searchedLocations[i].title;
		var address = searchedLocations[i].description;
		var distance = searchedLocations[i].distance;
		var link = searchedLocations[i].link;
		var phone = searchedLocations[i].phone;
		var street = searchedLocations[i].street;
		var city = searchedLocations[i].city;
		var state = searchedLocations[i].state;
		var zip = searchedLocations[i].zip;
		var storeHoursMF = searchedLocations[i].storeHoursMF;
		var storeHoursSat = searchedLocations[i].storeHoursSat;
		var storeHoursSun = searchedLocations[i].storeHoursSun;
		var point = new GLatLng(parseFloat(searchedLocations[i].lat),parseFloat(searchedLocations[i].lng));
		var marker = createMarker(point, name, address, link, phone, street, city, state, zip, storeHoursMF, storeHoursSat, storeHoursSun, i);
		map.addOverlay(marker);
		var sidebarEntry = createSidebarEntry(marker, name, address, distance, phone, street, city, state, zip, j, link);
		sidebar.appendChild(sidebarEntry);
		bounds.extend(point);
		j + 1;
	}
	bounds.extend(new GLatLng(lat, lng));
	map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds)), map.zoomOut();
}

function sortLocations(lat, lng, locations) {
	var radius = $('#radiusSelect').val();
	var UPPER_BOUND = radius;
	$(locations).each(function(i){
		locations[i].distance = distance(lat, lng, locations[i].lat, locations[i].lng, "M");
	});
	locations.sort(compareDistance);
	var prevDistance = 0;
	var index = 0;
	$(locations).each(function(i){
		var minDistance = UPPER_BOUND;
		$(locations).each(function(j){
			if((locations[j].distance < minDistance) && (locations[j].distance > prevDistance)) {
				minDistance = locations[j].distance; 
				index = j;
				sortedLocations.push(locations[index]);
			}
		});
		prevDistance = locations[index].distance;
	});
	return sortedLocations;
}

function compareDistance(a, b) {
	return a.distance - b.distance;
}

function distance(lat1, lon1, lat2, lon2, unit) {
	var radlat1 = Math.PI * lat1/180
	var radlat2 = Math.PI * lat2/180
	var radlon1 = Math.PI * lon1/180
	var radlon2 = Math.PI * lon2/180
	var theta = lon1-lon2
	var radtheta = Math.PI * theta/180
	var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
	dist = Math.acos(dist)
	dist = dist * 180/Math.PI
	dist = dist * 60 * 1.1515
	if (unit=="K") { dist = dist * 1.609344 }
	if (unit=="N") { dist = dist * 0.8684 }
	return dist
} 

function createMarker(point, name, address, link, phone, street, city, state, zip, storeHoursMF, storeHoursSat, storeHoursSun, j) {
	var number = j + 1;
	var reiIcon = new GIcon(G_DEFAULT_ICON);
		// Create our REI marker icon
		reiIcon.image = "/pix/maps/rei_icon.png";
		reiIcon.iconSize = new GSize(23, 31);
		reiIcon.iconAnchor = new GPoint(11, 31);
		reiIcon.shadow = "/pix/maps/rei_icon-shadow.png";
		reiIcon.shadowSize = new GSize(42, 31);
	
		// Set up our GMarkerOptions object
		markerOptions = { icon:reiIcon };
	var storeNumber = link.substr(26);
	var marker = new GMarker(point, markerOptions);
	var html = '<div style="width:340"><div style="float:left; margin-right:10px;"><b>' + '<a href="' + link + '">' + name + ' REI Store</a>' + '</b> <br/>' +  street + '<br/>'  + city + ', ' + state + ' ' + zip + '<br/>' + phone + '<br/><a href="/map/store/' + storeNumber + '">Get Directions</a><br/><br/>' + '<b>Store Hours:</b><ul><li>'+storeHoursMF+'</li><li>'+storeHoursSat+'</li><li>'+storeHoursSun+'</li></ul><a href="/stores/store_events.jsp?store=' + storeNumber + '">Store Events</a><br/><a href="/stores/' + storeNumber + '">More About this REI Store</a><br/><br/></div>' + '<a href="' + link + '"><img style="float:right" src="http://www.rei.com/pix/stores/storePictures/email/'+storeNumber+'.jpg" height="127" width="127" border="0" /></a></div>';
		
	GEvent.addListener(marker, 'mouseover', function() {
		marker.openInfoWindowHtml(html);
	});
	number ++;
	return marker;
}

function createMarkerStore(point, name, address, link, phone, street, city, state, zip, storeHoursMF, storeHoursSat, storeHoursSun, j) {
	var number = j + 1;
	var reiIcon = new GIcon(G_DEFAULT_ICON);
		// Create our REI marker icon
		reiIcon.image = "/pix/maps/rei_icon.png";
		reiIcon.iconSize = new GSize(23, 31);
		reiIcon.iconAnchor = new GPoint(11, 31);
		reiIcon.shadow = "/pix/maps/rei_icon-shadow.png";
		reiIcon.shadowSize = new GSize(42, 31);
		
		// Set up our GMarkerOptions object
		markerOptions = { icon:reiIcon };
	
	var storeNumber = link.substr(26);
	var marker = new GMarker(point, markerOptions);
	var html = '<div style="width:340"><div style="float:left; margin-right:10px;"><b>' + '<a href="' + link + '">' + name + '</a>' + '</b> <br/>' +  street + '<br/>'  + city + ', ' + state + ' ' + zip + '<br/>' + phone + '<br/><a href="/map/store/' + storeNumber + '">Get Directions</a><br/><br/>' + '<b>Store Hours:</b><ul><li>'+storeHoursMF+'</li><li>'+storeHoursSat+'</li><li>'+storeHoursSun+'</li></ul><a href="/stores/store_events.jsp?store=' + storeNumber + '">Store Events</a><br/><a href="/stores/' + storeNumber + '">More About this REI Store</a><br/><br/></div>' + '<a href="' + link + '"><img style="float:right" src="http://www.rei.com/pix/stores/storePictures/email/'+storeNumber+'.jpg" height="127" width="127" border="0" /></a></div>';

	GEvent.addListener(marker, 'mouseover', function() {
		marker.openInfoWindowHtml(html);
	});
	number ++;
	return marker;
}

function createSidebarEntryStatic(marker, name, address, phone, street, city, state, zip, j, link) {
	var div = document.createElement('div');
	var number = j+1;
	var storeNumber = link.substr(26);
	var html = '<div class="addressList"><a href="/stores/' + storeNumber + '"><b class="storeName">' + name + ' REI Store</b></a><br/>' + street + '<br/>' + city + ', ' + state + ' ' + zip + '<br/>' + phone + '<br/><a href="/map/store/' + storeNumber + '">Get Directions</a></div><div class="linkList">' + '</div>' + '<div style="clear: both"></div>';
	div.innerHTML = html;
	div.style.paddingTop = '10px';
	div.style.paddingBottom = '10px';
	div.style.paddingLeft = '5px';
	/*GEvent.addDomListener(div, 'click', function() {
		GEvent.trigger(marker, 'click');
	});
	GEvent.addDomListener(div, 'mouseover', function() {
		div.style.backgroundColor = 'pink';
	});
	GEvent.addDomListener(div, 'mouseout', function() {
		div.style.backgroundColor = 'green';
	});*/
	return div;
}

function createSidebarEntry(marker, name, address, distance, phone, street, city, state, zip, j, link) {
	var miles = distance.toFixed(1);
	var div = document.createElement('div');
	var number = j+1;
	var storeNumber = link.substr(26);
	var html = '<div class="addressList"><a href="/stores/' + storeNumber + '"><b class="storeName">' + name + ' REI Store</b> (' + miles + ') miles</a>' +'<br/>' + street + '<br/>' + city + ', ' + state + ' ' + zip + '<br/>' + phone + '<br/><a href="/map/store/' + storeNumber + '">Get Directions</a></div><div class="linkList">' + '</div>' + '<div style="clear: both"></div>';
	div.innerHTML = html;
	div.style.paddingTop = '10px';
	div.style.paddingBottom = '10px';
	div.style.paddingLeft = '5px';
	/*GEvent.addDomListener(div, 'click', function() {
		GEvent.trigger(marker, 'click');
	});
	GEvent.addDomListener(div, 'mouseover', function() {
		div.style.backgroundColor = '#eee';
	});
	GEvent.addDomListener(div, 'mouseout', function() {
		div.style.backgroundColor = '#fff';
	});*/
	return div;
}

function matchHash () {
	hash = parseInt(window.location.hash.substr(1));
	search = parseInt(location.pathname.substr(11));
	stateHash = window.location.hash.substr(1);
	map = new GMap2(document.getElementById('map'));
	gdir = new GDirections(map, document.getElementById("directions"));
	GEvent.addListener(gdir, "error", handleErrors);
	map.addControl(new GLargeMapControl3D());
	map.addControl(new GMapTypeControl());
	map.setCenter(new GLatLng(40, -100), 3);
	//map.addMapType(G_PHYSICAL_MAP);
	map.removeMapType(G_HYBRID_MAP);
	map.removeMapType(G_SATELLITE_MAP);
	map.enableContinuousZoom();
	if (isNaN(search)==false){
		for (var i = 0; i < locations.length; i++) {
			var storeNumber = parseInt(locations[i].link.substr(26));
			if (storeNumber == search){
				var name = locations[i].title;
				var address = locations[i].description;
				var distance = locations[i].distance;
				var link = locations[i].link;
				var phone = locations[i].phone;
				var street = locations[i].street;
				var city = locations[i].city;
				var state = locations[i].state;
				var zip = locations[i].zip;
				var storeHoursMF = locations[i].storeHoursMF;
				var storeHoursSat = locations[i].storeHoursSat;
				var storeHoursSun = locations[i].storeHoursSun;
				var point = new GLatLng(parseFloat(locations[i].lat),parseFloat(locations[i].lng));
				map.clearOverlays();
				var marker = createMarkerStore(point, name, address, link, phone, street, city, state, zip, storeHoursMF, storeHoursSat, storeHoursSun, i, storeNumber);
				var html = '<div style="width:340"><div style="float:left; margin-right:10px;"><b>' + '<a href="' + link + '">' + name + ' REI Store</a>' + '</b> <br/>' +  street + '<br/>'  + city + ', ' + state + ' ' + zip + '<br/>' + phone + '<br/><a href="/map/store/' + storeNumber + '">Get Directions</a><br/><br/>' + '<b>Store Hours:</b><ul><li>'+storeHoursMF+'</li><li>'+storeHoursSat+'</li><li>'+storeHoursSun+'</li></ul><a href="/stores/store_events.jsp?store=' + storeNumber + '">Store Events</a><br/><a href="/stores/' + storeNumber + '">More About this REI Store</a><br/><br/></div>' + '<a href="' + link + '"><img style="float:right" src="http://www.rei.com/pix/stores/storePictures/email/'+storeNumber+'.jpg" height="127" width="127" border="0" /></a></div>';
				map.addOverlay(marker);
				map.setCenter(point, 15);
				marker.openInfoWindowHtml(html);
				$('#mapTitle').append(name + ' Store');
				$('#storeAddressTitle').append(name + " REI Store");
				$('#storeAddress').append(street + "<br/>" + city + ", " + state + " " + zip + "<br/>" + phone + "<br/>");
                                                           $('#storeAddressTitle2').append(name + " REI Store");
                                                           $('#storeAddressTitle3').append(name + " REI Store");
				$('#storeAddress2').append(street + "<br/>" + city + ", " + state + " " + zip + "<br/>" + phone + "<br/>");				
				$('#storeLink').append('Visit our <a href="/stores/' + storeNumber + '">' + name + ' store page</a> for hours, events and more.');
				$('#storeForm').append('<div class="findStore findStoreForm"><fieldset style="border:0px solid #fff;"><ol><li><label for="streetInput">Street</label><input type="text" class="field streetField" size="30" id="streetInput"/></li><li><label for="addressInput">City</label><input type="text" class="field cityField" size="30" id="addressInput"/></li><li class="liStyle0"><label for="stateInput">State</label><input type="text" class="field stateField" size="3" id="stateInput"/></li><li class="liStyle1"><label class="zip" for="zipInput">Zip</label><input type="text" class="field zipField" size="6" id="zipInput"/></li><li class="finderBtn"><div id="finderFormButton" class="button" style="display: none;"><input type="submit" value="get directions"/></div><div style="display: block;" id="finderCssButton" class="button"><script type="text/javascript">document.getElementById("finderFormButton").style.display="none";document.getElementById("finderCssButton").style.display="block";</script><a onclick="conForm();" href="#" class="btnStyle1"><span>get directions</span></a></div></li></ol></fieldset></div><input type="hidden" size="25" id="toAddress" name="to" value="' + locations[i].lat + ',' + locations[i].lng + '">');
				$('#breadcrumbs').append('<a href="/stores/' + storeNumber + '">'+ name +' store page</a>');
				document.title = 'REI ' + name + ' Store: Map and Directions';
			}
		}
	}
	else if (isNaN(hash)==false){
		var address = hash;
		var radius = $('#radiusSelect').val();
		
		$('#staticMap').css('display','none');
	    $('#staticMapTitle').css('display','none');
	    $('#mapTitle').css('display','block');
		//$('#staticMap').css('display','none');
		radius = 319;
		geocoder.getLatLng(address, function(latlng) {
			if (!latlng) {
				alert(address + ' not found');
			} 
			else {
				showDistances(address, latlng.y, latlng.x);
			}
		});
	}
	else if (isNaN(stateHash)==true){
		alt = stateHash;
		states = document.getElementById('Map').areas;
		if (alt == 'DC') {
			document.getElementById('radiusSelect').value = 50;
			staticMapSelected(alt);
		}
		else {
			document.getElementById('radiusSelect').value = 500;
			staticMapSelected(alt);
		}
	}
}

function conForm() {
	var street = $("#streetInput").val();
	var city = $("#addressInput").val();
	var state = $("#stateInput").val();
	var zip = $("#zipInput").val();
	var conFromValue = street + " " + city + " " + state + " " + zip;
	var toAddress = $("#toAddress").val();
	setDirections(conFromValue, toAddress);
	$('#storeForm').hide();
	map.closeInfoWindow();
	$('#startingPoint').append('<a href="#" onClick="window.location.reload()">Select a new starting point</a>:')
}

function setDirections(fromAddress, toAddress) {
	gdir.load("from: " + fromAddress + " to: " + toAddress);
}


function handleErrors(){
	if (gdir.getStatus().code == G_GEO_UNKNOWN_ADDRESS)
	alert("No corresponding geographic location could be found for one of the specified addresses. This may be due to the fact that the address is relatively new, or it may be incorrect.\nError code: " + gdir.getStatus().code);
	else if (gdir.getStatus().code == G_GEO_SERVER_ERROR)
	alert("A geocoding or directions request could not be successfully processed, yet the exact reason for the failure is not known.\n Error code: " + gdir.getStatus().code);
	
	else if (gdir.getStatus().code == G_GEO_MISSING_QUERY)
	alert("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: " + gdir.getStatus().code);
	
	else if (gdir.getStatus().code == G_GEO_BAD_KEY)
	alert("The given key is either invalid or does not match the domain for which it was given. \n Error code: " + gdir.getStatus().code);
	
	else if (gdir.getStatus().code == G_GEO_BAD_REQUEST)
	alert("A directions request could not be successfully parsed.\n Error code: " + gdir.getStatus().code);
	
	else alert("An unknown error occurred.");
}