////////////////////////////////////////////////////////////////////////////////////////////
// This script is concieved and created by Jesse Schulman (http://year2032.com). (c) 2006
// He cut and pasted a lot from others. Feel free to use this script in any way you like.
//
// This program is free software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the Free Software Foundation;
// either version 2 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE.  See the GNU General Public License for more details.
//
// http://www.gnu.org/licenses/gpl.html
//
// Modifications made by Michael Woods, August 2007
//
////////////////////////////////////////////////////////////////////////////////////////////
var spb_map = null;
function load(xmlFileName)
{
	spb_map = new NJSPBMap('spb_map', 'map', 'map_sidebar');
	spb_map.load(xmlFileName);
}
/***
 * Class NJSPBMapLocation
 ***/
function NJSPBMapLocation(ordinal, marker, fromHtml, toHtml, infoWindowHtml)
{
	var ordinal = ordinal;
	var marker = marker;
	var fromHtml = fromHtml;
	var toHtml = toHtml;
	var infoWindowHtml = infoWindowHtml;

	this.getOrdinal = function()	{ return ordinal; };
	this.getMarker = function() 	{ return marker; };
	this.getFromHtml = function()	{ return fromHtml; };
	this.getToHtml = function()		{ return toHtml; };
	this.getInfoWindowHtml = function() { return infoWindowHtml; };
}
/***
 * Class NJSPBMap
 ***/
/***
 * NJSPBMap static DefaultColors
 ***/
NJSPBMap.DefaultColors = [ 'red', 'orange', 'yellow', 'green',  'purple', 'white', 'gray', 'black' ];
/***
 * NJSPBMap class def
 ***/
