//<![CDATA[

// ************************************************
// * Group and Site Map
// * by Rames Creel, April 2007
// *
// * Maps, satellite images & directions
// * by Google Maps, http://maps.google.com
// *
// * Cookie Utilities
// * by Scott Andrew (www.scottandrew.com)
// * From: www.quirksmode.org/js/cookies.html
// *
// * Prequisites:
// *	sites.js (contains the group and site data)
// * 
// ************************************************

var gMapElementId = "map";
var gGroupList = new Array();	// * All the groups
var gSiteList = new Array();	// * All the sites
var gMap;			// * The map (our wrapper around the Google map)
var gFromSiteId;		// * Holds the "Starting From" site ID
var gToSiteId;			// * Holds the "Going to" site Id

// ************************************************
// * Group Class
// ************************************************

function Group(anId, aLatitude, aLongitude, aGroup) {

	this._id			= anId;			// * Group's index in the gGroupList
	this._latitude		= aLatitude;		// * Latitude of the group's "center" - not implemented
	this._longitude		= aLongitude;		// * Longitude of the group's "center" - not implemented
	this._groupName		= aGroup;		// * Name of the group
	this._mapIcon		= newIcon(this._id);	// * Map icon for all sites in the group
	this._siteList		= new Array();		// * List of sites in the group
	this._isVisible		= true;			// * Are the sites for this group visible on the map?
	this._isExpanded	= false;		// * Is this group expanded (can you see the site list)?

	gGroupList[anId]		= this;			// * Add the group to the gGroupList
	}

	// ------------------------------------------------
	// - Accessors
	// ------------------------------------------------

	// * Return the group's index in the gGroupList

	Group.prototype.getId = function() {
		return this._id;
		}

	// * Return the group's longitude

	Group.prototype.getLatitude = function() {
		return this._latitude;
		}

	// * Return the group's longitude

	Group.prototype.getLongitude = function() {
		return this._longitude;
		}

	// * Return the list of sites for this group

	Group.prototype.siteList = function() {
		return this._siteList;
		}

	// * Return the map icon for all sites in this group

	Group.prototype.getIcon = function() {
		return this._mapIcon;
		}

	// * Return whether the sites for this group are displayed on the map

	Group.prototype.getVisibility = function() {
		return this._isVisible;
		}

	// * Set whether the sites for this group are displayed on the map

	Group.prototype.setVisibility = function(aBoolean) {
		this._isVisible = aBoolean;
		}

	// * Get whether this group's site list is expanded (can you see the site list?)

	Group.prototype.getExpanded = function(aBoolean) {
		return this._isExpanded;
		}

	// * Set whether this group's site list is expanded (can you see the site list?)

	Group.prototype.setExpanded = function(aBoolean) {
		this._isExpanded = aBoolean;
		}

	// * Return string representation of this object
	// * This allows us to use the object as if it were a string

	Group.prototype.toString = function() {
		return this._groupName;
		}

	// ------------------------------------------------
	// - Actions
	// ------------------------------------------------

	// * Add a site for this group

	Group.prototype.addSite = function(aSite) {
		// Make sure aSite is not null (it may be if the latitude is not defined)
		if (aSite != null)
			this._siteList[this._siteList.length] = aSite;
		}

	// * Show the group's sites on the map if they aren't already

	Group.prototype.show = function() {
		// * If a site is already visible don't do anything
		if (this._isVisible)
			return;
		showStatus("Showing " + this);
		eraseCookie("c" + this._id);
		document.getElementById("c" + this._id).checked = true;
		this._isVisible = true;
		for (var i=0; i<this._siteList.length; i++)
			this._siteList[i].show();
		showStatus(new String);
		}

	// * Hide the group's sites from the map

	Group.prototype.hide = function() {
		// * If a site is already hidden don't do anything
		if (!this._isVisible)
			return;
		showStatus("Hiding " + this);
		createCookie("c" + this._id, false, 9999);
		document.getElementById("c" + this._id).checked = false;
		this._isVisible = false;
		for (var i=0; i<this._siteList.length; i++)
			this._siteList[i].hide();
		showStatus(new String);
		}

	// * Hide/Show the sites on the map

	Group.prototype.toggleHidden = function() {
		if (this._isVisible)
			this.hide();
		else
			this.show();
		}

	// * Expand a group

	Group.prototype.expand = function() {
		if (!this._isExpanded) {
			showStatus("Expanding " + this);
			createCookie("sl" + this._id, true, 9999);
			document.getElementById("sl" + this._id).style.display = 'block';
			this._isExpanded = true;
			showStatus(new String);
			}
		}

	// * Collapse a group

	Group.prototype.collapse = function() {
		if (this._isExpanded) {
			showStatus("Collapsing " + this);
			eraseCookie("sl" + this._id);
			document.getElementById("sl" + this._id).style.display = 'none';
			this._isExpanded = false;
			showStatus(new String);
			}
		}

	// * Expand/Collapse the group

	Group.prototype.toggleExpand = function() {
		if (this._isExpanded)
			this.collapse();
		else
			this.expand();
		}

	// * Center the map on this group

	Group.prototype.centerMap = function() {
		gMap.centerMap(this._latitude, this._longitude, 13);
		}

	// ------------------------------------------------
	// - HTML Support
	// ------------------------------------------------

	// * Return the HTML suitable for the checkbox in the side bar
	// * If the box is checked the sites for the group display on the map

	Group.prototype.getCheckBoxHtml = function() {
		var strHtml = "<input id='c" + this._id + "' type=checkbox name='c" + this._id + "' ";
		if (this._isVisible)
			strHtml += " checked ";
		strHtml += "onClick='javascript:toggleHide(\"" + this._id + "\")'> ";
		return strHtml;
		}

	// * Return the HTML suitable for toggling whether or not the site list for the group is expanded

	Group.prototype.getToggleHtml = function() {
		return "<span onClick='javascript:toggleExpand(\"" + this._id + "\")'>" + this + "</span>";
		}

	// * Return the group as HTML suitable for the side bar

	Group.prototype.getSideBarHtml = function() {
		var strHtml = divClass("sbGroup", "d" + this._id, this.getCheckBoxHtml() + this.getToggleHtml());
		strHtml += "<div class='sbGroupList' id='sl" + this._id + "'";
		if (!this._isExpanded)
			strHtml += " style='display:none' ";
		strHtml += ">";
		for (var i=0; i<this._siteList.length; i++)
			strHtml += this._siteList[i].getSideBarHtml();
		strHtml += "</div>";
		return strHtml;
		}

