jQuery(document).ready(function($) {
	try {
    console.assert(1);
} catch(e) {
    if (typeof loadFirebugConsole == 'function') {
         loadFirebugConsole();
    }  else {
        console = {
            log: function() {},
            debug: function() {},
            info: function() {},
            warn: function() {},
            assert: function() {}
        }
    }
}
	initSearchableMap();
});

var options = {
	maxDistance 	: 1000, // distance in miles, filtered results will not display on map if they are further away
	startLat		: 42.350933, // on load the map will center at this latitude
	startLng		: -71.05751, // on load the map will center at this longitude
	cssName			: "name", // CSS class on item that wraps location Name information
	cssAddress		: "address", // CSS class that wraps location Address
	cssDescription	: "description", // CSS class that wraps location Description
	cssService		: "service" // CSS class that wraps location Services
}

function initSearchableMap() {
	
	parseHTML();
	initGoogleStuff();
	buildFilterControls();
	
	// Added By Jim Faulkner
	preloadGoogleMarkers();
	
	var zip = getQueryString("zip");
	if(zip) {
		SubmitQuery(zip);
		//addMarkers(true);
	}
}


var locCounter = 0;
var curFilterLocs = new Array();

//--------------------------------------------------------------------------------
// BEGIN CODE ADDED
//--------------------------------------------------------------------------------

var MARKER_LETTERS   = new Array("A", "B", "C", "D", "E", "F", "G", "H", "I", "J");
var MarkerLetterIcon = new Array(MARKER_LETTERS.length);
var ZipCodePoint     = null;

//--------------------------------------------------------------------------------
// preloadGoogleMarkers - function to preload and cache the Google A-J markers   
//--------------------------------------------------------------------------------
function preloadGoogleMarkers() {

	var shadowIcon = new GIcon(G_DEFAULT_ICON);
	
	shadowIcon.shadow           = 'http://www.google.com/mapfiles/shadow50.png';
	shadowIcon.iconSize         = new GSize(20, 34);
	shadowIcon.shadowSize       = new GSize(37, 34);
	shadowIcon.iconAnchor       = new GPoint(9, 34);
	shadowIcon.infoWindowAnchor = new GPoint(9, 2);
					
	for (var index = 0; index < MARKER_LETTERS.length; index++) {
		var letterIcon = new GIcon(shadowIcon);
		
		letterIcon.image = 'http://www.google.com/mapfiles/marker' + MARKER_LETTERS[index] + '.png';	
		
		MarkerLetterIcon[index] = letterIcon;
	}
}

//--------------------------------------------------------------------------------
// END CODE ADDED
//--------------------------------------------------------------------------------



var locationLookup = new Array();
var filters = new Array();

// pass in a parameter with the querystring to retrieve
// parse url and return value of query
function getQueryString(arg) {
	var qsParm = new Array();
	var query = window.location.search.substring(1);
	var parms = query.split('&');
	for (var i=0; i<parms.length; i++) {
		var pos = parms[i].indexOf('=');
		if (pos > 0) {
			var key = parms[i].substring(0,pos);
			var val = parms[i].substring(pos+1);
			qsParm[key] = val;
		}
	}
	
	return qsParm[arg];
}

// Build form controls used to filter results
function buildFilterControls() {
	var f = $j("#filters");

	// add filter options
	for(var filter in filters) {
		id = "filter-"+filter;
		displayName = filters[filter].displayName;
		
		f.append("<label><input id='"+id+"' name='filter' type='radio' />" + displayName + "</label>");
	}
	
	// add view all button
	f.append("<a href='#' id='view-all-loc'>View all locations</a>");
	$j("#view-all-loc").click(function() {
		addMarkers(true);
		return false;
	});
}


// Determine which locations should be added to the map
function addMarkers(all, localOnly) {
	all       = false || all;
	localOnly = false || localOnly;
	
	curFilterLocs = new Array();
	
	// Add new markers
	if(all) {	
		for (var i in locationLookup) {
			curFilterLocs.push(locationLookup[i]);
		}	
	}
	else {
		if($j(":radio:checked").length > 0) {
			$j(":radio:checked").each(function() {
				x = $j(this).attr("id").replace("filter-", "");
				curFilterLocs = filters[x].getLocations();
			});
		}
		else {
			for (var i in locationLookup) {
				curFilterLocs.push(locationLookup[i]);
			}
		}
	}
	
	gMap.clearOverlays();
	locCounter = 0;

	// If local, we need to grab the closest 10 locations and show them
	if (localOnly && gCGeo) {
		callNextDistance();
	}
	else {		
		callNextAddress();
	}
}