function NJSPBMap(mapObjId, mapPanelId, mapSidebarId)
{
	/***
	 * Private class fields
	 ***/
	var iconLookup = [];
	var baseIcon = null;

	var locations = [];
	var map = '';

	var sidebar_html = '';
	var allowedBounds = '';

	var mapObjId = mapObjId;

	var request = GXmlHttp.create();
	var allowedBounds = new GLatLngBounds(new GLatLng(39,-76), new GLatLng(41,-73.5));

	var mapPanel = document.getElementById(mapPanelId);
	var mapSidebar = document.getElementById(mapSidebarId);

	var imgPath = "map";
	var CO_addr = "171 Jersey Street, Trenton, NJ 08611";
	/***
	 *	<div class='infowindow'>
	 *		<a href='http://www.year2032.com' target='_blank'>Created by Jesse Schulman (c) 2006</a>
	 *	</div>
	 ***/
	var ji = '<div class="location_info"><div class="location_info_item"><a href="http://www.year2032.com" target="_blank">Created by Jesse Schulman (c) 2006</a></div></div>';
	var mi = '<div class="location_info"><div class="location_info_item"><a href="mailto:mikeswoods@gmail.com?subject=What do you think?">Also created by Mike Woods (c) 2007</div></div>';
	/***
	 * PUBLIC METHOD :- getMapObjectId
	 *
	 ***/
	this.getMapObjectId = function()
	{
		return mapObjId;
	};
	/***
	 * PUBLIC METHOD :- zoomIn(i)
	 *   Zoom-In method using Geocode point only.
	 ***/
	this.zoomIn = function(i)
	{
		map.setCenter(locations[i].getMarker().point, 14);
	};
	/***
	 * PUBLIC METHOD :- zoomOut()
	 *   Zoom-Out method using Geocode point only.
	 ***/
	this.zoomOut = function(i)
	{
		//Return to starting point.
		map.setCenter(locations[i].getMarker().point, 8);
	};
	/***
	 * PUBLIC METHOD :- showInfo(i)
	 *   This Function picks up the click and opens the corresponding info window -
	 ***/
	this.showInfo = function(i)
	{
		var loc = locations[i];
		var marker = loc.getMarker();
		marker.openInfoWindowHtml(loc.getInfoWindowHtml());
	};
	/***
	 * PUBLIC METHOD :- toHere(i)
	 *   Methods that open the directions forms -
	 ***/
	this.toHere = function(i)
	{
		var loc = locations[i];
		var marker = loc.getMarker();
		marker.openInfoWindowHtml(loc.getToHtml());
	};
	/***
	 * PUBLIC METHOD :- fromHere(i)
	 *   Methods that open the directions forms -
	 ***/
	this.fromHere = function(i)
	{
		var loc = locations[i];
		var marker = loc.getMarker();
		marker.openInfoWindowHtml(loc.getFromHtml());
	};
	/***
	 * PRIVATE METHOD :- checkBounds()
	 *   Function If the map position is out of range, move it back -
	 ***/
	var checkBounds = function()
	{
		// Perform the check and return if OK
		if (allowedBounds.contains(map.getCenter()))
			return;
		// It`s not OK, so find the nearest allowed point and move there
		var C = map.getCenter();
		var X = C.lng();
		var Y = C.lat();
		var AmaxX = allowedBounds.getNorthEast().lng();
		var AmaxY = allowedBounds.getNorthEast().lat();
		var AminX = allowedBounds.getSouthWest().lng();
		var AminY = allowedBounds.getSouthWest().lat();
		if (X < AminX) {X = AminX;}
		if (X > AmaxX) {X = AmaxX;}
		if (Y < AminY) {Y = AminY;}
		if (Y > AmaxY) {Y = AmaxY;}
		//alert ('Restricting '+Y+' '+X);
		map.setCenter(new GLatLng(Y,X));
	};

	var wheelZoom = function(a) {
	  if (a.detail) // Firefox
	  {
	    if (a.detail < 0)
	    { map.zoomIn(); }
	    else if (a.detail > 0)
	    { map.zoomOut(); }
	  }
	  else if (a.wheelDelta) // IE
	  {
	    if (a.wheelDelta > 0)
	    { map.zoomIn(); }
	    else if (a.wheelDelta < 0)
	    { map.zoomOut(); }
	  }
	};
	/***
	 * PUBLIC METHOD :- setMarkers(color)
	 *   Public wrapper method for private _setMarkers
	 ***/
	this.setMarkers = function(color)
	{
		_setMarkers(color);
	}
	/***
	 * PRIVATE METHOD :- _setMarkers
	 *   Draws a set of markers on the map based in their color attribute
	 ***/
	var _setMarkers = function(color)
	{
		var len = locations.length;
		var sidebar_html = '';
		var el = document.getElementById(color);

		map.closeInfoWindow();

		if (el && !el.checked) {
			// hide the marker
			for (var i=0; i<len; i++) {
				var marker = locations[i].getMarker();
				if (marker.type == color)
					map.removeOverlay(marker);
			}
		} else if (el) {
			// show the marker again
			for (var i=0; i<len; i++) {
				var marker = locations[i].getMarker();
				if (marker.type == color) {
					map.addOverlay(marker);
				}
			}
		}
		sidebar_html += '<ul>';
		for (var i=0; i<len;i++) {
			var loc = locations[i];
			var marker = loc.getMarker();
			if (document.getElementById(marker.type) && document.getElementById(marker.type).checked)  {
				//if (marker.type != 'purple') {
				if (marker.type) {
					sidebar_html +=
						'<li><img src="img/list_bullet.gif"/><a href="javascript:' + mapObjId + '.showInfo(' + loc.getOrdinal() + ')">' + marker.name + '</a></li>';
				}
			}
		}
		sidebar_html += '</ul>';
		mapSidebar.innerHTML = sidebar_html;
	};
	/***
	 * PUBLIC METHOD :- setDefaultMarkers
	 *   Public wrapper method for private _setDefaultMarkers
	 ***/
	this.setDefaultMarkers = function()
	{
		_setDefaultMarkers();
	}
	/***
	 * PRIVATE METHOD :- _setDefaultMarkers
	 *   Calls the _setMarkers method to draw the default marker set
	 ***/
	var _setDefaultMarkers = function()
	{
		for (var i=0; i<NJSPBMap.DefaultColors.length; i++) {
			var color = NJSPBMap.DefaultColors[i];
			_setMarkers(color);
		};
	};
	/***
	 * PUBLIC METHOD :- addIcon(color)
	 *
	 ***/
	var addIcon = function(color)
	{
		var icon = new GIcon(getBaseIcon());
		icon.image = imgPath + '/mm_20_' + color + '.png';
		iconLookup[color] = icon;

		return icon;
	};
	/***
	 * PUBLIC METHOD :- getIcon(color)\
	 *
	 ***/
	 var getIcon = function(color)
	 {
		 return iconLookup[color];
	 };
	/***
	 * PUBLIC METHOD :- getDefaultIcon
	 *
	 ***/
	var getBaseIcon = function()
	{
		if (!baseIcon) {
			baseIcon = new GIcon();
			baseIcon.image = imgPath + '/mm_20_red.png';
			baseIcon.shadow = imgPath + '/mm_20_shadow.png';
			baseIcon.iconSize = new GSize(12, 20);
			baseIcon.shadowSize = new GSize(22, 20);
			baseIcon.iconAnchor = new GPoint(6, 20);
			baseIcon.infoWindowAnchor = new GPoint(5, 1);
			baseIcon.imageMap = [ 4, 0, 0, 4, 0, 7, 3, 11, 4, 19, 7, 19, 8, 11, 11, 7, 11, 4, 7, 0 ];
		}

		return baseIcon;
	};
	/***
	 * PUBLIC METHOD :- coloredRideshareIcon(iconColor)
	 *
	 ***/
	var getColoredRideshareIcon = function(iconColor)
	{
		// Create marker icons
		var icon = null;
		var color = 'green'; // green by default

		if (iconColor && typeof(iconColor) != 'undefined') {
			color = iconColor;
		}
		icon = getIcon(color);
		if (!icon) {
			icon = addIcon(color);
		}

		return icon;
	};
	/***
	 * PUBLIC METHOD :- createMarkersFromXML(xmlDoc)
	 *
 	 ***/
	var readLocationsFromXML = function(xmlDoc)
	{
		// obtain the array of markers and loop through it
		var markers = xmlDoc.documentElement.getElementsByTagName('marker');
		var ls = [];
		for (var i=0; i < markers.length; i++) {
			// obtain the attribues of each marker
			var info = [];
			info['lat'] = parseFloat(markers[i].getAttribute('lat'));
			info['lng'] = parseFloat(markers[i].getAttribute('lng'));
			info['label'] = markers[i].getAttribute('label');
			info['office'] = markers[i].getAttribute('office');
			info['site'] = markers[i].getAttribute('site');
			info['phone'] = markers[i].getAttribute('phone');
			info['icolor'] = markers[i].getAttribute('icolor');
			ls[i] = createLocation(i, info);
		}
		setLocations(ls);
	};
	/***
	 * PUBLIC METHOD :- createLocation(ordinal, info)
	 *   Method to create a map location
	 ***/
	var createLocation = function(ordinal, info)
	{
		var icolor = info['icolor'];
		var point = new GLatLng(info['lat'], info['lng']);
		var icon = getColoredRideshareIcon(icolor);
		var marker = new GMarker(point, icon);
		var infoWindowHtml =
			'<div class="location_info">' +
			'	<div class="map_legend">' +
			'		<h2>' + info['office'] + '</h2>' +
			'	</div>' +
			'	<div class="location_info_item">' +
			'		<address>' +
			info['label'] + info['phone'];
		var toHtml = '';
		var fromHtml = '';
		var name = info['site'] + ' - ' + info['phone'];

		marker.name = info['office'];
		if (icolor) { // icolor is defined
			marker.type = icolor;
		}
		//else {
		//	marker.type = 'purple';
		//}
		/***
		 *	Zoom in and out:
		 ***/
		infoWindowHtml +=
			'		</address>' +
			'</div>' +
			'<div class="location_info_item">' +
			'	<h2 class="inline_h">Zoom:</h2>' +
			'	<span>' +
			'		&nbsp;<a href="javascript:' + mapObjId + '.zoomIn(' + ordinal + ');">In</a>' +
			'		&nbsp;|&nbsp;<a href="javascript:' + mapObjId + '.zoomOut(' + ordinal + ');">Out</a>&nbsp;' +
			'	</span>' +
			'</div>';

		/***
		 *	The info window version with the 'to here' form open
		 ***/
		toHtml = infoWindowHtml +
			'<div class="location_info_item">' +
			'	<h2 class="inline_h">Directions:</h2>' +
			'	<span>' +
			'		&nbsp;To here&nbsp;|&nbsp;<a href="javascript:' + mapObjId + '.fromHere(' + ordinal + ')">From here</a>&nbsp;' +
			'	</span>' +
			'	<h2>Start Address: </h2>' +
			'	<form action="http://maps.google.com/maps" method="get" target="_blank">' +
			'		<input type="text" size="30" maxlength="60" name="daddr" id="daddr" onFocus="this.select()" value="' + CO_addr + '"/>' +
			'		<br/>' +
			'		<input class="map_submit" value="Get Directions" type="submit">' +
			'		<input type="hidden" name="saddr" value="' + point.lat() + ',' + point.lng() + '(' + name + ')' + '"/>' +
			'	</form>' +
			'</div>';

		/***
		 *	The info window version with the 'from here' form open
		 ***/
		fromHtml = infoWindowHtml +
			'<div class="location_info_item">' +
			'	<h2 class="inline_h">Directions:</h2>' +
			'	<span>' +
			'		&nbsp;<a href="javascript:' + mapObjId + '.toHere(' + ordinal + ')">To Here</a>&nbsp;|&nbsp;From Here&nbsp;' +
			'	</span>' +
			'	<h2>End Address: </h2>' +
			'	<form action="http://maps.google.com/maps" method="get" target="_blank">' +
			'		<input type="text" size="30" maxlength="60" name="daddr" id="daddr" onFocus="this.select()" value="' + CO_addr + '"/>' +
			'		<br/>' +
			'		<input class="map_submit" value="Get Directions" type="submit">' +
			'		<input type="hidden" name="saddr" value="' + point.lat() + ',' + point.lng() + '(' + name + ')' + '"/>' +
			'	</form>' +
			'</div>';

		/***
		 *	The inactive version of the direction info
		 ***/
		infoWindowHtml +=
			'<div class="location_info_item">' +
			'	<h2 class="inline_h">Directions:</h2>' +
			'	<span>' +
			'		&nbsp;<a href="javascript:' + mapObjId + '.toHere(' + ordinal + ')">To Here</a>&nbsp;|&nbsp;' +
			'		<a href="javascript:' + mapObjId + '.fromHere(' + ordinal + ')">From Here</a>&nbsp;' +
			'	</span>' +
			'</div>';

		 // Register the marker to open the infowindow when a click event is fired
		GEvent.addListener(marker, 'click', function() { marker.openInfoWindowHtml(infoWindowHtml); });

		return new NJSPBMapLocation(ordinal, marker, fromHtml, toHtml, infoWindowHtml);
	};
	/***
	 * PRIVATE METHOD :- setLocations
	 *
	 ***/
	var setLocations = function(locs)
	{
		locations = locs;
	};
	/***
	 * PRIVATE METHODS :- callback
	 *
	 ***/
	var callbackAction = function()
	{
		if (request.readyState == 4) {
			readLocationsFromXML(request.responseXML);
			_setDefaultMarkers();
		}
	};
	/***
	 * PUBLIC METHOD :- load
	 *   Initializes the map
	 ***/
	this.load = function(xmlFileName)
	{
		var kb = null;
		// Check to see if user has Internet connection
		try {
			// Check to see if this browser can run the Google API
				if (GBrowserIsCompatible()) {
    	  	// Display the map, with some controls and set the initial location
       			map = new GMap2(mapPanel);
       			kb = new GKeyboardHandler(map);
				map.addControl(new GLargeMapControl());
				map.addControl(new GMapTypeControl());
   	    		map.enableDoubleClickZoom();
				map.enableContinuousZoom();


				// these listeners are to capture the mouse scroll wheel activity
				GEvent.addDomListener(document.getElementById('map'), "DOMMouseScroll", wheelZoom); // Firefox
				GEvent.addDomListener(document.getElementById('map'), "mousewheel", wheelZoom); // IE
       			map.setCenter(new GLatLng(40.15,-74.74), 8);

  		  		// Read the data from xml file
        		request.open('GET', 'map/' + xmlFileName + '.xml', true);
       			request.onreadystatechange = callbackAction;

				// About info
				var marker_j = new GMarker(new GLatLng(-85,-180), getColoredRideshareIcon('transparent'));
				GEvent.addListener(marker_j, 'click', function() { marker_j.openInfoWindowHtml(ji); });
				map.addOverlay(marker_j);
				var marker_m = new GMarker(new GLatLng(-27.112923, -109.368896), getColoredRideshareIcon('transparent'));
				GEvent.addListener(marker_m, 'click', function() { marker_m.openInfoWindowHtml(mi); });
				map.addOverlay(marker_m);

				// Do it
				request.send(null);

				// Add a move listener to restrict the bounds range
				GEvent.addListener(map, 'move', checkBounds);
				// The allowed region which the whole map must be within
			} else {
				alert('Sorry, the Google Maps API is not compatible with this browser');
			}
		} catch(err) {
			alert(err);
			// Error to display if user does not have an Internet connection
			txt =
				'It appears as though you do not have a connection to the Internet. ' +
				'This may be caused by not being authenticated to a proxy server if you are using one. ' +
				'You must have an active Internet connection to use the new interactive maping features. ' +
				'You may access the previous non-interactive version of the map by clicking below.';
			mapPanel.innerHTML=
				'<br/><center><div class="boardmembersbold">' + txt +
				'<br/><br/><a href="locationsold.htm">Non-interactive SPB Map</a>' +
				'<br/><br/>You can test your Internet connectivity by clicking the link below.' +
				'<br/><br/><a href="http://maps.google.com">Google Maps</a>' +
				'</div></center>';
		}
	};
};