// ************************************************
// * Site Class
// ************************************************

function Site(aGroupId, aLatitude, aLongitude, aSiteName, aSiteAddr1, aSiteAddr2, aPhoneNumber, anImageUrl) {

	// If a latitude is not specified skip this site.
	if (aLatitude == new String)
		return null;

	this._id			= gSiteList.length;	// * Sites's index in the gSiteList
	this._group			= gGroupList[aGroupId];	// * The group to which this site belongs
	this._latitude		= aLatitude;		// * Latitude of the site
	this._longitude		= aLongitude;		// * Longitude of the site
	this._siteName		= aSiteName;		// * The name of the site
	this._address1		= aSiteAddr1;		// * The first line of the site's address (street address)
	this._address2		= aSiteAddr2;		// * The second line of the sites's address (city, state zip)
	this._phone			= aPhoneNumber;		// * The sites phone number
	this._imageUrl		= anImageUrl;		// * The url containing an image of the site (may be an empty string)
	this._marker		= newMarker(this);	// * The marker is the reprentation of this site on the map

	gSiteList[this._id]	= this;			// * Add the site to the gSiteList
	this._group.addSite(this);			// * Add the site to the group
	}

	// ------------------------------------------------
	// - Accessors
	// ------------------------------------------------

	// * Return the site's index in the gSiteList

	Site.prototype.getId = function() {
		return this._id;
		}

	// * Return the site's group

	Site.prototype.getGroup = function() {
		return this._group;
		}

	// * Return the site's longitude

	Site.prototype.getLatitude = function() {
		return this._latitude;
		}

	// * Return the site's longitude

	Site.prototype.getLongitude = function() {
		return this._longitude;
		}

	// * Return the site's icon

	Site.prototype.getIcon = function() {
		return this._group.getIcon();
		}

	// * Return the site's map marker

	Site.prototype.getMarker = function() {
		return this._marker;
		}

	// * Return string representation of this object
	// * This allows us to use the object as if it were a string

	Site.prototype.toString = function() {
		return this._siteName;
		}

	// ------------------------------------------------
	// - Action
	// ------------------------------------------------

	// * Hide the site from the map

	Site.prototype.hide = function() {
		gMap.removeOverlay(this.getMarker());
		}

	// * Show the site on the map

	Site.prototype.show = function() {
		gMap.addOverlay(this.getMarker());
		}

	// * Center the map on this site

	Site.prototype.centerMap = function() {
		gMap.centerMap(this._latitude, this._longitude, 15);
		}

	// ------------------------------------------------
	// - HTML Support
	// ------------------------------------------------

	// * Return the URL encoded address (1 & 2)

	Site.prototype.getEncodedAddress = function () 	{
		return (this._address1 + " " + this._address2).replace(/ /g, "+");
		}

	// * Return the site as a link that opens the map information window

	Site.prototype.getSiteLink = function() {
		return "<a href='javascript:showInfo(\"" + this._id + "\");'>" + this + "</a>";
		}

	// * Return the site as HTML

	Site.prototype.getSiteHtml = function() {
		return divClass("site", new String, this._siteName);
		}

	// * Return the group as HTML

	Site.prototype.getGroupHtml =function() {
		return divClass("group", new String, this._group);
		}

	// * Return address1 as HTML

	Site.prototype.getAddress1Html =function() {
		return divClass("address1", new String, this._address1);
		}

	// * Return address2 as HTML

	Site.prototype.getAddress2Html =function() {
		return divClass("address2", new String, this._address2);
		}

	// * Return the phone as HTML

	Site.prototype.getPhoneHtml = function() {
		return divClass("phone", new String, this._phone);
		}

	// * Return the HTML that allows the user to set this site as the source or destination 

	Site.prototype.getLocationHtml =function() {
		var strHtml = "Set location: <a href='javascript:saveLocation(\"from\", " + this._id + ")'>From Here</a> - ";
		strHtml += "<a href='javascript:saveLocation(\"to\", " + this._id + ")'>To Here</a>"
		return divClass("setLocation", new String, strHtml);
		}

	// * Return the image as an HTML link

	Site.prototype.getImageHtml = function() {
		if (this._imageUrl != new String) {
			var strHtml = "<img src='" + this._imageUrl + "' height='150px'></img>";
			return divClass("image", new String, strHtml);
			}
		else
			return new String;
		}

	// * Return the site as HTML suitable for the side bar

	Site.prototype.getSideBarHtml = function() {
		return divClass("sbSite", "s" + this._id, this.getSiteLink());
		}

	// * Return the detail used in the site's map information

	Site.prototype.detail = function() {
		var siteInfo = "<div class='siteInfo'>";
		siteInfo += this.getSiteHtml();
		siteInfo += this.getGroupHtml();
		siteInfo += this.getAddress1Html();
		siteInfo += this.getAddress2Html();
		siteInfo += this.getPhoneHtml();
		siteInfo += this.getImageHtml();
		//siteInfo += this.getLocationHtml();

		if (gFromSiteId != null && gToSiteId != null) {
			if (gFromSiteId == this._id)
				var siteId = gToSiteId;
			else
				var siteId = gFromSiteId;
			var site = gSiteList[siteId];
			var aUrl = getDirectionUrl(this, site);
			siteInfo += "Get directions: <a href='javascript:openDirections(\"" + aUrl + "\");'>From here to " + site + "</a><br>";
			var aUrl = getDirectionUrl(site, this);
			siteInfo += "Get directions: <a href='javascript:openDirections(\"" + aUrl + "\");'>From " + site + " to here</a><br>";
			}
		siteInfo += "</div>";

		return siteInfo;
		}

