
/**
 * cross browser function to ADD an event callback to an element
 * very useful for adding stuff to window.onload without harming existing callbacks
 **/
 
function GMHAddEvent(obj, evType, fn, useCapture){
  if (obj.addEventListener){
    obj.addEventListener(evType, fn, useCapture);
    return true;
  } else if (obj.attachEvent){
    var r = obj.attachEvent("on"+evType, fn);
    return r;
  } else {
    //alert("Handler could not be attached");
  }
} 

/**
 * cross browser function to REMOVE an event callback from an element
 * reverses the effect of addEvent
 **/
function GMHRemoveEvent(obj, evType, fn, useCapture){
  if (obj.removeEventListener){
    obj.removeEventListener(evType, fn, useCapture);
    return true;
  } else if (obj.detachEvent){
    var r = obj.detachEvent("on"+evType, fn);
    return r;
  } else {
    //alert("Handler could not be removed");
  }
} 

/**
 * cross browser way to get outerHTML (IE only) of an element
 **/
function GetOuterHTML(e) {
  if( e.outerHTML )
	return e.outerHTML;
	
  var d = e.ownerDocument.createElement("body");
  d.appendChild(e);
  return d.innerHTML;
}

/****************
 * GMHMaster class
 ****************/
function GMHMaster(mapDivID) {
	this.mapDivID = mapDivID;
	this.markers = [];
	this.markerIds = [];
	this.markersCount = 0;
	this.map = null;
}

GMHMaster.prototype.AddMarker = function(gmhMarker) {
	if( this.markers[gmhMarker.id]==null ) {
	    this.markerIds[this.markersCount] = gmhMarker.id;
		this.markersCount++;
	}
	this.markers[gmhMarker.id] = gmhMarker;
};

GMHMaster.prototype.PopulateMap = function() {
	var hMapDiv = document.getElementById(this.mapDivID)
	if (this.markersCount > 0 && window.GBrowserIsCompatible && GBrowserIsCompatible()) {
        this.map = new GMap2(hMapDiv);
                
        var typeCtl = new GMenuMapTypeControl();
        if( hMapDiv.offsetWidth > 250 ) {
			this.map.addControl(typeCtl);
			this.map.addControl(new GOverviewMapControl());
			if(window.TrafficMapTypeControl) {
			    this.map.addControl(new TrafficMapTypeControl({showTraffic: true, showTrafficKey: true}), new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(87,7)) );
            }
		}
		else if( hMapDiv.offsetWidth > 150 ) {
			this.map.removeMapType(G_SATELLITE_MAP);
			this.map.addControl(typeCtl);
		}		
		if( hMapDiv.offsetHeight > 250 ) {
			 this.map.addControl(new GLargeMapControl());
		}
		else {
			this.map.addControl(new GSmallMapControl());
		}
		
		this.map.enableDoubleClickZoom();
		//this.map.enableContinuousZoom();
		
		var totalLat = 0;
		var totalLong = 0;
		var minLat=99999;
		var minLong=99999;
		var maxLat=-99999;
		var maxLong=-99999;

		// get extremities, set up map		
		for (var i=0;i<this.markersCount;i++) {
		    var id = this.markerIds[i];
			totalLat += this.markers[id].latitude;
			totalLong += this.markers[id].longitude;
			if( this.markers[id].latitude < minLat ) minLat = this.markers[id].latitude;
			if( this.markers[id].longitude < minLong ) minLong = this.markers[id].longitude;
			if( this.markers[id].latitude > maxLat ) maxLat = this.markers[id].latitude;
			if( this.markers[id].longitude > maxLong ) maxLong = this.markers[id].longitude;
		}
		
		var zoomLev = this.map.getBoundsZoomLevel(new GLatLngBounds(new GLatLng(minLat,minLong), new GLatLng(maxLat,maxLong)));		
		if( zoomLev > 16 )
			zoomLev = 16; // cap at a reasonable street level
		this.map.setCenter(new GLatLng(totalLat/this.markersCount, totalLong/this.markersCount), (zoomLev<8 ? zoomLev : zoomLev-1));
		
		//this.SetUpMarkers();
		var _this = this
		window.setTimeout(function () { _this.SetUpMarkers(); }, 100);
		
		GEvent.addListener(this.map, "click", function(marker, point) {
			if (marker) {
				if( marker.GMHMarkerHandle && marker.GMHMarkerHandle.SetHighlight ) {
					marker.GMHMarkerHandle.SetHighlight(marker.GMHMarkerHandle,true);
				}
			} 
		});
	}
	else {
		hMapDiv.style.display = "none";
	}
};

GMHMaster.prototype.SetUpMarkers = function() {	
	// set up GMarkers
	if( this.map ) {
		for (var i=0;i<this.markersCount;i++) {
		    var id = this.markerIds[i];
			var point = new GLatLng(this.markers[id].latitude,
									this.markers[id].longitude);
			var gMarker = new GMarker(point);
			gMarker.GMHMarkerHandle = this.markers[id]; // back ref
			this.markers[id].GMarkerHandle = gMarker; // back ref
			this.map.addOverlay(gMarker);
			
			GEvent.addListener(gMarker, "infowindowclose", function(marker, point) {
				if( this.GMHMarkerHandle && this.GMHMarkerHandle.SetHighlight ) {
					this.GMHMarkerHandle.SetHighlight(this.GMHMarkerHandle,false);
				} 
			});
		}
	}
}

GMHMaster.prototype.Destroy = function() {
	for (var i=0;i<this.markersCount;i++) {
		var id = this.markerIds[i];
		this.markers[id].GMarkerHandle = null;
		this.markers[id]=null;
		this.markerIds[i]=null;
	}
	if (window.GBrowserIsCompatible && GBrowserIsCompatible()) {
		GUnload();
	}
	this.map = null;
};

/****************
 * GMHMarker class
 ****************/
 function GMHMarker(longitude,latitude,label,id,highlightCallback) {
	this.longitude = longitude;
	this.latitude = latitude;
	this.label = label;
	this.id = id;
	this.SetHighlight = highlightCallback;
	this.GMarkerHandle = null;
 }

