/* GOOGLEMAP.JS
   Utilities for working with Google Maps.

   Version Information
    20060510a = Created.
    20061211a = Added tooltip to icon images.
    20070321a = Added support for local URLs (don't appear in popup window) as map point clickactions.
    20110225a = Added support for content supplied by AJAX call to createPoint HTML.
    20110812a = Added support for v3 Google Maps.
    20111123a = Fixed bug in loadCategoryState function that caused errors when categories in cookies were not on current map.

Copyright © 2011, Land Information Access Association
*/

//Utility functions
function isArray(a) {
    return isObject(a) && a.constructor == Array;
}
function isObject(a) {
    return (a && typeof a == 'object') || isFunction(a);
}
function isFunction(a) {
    return typeof a == 'function';
}
Array.prototype.isKey = function(){ //adds a test to see if a element exists in an array
  for(i in this){
    if(i === arguments[0])
      return true;
  };
  return false;
}; 
//Global variables
var ccLocMapWin

function createPoint(ptID, ptLat, ptLon, ptName, ptIcon, ptIconX, ptIconY, ptHTML) {
	//Create an icon object for the icon image
	var picon = new GIcon();
	picon.image = ptIcon;
	picon.iconSize = new GSize(ptIconX, ptIconY);
	var centerX = parseInt(ptIconX / 2.0);
	var centerY = parseInt(ptIconY / 2.0);
	picon.iconAnchor = new GPoint(centerX, centerY);
	picon.infoWindowAnchor = new GPoint(centerX, centerY);
	//Create the coordinates for the point
	var point = new GLatLng(ptLat, ptLon);
	//Create the marker object for the point
	var marker = new GMarker(point, {icon: picon, title: ptName});
	//Create the popup for the point if requested
	if (ptHTML) {
		//If ptHTML is an array, then prepare for tabs
		if (isArray(ptHTML)) {
			//Create the click event for the point
			GEvent.addListener(marker, "click", function() {
				marker.openInfoWindowTabsHtml(ptHTML);
			});
		} else {
			//Check if a JavaScript is to be run
			if (ptHTML.substr(0, 4) == 'scr|') {
				GEvent.addListener(marker, "click", function() {
					eval(unescape(ptHTML.substr(4)));
				});
			//Check if a URL is provided
			} else if (ptHTML.substr(0, 4) == 'url|') {
				GEvent.addListener(marker, "click", function() {
					ccLocMapWin = window.open(unescape(ptHTML.substr(4)), 'LocMapWin');
					if (ccLocMapWin) ccLocMapWin.focus();
				});
			//Check if a local URL is provided
			} else if (ptHTML.substr(0, 5) == 'lurl|') {
				GEvent.addListener(marker, "click", function() {
					window.location = unescape(ptHTML.substr(5));
					if (ccLocMapWin) ccLocMapWin.focus();
				});
			//Check if an ajax URL is provided
			} else if (ptHTML.substr(0, 5) == 'ajax|') {
				GEvent.addListener(marker, "click", function() {
					//Display wait message
					var winContent = document.createElement('div');
					winContent.innerHTML = '<div class="locpopup"><img src="' + tbSiteRoot + 'cc/images/wait26trans.gif" border="0" width="26" height="26" align="absmiddle" alt="Please Wait" title="Please Wait">Loading...</div>';
					marker.openInfoWindowHtml(winContent);
					//Replace wait message with AJAX content when ready
            		GDownloadUrl(unescape(ptHTML.substr(5)), function(data) {
            			marker.openInfoWindowHtml('<div class="locpopup">' + data + '</div>');
            		});
				});
			} else {
				//Display the text when the point is clicked
				GEvent.addListener(marker, "click", function() {
					marker.openInfoWindowHtml(ptHTML);
				});
			}
		}
	}
	//Return the point
	return marker;
}