// ************************************************
// * Map Class
// *
// * Return a new map given:
// ************************************************

function Map() {

	showStatus("Creating map...");
	this._map = new GMap2(document.getElementById(gMapElementId));
	this.setDefaultCenter();
	this._map.addControl(new GLargeMapControl());
	this._map.addControl(new GMapTypeControl());
	//this._map.enableScrollWheelZoom();
	this._map.enableDoubleClickZoom();
	this._map.enableContinuousZoom();
	showStatus(new String);
	}

	// ------------------------------------------------
	// - Utilities
	// ------------------------------------------------

	// * Center the map using using the default latitude, longitude and zoom level

	Map.prototype.setDefaultCenter = function() {
		this._map.setCenter(new GLatLng(gMapLatitude, gMapLongitude), gMapZoom);
		}

	// * Render the map

	Map.prototype.render = function() {
		showStatus("Mapping sites ...");
		for (var i=0; i<gGroupList.length; i++)
			this.renderGroup(gGroupList[i]);
		showStatus(new String);
		}

	// * Render the group on the map

	Map.prototype.renderGroup = function(aGroup) {
		if (!aGroup.getVisibility())
			return;
		var siteList = aGroup.siteList();
		for (var x=0; x<=siteList.length - 1; x++) {
			var site = siteList[x];
			this.renderSite(site);
			}
		}

	// * Render the site on the map

	Map.prototype.renderSite = function(aSite) {
		this._map.addOverlay(aSite.getMarker());
		}

	// * Add an overlay (marker) to the map

	Map.prototype.addOverlay = function(aMarker) {
		this._map.addOverlay(aMarker);
		}

	// * Remove an overlay (marker) from the map

	Map.prototype.removeOverlay = function(aMarker) {
		this._map.removeOverlay(aMarker);
		}

	// * Center the map on a group or a site

	Map.prototype.centerMap = function(aLatitude, aLongitude) {
		this._map.panTo(new GLatLng(aLatitude, aLongitude));
		}

