// JS helper functions for YM4R

function addInfoWindowToMarker(marker,info,options){
  GEvent.addListener(marker, "click", function() {marker.openInfoWindowHtml(info,options);});
  return marker;
}

function addInfoWindowTabsToMarker(marker,info,options){
     GEvent.addListener(marker, "click", function() {marker.openInfoWindowTabsHtml(info,options);});
     return marker;
}

function addPropertiesToLayer(layer,getTile,copyright,opacity,isPng){
    layer.getTileUrl = getTile;
    layer.getCopyright = copyright;
    layer.getOpacity = opacity;
    layer.isPng = isPng;
    return layer;
}

function addOptionsToIcon(icon,options){
    for(var k in options){
  icon[k] = options[k];
    }
    return icon;
}

function addCodeToFunction(func,code){
    if(func == undefined)
  return code;
    else{
  return function(){
   func();
   code();
  }
    }
}

function addGeocodingToMarker(marker,address){
    marker.orig_initialize = marker.initialize;
    orig_redraw = marker.redraw;
    marker.redraw = function(force){}; //empty the redraw method so no error when called by addOverlay.
    marker.initialize = function(map){
  new GClientGeocoder().getLatLng(address,
          function(latlng){
   if(latlng){
    marker.redraw = orig_redraw;
    marker.orig_initialize(map); //init before setting point
    marker.setPoint(latlng);
   }//do nothing
  });
    };
    return marker;
}



GMap2.prototype.centerAndZoomOnMarkers = function(markers) {
     var bounds = new GLatLngBounds(markers[0].getPoint(),
         markers[0].getPoint());
     for (var i=1, len = markers.length ; i<len; i++) {
   bounds.extend(markers[i].getPoint());
     }

     this.centerAndZoomOnBounds(bounds);
 }

GMap2.prototype.centerAndZoomOnPoints = function(points) {
     var bounds = new GLatLngBounds(points[0],
         points[0]);
     for (var i=1, len = points.length ; i<len; i++) {
   bounds.extend(points[i]);
     }

     this.centerAndZoomOnBounds(bounds);
 }

GMap2.prototype.centerAndZoomOnBounds = function(bounds) {
    var center = bounds.getCenter();
    this.setCenter(center, this.getBoundsZoomLevel(bounds));
}

//For full screen mode
function setWindowDims(elem) {
    if (window.innerWidth){
  elem.style.height = (window.innerHeight) + 'px;';
  elem.style.width = (window.innerWidth) + 'px;';
    }else if (document.body.clientWidth){
  elem.style.width = (document.body.clientWidth) + 'px';
  elem.style.height = (document.body.clientHeight) + 'px';
    }
}

ManagedMarker = function(markers,minZoom,maxZoom) {
    this.markers = markers;
    this.minZoom = minZoom;
    this.maxZoom = maxZoom;
}

//Add the markers and refresh
function addMarkersToManager(manager,managedMarkers){
    for(var i = 0, length = managedMarkers.length; i < length;i++) {
  mm = managedMarkers[i];
  manager.addMarkers(mm.markers,mm.minZoom,mm.maxZoom);
    }
    manager.refresh();
    return manager;
}


var INVISIBLE = new GLatLng(0,0); //almost always invisible

if(self.Event && Event.observe){
    Event.observe(window, 'unload', GUnload);
}else{
    window.onunload = GUnload;
}

function GMarkerGroup(active, markers, markersById) {
    this.active = active;
    this.markers = markers || new Array();
    this.markersById = markersById || new Object();
}

GMarkerGroup.prototype = new GOverlay();

GMarkerGroup.prototype.initialize = function(map) {
    this.map = map;
    
    if(this.active){
	for(var i = 0 , len = this.markers.length; i < len; i++) {
	    this.map.addOverlay(this.markers[i]);
	}
	for(var id in this.markersById){
	    this.map.addOverlay(this.markersById[id]);
	}
    }
}

//If not already done (ie if not inactive) remove all the markers from the map
GMarkerGroup.prototype.remove = function() {
    this.deactivate();
}

GMarkerGroup.prototype.redraw = function(force){
    //Nothing to do : markers are already taken care of
}

//Copy the data to a new Marker Group
GMarkerGroup.prototype.copy = function() {
    var overlay = new GMarkerGroup(this.active);
    overlay.markers = this.markers; //Need to do deep copy
    overlay.markersById = this.markersById; //Need to do deep copy
    return overlay;
}

//Inactivate the Marker group and clear the internal content
GMarkerGroup.prototype.clear = function(){
    //deactivate the map first (which removes the markers from the map)
    this.deactivate();
    //Clear the internal content
    this.markers = new Array();
    this.markersById = new Object();
}

//Add a marker to the GMarkerGroup ; Adds it now to the map if the GMarkerGroup is active
GMarkerGroup.prototype.addMarker = function(marker,id){
    if(id == undefined){
	this.markers.push(marker);
    }else{
	this.markersById[id] = marker;
    }
    if(this.active && this.map != undefined ){
	this.map.addOverlay(marker);
    }
}