function callNextDistance() {
	if (locCounter < curFilterLocs.length) {
		
		var point = curFilterLocs[locCounter].point;
		if (point) {
			var distance = gMap.getCenter().distanceFrom(point);
			curFilterLocs[locCounter].setDistanceFromZip(distance);
		}
		
		locCounter++;
		callNextDistance();
	}
	else {
		// Here we need to show the 10 closest locations
		curFilterLocs.sort(function(a,b){return a.distanceFromZip - b.distanceFromZip});
		
		var maxResults   = (curFilterLocs.length > 9 ? 10 : curFilterLocs.length); 
		var leftColHTML  = '';
		var rightColHTML = '';
		
		for (var x = 0; x < maxResults; x++) {
			setAddressForDistanceMarker(curFilterLocs[x], x);
		}
	}
}

function setAddressForDistanceMarker(loc, markerLetterIndex) {

	markerOptions = {icon: MarkerLetterIcon[markerLetterIndex]}
	var marker = new GMarker(loc.point, markerOptions);
			
	GEvent.addListener(marker, "click", function() {
			var html = buildInfoHTML(loc, userAddress)
			this.openInfoWindowHtml(html, {maxWidth : 350});
		}
	);
	
	gMap.addOverlay(marker);
}

function callNextAddress() {
	if(locCounter < curFilterLocs.length) {
		setAddress(curFilterLocs[locCounter]);
	}
}

// Given an address convert to latLng()
// call addMarker
function setAddress(loc) {
	if(loc.point) {
		var marker = new GMarker(loc.point);
		
		GEvent.addListener(marker, "click", function() {
				var html = buildInfoHTML(loc, userAddress)
				this.openInfoWindowHtml(html, {maxWidth : 350});
			}
		);

		gMap.addOverlay(marker);
	}
	locCounter++;
	callNextAddress();
}


// HTML that appears in popup info box when user clicks on a location
function buildInfoHTML(loc, from) {
	var html = loc.description;
	html = "<div class='infobox'> <h3>"+loc.displayName+"</h3><div>" + html;
	if(userAddress != "") {
		html += "<a href='http://maps.google.com/maps?daddr=" + loc.point.toUrlValue() + "&amp;saddr="+ from +"'>Get directions</a><br />";
	}
	else {
		html += "<a href='http://maps.google.com/maps?daddr=" + loc.point.toUrlValue() + "'>directions</a><br />";
	}
	html += "</div></div>";
	return html;
}

// Parse the existing HTML and replace with Google Map
function parseHTML() {
	buildFilters();
	$j("#gmap-placeholder > #locations > li").each(function() {

		var name = $j(this).children("." + options.cssName).text();
		var address = $j(this).children("." + options.cssAddress).text();
		var description = $j(this).children("." + options.cssDescription).html();

		var loc = new Location(name, address, description);
		locationLookup[name] = loc;

		$j(this).find("." + options.cssService).each(function() {
			var filterName = $j(this).text();
			var filterId = stripSpecial(filterName);
			var f;
			
			if(filters[filterId]) {
				f = filters[filterId];
				f.addLocation(loc);
			}
		});
	});
	
	// Write the HTML that will hold the map and filters
	$j("#gmap-placeholder").html(			
	"<div id='search'><p>To find the Shields location closest to you, enter your zipcode:</p><div id='searchform'></div><div id='filters'><h3>Advanced Search Options</h3><p>To refine your search, please select a service:</p></div></div><div id='map'></div><div id='distlocs' name='distlocs'><div><div id='leftcol' name='leftcol' style='width: 242px; float: left; margin-left: 5px; margin-right: 5px;'></div><div id='rightcol' name='rightcol' style='width: 242px; float: left; margin-left: 5px; margin-right: 5px;'></div></div></div>"
	);
}

// Reads list of services from #services-offered, then build a filter for each
function buildFilters() {
	$j("#gmap-placeholder > #services-offered > ul > li").each(function() {
		var filterName = $j(this).text();
		var filterId = stripSpecial(filterName);

		var f;
		
		if(filters[filterId]) {
			f = filters[filterId]	
		}
		else {
			f = new Filter(filterName);
			filters[filterId] = f;
		}
	});
}

// Creates a new Filter object
// Each filter has a name and can contain several locations
function Filter(dName) {
	var locations = new Array();

	this.id = stripSpecial(dName);
	this.displayName = dName;
	this.addLocation = function(loc) {
		locations.push(loc);
	};
	this.getLocations = function() {
		return locations;
	};
}