function createPoint3(ptID, ptMap, ptLat, ptLon, ptName, ptIcon, ptIconX, ptIconY, ptHTML) {
	var centerX = parseInt(ptIconX / 2.0);
	var centerY = parseInt(ptIconY / 2.0);
	//Create an icon object for the icon image
	var picon = new google.maps.MarkerImage(
		ptIcon,//path
		new google.maps.Size(ptIconX, ptIconY),//size
		new google.maps.Point(0,0),//origin
		new google.maps.Point(centerX, centerY));//anchor
	//Create the coordinates for the point
	var point = new google.maps.LatLng(ptLat, ptLon);
	//Create the marker object for the point
    var marker = new google.maps.Marker({
        position: point,
        icon: picon,
        title: ptName,
        map: ptMap
    });
	//Create the popup for the point if requested
	if (ptHTML) {
		//If ptHTML is an array, then prepare for tabs
		if (isArray(ptHTML)) {
			//Create the click event for the point
			GEvent.addListener(marker, "click", function() {
				marker.openInfoWindowTabsHtml(ptHTML);
			});
		} else {
			//Check if a JavaScript is to be run
			if (ptHTML.substr(0, 4) == 'scr|') {
				google.maps.event.addListener(marker, "click", function() {
					eval(unescape(ptHTML.substr(4)));
				});
			//Check if a URL is provided
			} else if (ptHTML.substr(0, 4) == 'url|') {
				google.maps.event.addListener(marker, "click", function() {
					ccLocMapWin = window.open(unescape(ptHTML.substr(4)), 'LocMapWin');
					if (ccLocMapWin) ccLocMapWin.focus();
				});
			//Check if a local URL is provided
			} else if (ptHTML.substr(0, 5) == 'lurl|') {
				google.maps.event.addListener(marker, "click", function() {
					window.location = unescape(ptHTML.substr(5));
				});
			//Check if an ajax URL is provided
			} else if (ptHTML.substr(0, 5) == 'ajax|') {
				google.maps.event.addListener(marker, "click", function() {
					//Display wait message
					var winContent = document.createElement('div');
					winContent.innerHTML = '<div class="locpopup"><img src="' + tbSiteRoot + 'cc/images/wait26trans.gif" border="0" width="26" height="26" align="absmiddle" alt="Please Wait" title="Please Wait">Loading...</div>';
					//Open generic infowindow
					mapInfo.close();
					mapInfo.setContent(winContent);
					mapInfo.open(ptMap, this);
	        		downloadUrl(unescape(ptHTML.substr(5)), function(data) {
            			mapInfo.setContent('<div class="locpopup">' + data + '</div>');
            		});
				});
			} else {
				//Display the text when the point is clicked
				google.maps.event.addListener(marker, "click", function() {
					mapInfo.close();
					mapInfo.setContent(ptHTML);
					mapInfo.open(ptMap, this);
				});
			}
		}
	}
	//Return the point
	return marker;
}

function addPoint(ptArray, ptID, ptMap, ptLat, ptLon, ptName, ptIcon, ptIconX, ptIconY, ptHTML) {
	ptArray[ptID] = new mapPoint(ptID, ptMap, ptLat, ptLon, ptName, ptIcon, ptIconX, ptIconY, ptHTML);
}

/* constructor for point */

function mapPoint(ptID, ptMap, ptLat, ptLon, ptName, ptIcon, ptIconX, ptIconY, ptHTML) {
	this.id = ptID;
	this.map = ptMap;
	this.lat = ptLat;
	this.lon = ptLon;
	this.ptname = ptName;
	this.icon = ptIcon;
	this.iconx = ptIconX;
	this.icony = ptIconY;
	this.html = ptHTML;
	this.show = function() {
		this.marker = createPoint3(this.id, this.map, this.lat, this.lon, this.ptname, this.icon, this.iconx, this.icony, this.html);
	}
	this.hide = function() {
		if (isObject(this.marker)) {
			this.marker.setMap(null);
		}
	}
}