//Open the info window (or info window tabs) of a marker
GMarkerGroup.prototype.showMarker = function(id){
    var marker = this.markersById[id];
    if(marker != undefined){
	GEvent.trigger(marker,"click");
    }
}

//Activate (or deactivate depending on the argument) the GMarkerGroup
GMarkerGroup.prototype.activate = function(active){
    active = (active == undefined) ? true : active;
    if(!active){
	if(this.active){
	    if(this.map != undefined){
		for(var i = 0 , len = this.markers.length; i < len; i++){
		    this.map.removeOverlay(this.markers[i])
		}
		for(var id in this.markersById){
		    this.map.removeOverlay(this.markersById[id]);
		}
	    }
	    this.active = false;
	}
    }else{
	if(!this.active){
	    if(this.map != undefined){
		for(var i = 0 , len = this.markers.length; i < len; i++){
		    this.map.addOverlay(this.markers[i]);
		}
		for(var id in this.markersById){
		    this.map.addOverlay(this.markersById[id]);
		}
	    }
	    this.active = true;
	}
    }
}

GMarkerGroup.prototype.centerAndZoomOnMarkers = function() {
    if(this.map != undefined){
	//merge markers and markersById
	var tmpMarkers = this.markers.slice();
	for (var id in this.markersById){
	    tmpMarkers.push(this.markersById[id]);
	}
	if(tmpMarkers.length > 0){
    	    this.map.centerAndZoomOnMarkers(tmpMarkers);
	} 
    }
}	

//Deactivate the Group Overlay (convenience method)
GMarkerGroup.prototype.deactivate = function(){
    this.activate(false);
}


/*
* LabeledMarker Class
*
* Copyright 2007 Mike Purvis (http://uwmike.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This class extends the Maps API's standard GMarker class with the ability
* to support markers with textual labels. Please see articles here:
*
*       http://googlemapsbook.com/2007/01/22/extending-gmarker/
*       http://googlemapsbook.com/2007/03/06/clickable-labeledmarker/
*/

/* Constructor */
function LabeledMarker(latlng, options){
    this.latlng = latlng;
    this.labelText = options.labelText || "";
    this.labelClass = options.labelClass || "markerLabel";
    this.labelOffset = options.labelOffset || new GSize(0, 0);
    this.zIndex = options.zIndex || 1;

    this.clickable = options.clickable || true;

    if (options.draggable) {
    	// This version of LabeledMarker doesn't support dragging.
    	options.draggable = false;
    }

    GMarker.apply(this, arguments);
}


/* It's a limitation of JavaScript inheritance that we can't conveniently
   extend GMarker without having to run its constructor. In order for the
   constructor to run, it requires some dummy GLatLng. */
LabeledMarker.prototype = new GMarker(new GLatLng(0, 0));


// Creates the text div that goes over the marker.
LabeledMarker.prototype.initialize = function(map) {
	// Do the GMarker constructor first.
	GMarker.prototype.initialize.apply(this, arguments);

	var div = document.createElement("div");
	div.className = this.labelClass;
	div.innerHTML = this.labelText;
	div.style.position = "absolute";
	map.getPane(G_MAP_MARKER_PANE).appendChild(div);

	if (this.clickable) {
		// Pass through events fired on the text div to the marker.
		var eventPassthrus = ['click', 'dblclick', 'mousedown', 'mouseup', 'mouseover', 'mouseout'];
		for(var i = 0; i < eventPassthrus.length; i++) {
			var name = eventPassthrus[i];
			GEvent.addDomListener(div, name, newEventPassthru(this, name));
		}

		// Mouseover behaviour for the cursor.
		div.style.cursor = "pointer";
	}

	this.map = map;
	this.div = div;
}

function newEventPassthru(obj, event) {
	return function() {
		GEvent.trigger(obj, event);
	};
}

// Redraw the rectangle based on the current projection and zoom level
LabeledMarker.prototype.redraw = function(force) {
	GMarker.prototype.redraw.apply(this, arguments);

	// We only need to do anything if the coordinate system has changed
	if (!force) return;

	// Calculate the DIV coordinates of two opposite corners of our bounds to
	// get the size and position of our rectangle
	var p = this.map.fromLatLngToDivPixel(this.latlng);
	// var z = GOverlay.getZIndex(this.latlng.lat());

	// Now position our DIV based on the DIV coordinates of our bounds
	this.div.style.left = (p.x + this.labelOffset.width) + "px";
	this.div.style.top = (p.y + this.labelOffset.height) + "px";
	this.div.style.zIndex = this.zIndex + 1; // in front of the marker
}

// Remove the main DIV from the map pane, destroy event handlers
LabeledMarker.prototype.remove = function() {
	GEvent.clearInstanceListeners(this.div);
	this.div.parentNode.removeChild(this.div);
	this.div = null;
	GMarker.prototype.remove.apply(this, arguments);
}