// Creates a new Location object
// A location contains a name, address, and description
function Location(displayName, address, description) {
	var l = this;
	
	var latLng = address.split(',');
	var lat = latLng[0];
	var lng = latLng[1];
	
	this.address = address;
	this.displayName = displayName;
	this.description = description;
	this.distanceFromZip = 999999999;
	this.point = new GLatLng(lat, lng);
	
	this.setDistanceFromZip = function(distance) { l.distanceFromZip = distance; }
}

// Remove any crazy characters
function stripSpecial(text) {
	text = new String(text);	
	return text.replace(/[^a-zA-Z 0-9]+/g,'').replace(/ /g,'');
}


/*********************************************
	Begin Google Map Code
*********************************************/

google.load('search', '1');
google.load('maps', '2.x');

var metersInMile = 1609.344;

// Our global state
var gLocalSearch;
var gMap;
var gSelectedResults = [];
var gCurrentResults = [];
var gSearchForm;
var gCGeo;
var userAddress;
var swPoint;
var nePoint;

// Set up the map and the local searcher.
function initGoogleStuff() {
	gSearchForm = new google.search.SearchForm(false, document.getElementById("searchform"));
	gSearchForm.setOnSubmitCallback(null, CaptureForm);
	gSearchForm.input.focus();

	// Initialize the map
	gMap = new google.maps.Map2(document.getElementById("map"));
	gMap.enableScrollWheelZoom();
	gMap.addControl(new google.maps.LargeMapControl());
	gMap.addControl(new google.maps.MapTypeControl());
	gMap.setCenter(new google.maps.LatLng(options.startLat, options.startLng), 10);
	gCGeo = new GClientGeocoder();

	// Initialize the local searcher
	gLocalSearch = new google.search.LocalSearch();
	gLocalSearch.setCenterPoint(gMap);
	gLocalSearch.setSearchCompleteCallback(null, OnLocalSearch);
	
	$j("body").unload(GUnload);
}

// Called when Local Search results are returned, we clear the old
// results and load the new ones.
function OnLocalSearch() {
	
	if (!gLocalSearch.results) return;
	// Clear the map
	for (var i = 0; i < gCurrentResults.length; i++) {
		gMap.removeOverlay(gCurrentResults[i].marker());
	}
	
	gCurrentResults = [];
	for (var i = 0; i < gLocalSearch.results.length; i++) {
		gCurrentResults.push(new LocalResult(gLocalSearch.results[i]));
	}

	// move the map to the first result
	var first = gLocalSearch.results[0];
	if(first) {
		gMap.panTo(new google.maps.LatLng(first.lat, first.lng));
	}
}

// Cancel the form submission, executing an AJAX Search API search.
function CaptureForm(searchForm) {
	userAddress = searchForm.input.value;
	gLocalSearch.setCenterPoint(userAddress);
	gLocalSearch.execute(searchForm.input.value);

	// Modified by Jim Faulkner
	if (userAddress.length < 4) {
		addMarkers();
	}
	else {
		// Here we need to get the local results
		addMarkers(false, true);
	}
		
	return false;
}

// Pass in a string and submit search request to Google
function SubmitQuery(arg) {
	userAddress = arg;
	gLocalSearch.setCenterPoint(userAddress);
	gLocalSearch.execute(arg);
	//addMarkers(false, true);
	for (var i in locationLookup) {
		curFilterLocs.push(locationLookup[i]);
	}	
	callNextDistance();
	return false;
}

// A class representing a single Local Search result returned by the
// Google AJAX Search API.
function LocalResult(result) {
	this.result_ = result;
	this.resultNode_ = this.unselectedHtml();
	gMap.addOverlay(this.marker());
}

// Returns the GMap marker for this result, creating it with the given
// icon if it has not already been created.
LocalResult.prototype.marker = function(opt_icon) {
	if (this.marker_) return this.marker_;
	var marker = new google.maps.Marker(new google.maps.LatLng(parseFloat(this.result_.lat),
	                                   parseFloat(this.result_.lng)), opt_icon);
	GEvent.bind(marker, "click", this, function() {
	  marker.openInfoWindow(this.unselectedHtml());
	});
	this.marker_ = marker;
	return marker;
}

// Returns the HTML we display for a result before it has been "saved"
LocalResult.prototype.unselectedHtml = function() {
	var container = document.createElement("div");
	container.appendChild(this.result_.html.cloneNode(true));
	return container;
}