/* constructor for category */
function mapCategory(catName, mapPoints, catID) {
	this.id = catID;
	this.itemname = catName;
	this.points = mapPoints;
	this.view = false;
	this.ids = new Array();
	this.savestate = false;
	this.onloadstate = function() { return true; }
	this.addids = function(strIDs) {
		var id;
		if (strIDs != '') {
			var idlist = strIDs.split(',');
			for (var i = 0; i < idlist.length; i++) {
				id = parseInt(idlist[i])
				if (!(id in this.ids)) this.ids.push(id);
			}
		}
	}
	this.toggleView = function() {
		this.view = !this.view;
		var cicon = document.getElementById(this.id);
		if (cicon) cicon.className = this.view ? 'lmcaton' : 'lmcatoff';
		var zoomto = new google.maps.LatLngBounds();
		for (var i = 0; i < this.ids.length; i++) {
			if (this.view) {
				this.points[this.ids[i]].show();
				zoomto.extend(new google.maps.LatLng(this.points[this.ids[i]].lat, this.points[this.ids[i]].lon));
			} else {
				this.points[this.ids[i]].hide();
			}
		}
		if (!zoomto.isEmpty()) {
			if (this.ids.length == 1) {
				this.points[this.ids[0]].map.setCenter(new google.maps.LatLng(this.points[this.ids[0]].lat, this.points[this.ids[0]].lon));
			} else {
				this.points[this.ids[0]].map.fitBounds(zoomto);
			}
		}
		if (this.savestate) saveCategoryState(this.id, this.view);
		this.onloadstate();
	}
	this.hide = function() {
		if (this.view) {
			this.view = false;
			var cicon = document.getElementById(this.id);
			if (cicon) cicon.className = 'lmcatoff';
			for (var i = 0; i < this.ids.length; i++) {
				this.points[this.ids[i]].hide();
			}
			if (this.savestate) saveCategoryState(this.id, this.view);
			this.onloadstate();
		}
	}
	this.show = function() {
		if (!this.view) {
			var zoomto = new google.maps.LatLngBounds();
			this.view = true;
			var cicon = document.getElementById(this.id);
			if (cicon) cicon.className = 'lmcaton';
			for (var i = 0; i < this.ids.length; i++) {
				this.points[this.ids[i]].show();
				zoomto.extend(new google.maps.LatLng(this.points[this.ids[i]].lat, this.points[this.ids[i]].lon));
			}
			if (!zoomto.isEmpty()) {
				if (this.ids.length == 1) {
					this.points[this.ids[0]].map.setCenter(new google.maps.LatLng(this.points[this.ids[0]].lat, this.points[this.ids[0]].lon));
				} else {
					this.points[this.ids[0]].map.fitBounds(zoomto);
				}
			}
			if (this.savestate) saveCategoryState(this.id, this.view);
			this.onloadstate();
		}
	}
}
function saveCategoryState(id, how) {
	if (how) {
		lmSetCookie(id,'on');
	} else {
		lmSetCookie(id,'off');
	}
}
function lmSetCookie(name,value,days) {
	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 loadCategoryState(idseed) {
	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(idseed) == 0) {
			var cv = c.split('=');
			var cid = parseInt(cv[0].substring(idseed.length));
			var objC = eval(idseed);
			if (objC instanceof Array) {
				if (objC.isKey(cid)) {
					if (cv[1] == 'on') {
						objC[cid].show();
					} else if (cv[1] == 'off') {
						objC[cid].hide();
					}
					if (cv[1] != '') objC[cid].onloadstate();
				}
			}
		}
	}
}

/**
* Returns an XMLHttp instance to use for asynchronous
* downloading. This method will never throw an exception, but will
* return NULL if the browser does not support XmlHttp for any reason.
* @return {XMLHttpRequest|Null}
*/
function createXmlHttpRequest() {
 try {
   if (typeof ActiveXObject != 'undefined') {
     return new ActiveXObject('Microsoft.XMLHTTP');
   } else if (window["XMLHttpRequest"]) {
     return new XMLHttpRequest();
   }
 } catch (e) {
   changeStatus(e);
 }
 return null;
};

/**
* This functions wraps XMLHttpRequest open/send function.
* It lets you specify a URL and will call the callback if
* it gets a status code of 200.
* @param {String} url The URL to retrieve
* @param {Function} callback The function to call once retrieved.
*/
function downloadUrl(url, callback) {
 var status = -1;
 var request = createXmlHttpRequest();
 if (!request) {
   return false;
 }

 request.onreadystatechange = function() {
   if (request.readyState == 4) {
     try {
       status = request.status;
     } catch (e) {
       // Usually indicates request timed out in FF.
     }
     if (status == 200) {
       //callback(request.responseXML, request.status);
       callback(request.responseText, request.status);
       request.onreadystatechange = function() {};
     }
   }
 }
 request.open('GET', url, true);
 try {
   request.send(null);
 } catch (e) {
   changeStatus(e);
 }
};

/**
 * Parses the given XML string and returns the parsed document in a
 * DOM data structure. This function will return an empty DOM node if
 * XML parsing is not supported in this browser.
 * @param {string} str XML string.
 * @return {Element|Document} DOM.
 */
function xmlParse(str) {
  if (typeof ActiveXObject != 'undefined' && typeof GetObject != 'undefined') {
    var doc = new ActiveXObject('Microsoft.XMLDOM');
    doc.loadXML(str);
    return doc;
  }

  if (typeof DOMParser != 'undefined') {
    return (new DOMParser()).parseFromString(str, 'text/xml');
  }

  return createElement('div', null);
}

/**
 * Appends a JavaScript file to the page.
 * @param {string} url
 */
function downloadScript(url) {
  var script = document.createElement('script');
  script.src = url;
  document.body.appendChild(script);
}