// ************************************************
// * Direction Utilities
// ************************************************

// * Save the location as either a source or destination site

function saveLocation(aType, anId) {
	var site = gSiteList[anId];
	if (aType == "from") {
		gFromSiteId = site.getId();
		createCookie("fromSiteId", gFromSiteId, 9999);
		}
	else {
		gToSiteId = site.getId();
		createCookie("toSiteId", gToSiteId, 9999);
		}
	document.getElementById(aType + "Name").innerHTML = site.getSiteLink();
	if (gFromSiteId != null && gToSiteId != null)
		document.getElementById("getDirections").disabled = false;
	}

// * Return a HTML link to get directions from one site to another

function getDirectionUrl(fromSite, toSite) {
	var strHtml = "http://maps.google.com/maps?saddr=";
	strHtml += fromSite.getEncodedAddress();
	strHtml += "&daddr=";
	strHtml += toSite.getEncodedAddress();
	return strHtml;
	}

// * Get directions from Google Maps

function getDirections() {
	var aUrl = getDirectionUrl(gSiteList[gFromSiteId], gSiteList[gToSiteId]);
	window.open(aUrl);
	}

// * Get directions from Google Maps
// * Use this functtion when opening the address from a, "a href" link

function openDirections(aUrl) {
	window.open(aUrl);
	}

// ************************************************
// * Group Side Bar Utilities
// ************************************************

// * Add the list of groups and sites (sites are initially hidden) to the side bar

function addGroupsToSideBar() {
	var strHtml = new String;
	for (var i=0; i<gGroupList.length; i++)
		strHtml += gGroupList[i].getSideBarHtml();
	document.getElementById("side_bar").innerHTML = strHtml;
	}

// * Expand/Collapse the group

function toggleExpand(anId) {
	gGroupList[anId].toggleExpand();
	var siteList = gGroupList[anId].siteList();
	siteList[0].centerMap();
	showInfo(siteList[0].getId());
	}

// * Expand all groups

function expandAll() {
	for (var i=0; i<gGroupList.length; i++)
		gGroupList[i].expand(i);
	}

// * Collapse all groups

function collapseAll() {
	for (var i=0; i<gGroupList.length; i++)
		gGroupList[i].collapse(i);
	}

// * Hide/Show all the sites for the group on the map

function toggleHide(anId) {
	gGroupList[anId].toggleHidden();
	}

// * Show all the sites on the map

function showAll() {
	for (var i=0; i<gGroupList.length; i++)
		gGroupList[i].show();
	gMap.setDefaultCenter();
	}

// * Hide all the sites on the map

function hideAll() {
	for (var i=0; i<gGroupList.length; i++)
		gGroupList[i].hide();
	}

// ************************************************
// * Misc Utilities
// ************************************************

// * Show the map information window for a site

function showInfo(anId) {
	gSiteList[anId].centerMap();
	GEvent.trigger(gSiteList[anId].getMarker(), "click");
	}

function showStatus(aMessage) {
	window.status = aMessage;
	}

// * Return a new icon for the map
// * This would have been a method in the map class but we need
// * to create the icon when the group is created but the map
// * doesn't exist yet

function newIcon(anId) {
	var mapIcon = new GIcon();
	mapIcon.image = "/agentIDX/GMap/images/marker" + anId + ".png";
	mapIcon.shadow = "/agentIDX/GMap/images/shadow.png";
	mapIcon.iconSize = new GSize(12, 20);
	mapIcon.shadowSize = new GSize(22, 20);
	mapIcon.iconAnchor = new GPoint(6, 20);
	mapIcon.infoWindowAnchor = new GPoint(5, 1);
	return mapIcon;
	}

// * Return a new map marker
// * This would have been a method in the map class but we need
// * to create the marker when the site is created but the map
// * doesn't exist yet

function newMarker(aSite) {
	var marker = new GMarker(new GLatLng(aSite.getLatitude(), aSite.getLongitude()), aSite.getIcon());
//	var site = this;
	GEvent.addListener(marker, "click", function() {
		marker.openInfoWindowHtml(aSite.detail());
		});
	return marker;
	}

// ************************************************
// * Saved Settings
// ************************************************

// * Read cookies and restore state

function restoreState() {

	var fromSiteId = readCookie("fromSiteId");
	var toSiteId = readCookie("toSiteId");
	var showHelp = readCookie("showHelp");

	// * Restore Starting From / Going To locations
	if (fromSiteId)
		saveLocation("from", fromSiteId);
	if (toSiteId)
		saveLocation("to", toSiteId);

	//* Restore group visibile and expanded states

	for (i=0; i<gGroupList.length; i++) {
		var group = gGroupList[i];
		var showGroup = readCookie("c" + i);
		if (showGroup)
			group.setVisibility(false);
		var showSites = readCookie("sl" + i);
		if (showSites)
			group.setExpanded(true);
		}

	//* Restore the help window state
	
	if (showHelp == "true")
		showbox();

	}

function clearSavedSettings() {
	if (confirm("Do you want to reset all settings to their defaults?")) {
		eraseAllCookies();
		window.location.reload();
		}
	}

// ************************************************
// * HTML Utilities
// ************************************************

// * Create a HTML span tag with the specified class and (optionally) and ID

function spanClass(aClass, anId, aString) {
	if (anId == new String)
		return "<span class='" + aClass + "'>" + aString + "</span>";
	else
		return "<span class='" + aClass + "' id='" + anId + "'>" + aString + "</span>";

	}

// * Create a HTML div tag with the specified class and (optionally) and ID

function divClass(aClass, anId, aString) {
	if (anId == new String)
		return "<div class='" + aClass + "'>" + aString + "</div>";
	else
		return "<div class='" + aClass + "' id='" + anId + "'>" + aString + "</div>";
	}

// ************************************************
// * Cookie Utilities
// ************************************************

function createCookie(name, value, days) {
	if (navigator.cookieEnabled == 0)
		return;
	if (days) {
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
		}
	else
		var expires = "";
	document.cookie = name+"="+value+expires+"; path=/";
	}

function readCookie(name) {
	if (navigator.cookieEnabled == 0)
		return;
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
		}
	return null;
	}

function eraseCookie(name) {
	createCookie(name,"",-1);
	}

function eraseAllCookies() {
	if (navigator.cookieEnabled == 0)
		return;
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var sc= ca[i].split("=");
		if (sc.length != 2)
			continue;
		var name = unescape(sc[0]);
		eraseCookie(name);
		}
	}

// ************************************************
// * Page Load
// ************************************************

function load() {
	if (GBrowserIsCompatible()) {
		loadSiteList();
		restoreState();
		addGroupsToSideBar();
 		gMap = new Map();
		gMap.render();
		}
	else
		alert("Sorry, the Google Maps API is required to see this page but it is not compatible with this browser.");
	}

//]]>
