var DEBUG = false;

var _maps = new Array();
var _mapid = 0;

//SPRACHE
var lang_bitteWarten = 'Bitte warten...';
var lang_und = 'und';

var lang_multiKopf = 'Folgende Objekte befinden sich hier:';
var lang_multiSeiteVor = 'Seite vor &raquo;';
var lang_multiSeiteZurueck = '&laquo; Seite zur&uuml;ck';

var lang_multiEinWeiteres = '(und ein weiteres Objekt)';
var lang_multiWeitereText = '(und #N# weitere Objekte)';
function lang_multiWeitere(x) { return lang_multiWeitereText.replace(/#N#/, x); }

var lang_clustererInfo = 'Die Objekte an dieser Stelle wurden zusammengefasst, um die Darstellung zu vereinfachen. Benutzen Sie die Zoomfunktion (Knopf [+]), um sich die einzelnen Objekte anzeigen zu lassen.';

//MAP-OBJEKT
function ravMap(gm_map_name) {
	this.loaded = false;
	
	this.mapid;
	this.gm_map;
	this.gm_errorAtLevel = 0;
	this.gm_errorOriginalType = false;
	this.gm_tilesPending = false;
	this.gm_start_marker = new Array();
	this.gm_location_marker = new Array();
	
	this.icons = new Array();
	this.icon_names = new Array();
	
	this.tempAddOverlay = new Array();
	
	// diverse Einstellungen
	this.gm_max_visible_markers = 30;
	this.gm_min_markers_per_cluster = 3;
	this.gm_marker_grid_size = 10;
	this.gm_cluster_lines_per_info_box = 5;
	
	this.multiObjekteProSeite = 10;

	this.gm_map_name = gm_map_name;
	
	this.clusterer;
	this.directions;
	
	this.my_url = '?';
	this.set_my_url = function(b) {
		this.my_url = b;
	}
	
	this.MTMCbaseUrl = '/cambio/styles/gmaps/maptype/';
	this.setMTMCbaseUrl = function(burl) {
		MTMCbaseUrl = burl;
	}
	
	this.gm_show_control_overview = false;
	this.set_gm_show_control_overview = function(b) {
		this.gm_show_control_overview = b;
	}

	this.gm_show_control_large = false;
	this.set_gm_show_control_large = function(b) {
		this.gm_show_control_large = b;
		if(b) {
			this.gm_show_control_sm = false;
		}
	}

	this.gm_show_control_sm = true;
	this.set_gm_show_control_sm = function(b) {
		this.gm_show_control_sm = b;
		if(b) {
			this.gm_show_control_large = false;
		}
	}

	this.gm_show_control_type = true;
	this.set_gm_show_control_type = function(b) {
		this.gm_show_control_type = b;
		if(b) {
			this.gm_show_control_type_sm = false;
		}
	}

	this.gm_show_control_type_sm = false;
	this.set_gm_show_control_type_sm = function(b) {
		this.gm_show_control_type_sm = b;
		if(b) {
			this.gm_show_control_type = false;
		}
	}

	this.gm_show_control_scale = true;
	this.set_gm_show_control_scale = function(b) {
		this.gm_show_control_scale = b;
	}

	this.gm_show_control_vergroessern = false;
	this.set_gm_show_control_vergroessern = function(b) {
		this.gm_show_control_vergroessern = b;
	}	
	
	
	this.gm_center = null;
	this.set_gm_center = function(lat,lng) {
		if(lat && lng) {
			this.gm_center = new GLatLng(lat,lng);
		} else {
			this.gm_center = null;
		}
	}

	this.gm_zoom = null;
	this.set_gm_zoom = function(c) {
		if(c > 0 && c <= 17) {
			this.gm_zoom = c;
		}
		else {
			this.gm_zoom = null;
		}
	}

	this.gm_type = 'G_NORMAL_MAP';
	this.set_gm_type = function(c) {
		if(this.gm_type)
			this.gm_type = c;
	}	

	this.static_map = false;
	this.set_static_map = function(c) {
		this.static_map = c;
	}

	this.selected = -1;
	this.set_selected = function(c) {
		this.selected = c;
	}

	this.icon_default = null;
	this.set_icon_default = function(name) {
		this.icon_default = this.findIcon(name);
	}

	this.icon_clusterer = null;
	this.set_icon_clusterer = function(name) {
		this.icon_clusterer = this.findIcon(name);
	}

	this.icon_selected = null;
	this.set_icon_selected = function(name) {
		this.icon_selected = this.findIcon(name);
	}

	this.icon_clusterer_selected = null;
	this.set_icon_clusterer_selected = function(name) {
		this.icon_clusterer_selected = this.findIcon(name);
	}
}

/*
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
||| Methoden
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
*/

//enclosure f?r funtionen im listener - wie beim clusterer
function ravMakeCaller( func, arg, m ) {
		return function () { func( arg, m ); };
	};
function ravMakeCaller_mitArg( func, m ) {
		return function (arg) { func( arg, m ); };
	};


ravMap.prototype.private_gm_click_listener = function(overlay, mapid) {
		// ist dummerweise auch manchmal was anderes als ein marker
		if (overlay && overlay.openInfoWindowHtml) {
			_maps[mapid].private_handlemarkerclick(overlay, _maps[mapid].gm_start_marker, mapid);
			_maps[mapid].private_handlemarkerclick(overlay, _maps[mapid].gm_location_marker, mapid);
		}
	}
ravMap.prototype.private_gm_drag_listener = function(m) {
		m.gm_map.closeInfoWindow();
	}
/* ravMap.prototype.private_gm_zoom_listener = function(vorher, nachher) {
		alert(nachher);
	} */
/* ravMap.prototype.private_gm_drag_listener = function(m) {
		m.gm_map.closeInfoWindow();
	} */
	
ravMap.prototype.private_handlemarkerclick = function(marker, gmarr) {
	for(var i=0; i < gmarr.length; ++i) {
		var gm = gmarr[i];
		if(marker.getPoint().equals(gm.latlng_)) {	
			this.private_handlemarkerclick_click(gm);
			break;
		}
	}
}

ravMap.prototype.private_handlemarkerclick_click = function(gm) {
	//Nichts anzeigen
	if(gm.noinfowindow_ === true)
		return false;
		
	//Eigene Onclick-Funktion
	if(gm.onclick_) {
		//AJAX-Kram?
		if(gm.onclick_(gm) === true) {
			gm.marker_.openInfoWindowHtml(lang_bitteWarten);
		}
		
		//Fertig
		return false;
	}
	
	
	if( gm.text_) { 
		//InfoWindow mit Text zeigen
		gm.marker_.openInfoWindowHtml(gm.text_);
	} else if( gm.gotlocation_) {
		//Zu Seite gehen
		document.location = gm.gotlocation_				
	} else {
		//Minikarte zeigen
		gm.marker_.showMapBlowup();
	}
}

ravMap.prototype.newIcon = function(file, size, anchor, windowanchor) {
	var icon = new GIcon();
	icon.image = file;
	icon.iconSize = new GSize(size[0], size[1]);
	icon.iconAnchor = new GPoint(anchor[0], anchor[1]);
	icon.infoWindowAnchor = new GPoint(windowanchor[0], windowanchor[1]);
	return icon;
}

ravMap.prototype.insertIcon = function(name, file, size, anchor, windowanchor) {
	this.icons.push(this.newIcon(file, size, anchor, windowanchor));
	this.icon_names.push(name);
}


ravMap.prototype.findIcon = function(name) {
	if(name == null) return this.icon_default;
	
	for(var i = 0; i < this.icon_names.length; i++) {
		if(this.icon_names[i] == name) return this.icons[i];
	}
	
	return false;
}

ravMap.prototype.load = function() {
	this.mapid = _mapid++;
	_maps[this.mapid] = this;
	
	//try {
		if(this.gm_map_name == undefined) {
			alert('Keine DIV-Id bekannt: '+this.gm_map_name);
			return false;
		}
		
		if (GBrowserIsCompatible()) {
			var map_div = document.getElementById(this.gm_map_name);
			this.gm_map = new GMap2(map_div);
			this.gm_map.setCenter(new GLatLng(0,0));

			var ll;
			var bounds = new GLatLngBounds();
			
			//Startpunkt zeigen
			this.private_gm_show_start(bounds);
			
			//MapTyp setzen - muss mit eval sein, da wir Strings kriegen aber Objekte brauchen
			this.gm_map.setMapType(eval(this.gm_type));
			
			//CLUSTERER
			//http://www.acme.com/javascript/#Clusterer
			var clusterer = new Clusterer(this.gm_map);
			this.clusterer = clusterer;
			clusterer.SetMaxVisibleMarkers(this.gm_max_visible_markers);
			clusterer.SetMinMarkersPerCluster(this.gm_min_markers_per_cluster);
			clusterer.SetGridSize(this.gm_marker_grid_size);			
			clusterer.SetMaxLinesPerInfoBox(this.gm_cluster_lines_per_info_box);
			
			if(this.icon_clusterer != null) {
				clusterer.SetIcon(this.icon_clusterer);
			}

			//CONTROLS
			if(this.gm_show_control_large) {
				this.gm_map.addControl(new GLargeMapControl());		
			}

			if(this.gm_show_control_sm) {
				this.gm_map.addControl(new GSmallMapControl());		
			}

			if(this.gm_show_control_scale) {
				this.gm_map.addControl(new GScaleControl());
			}

			if(this.gm_show_control_type) {
				this.gm_map.addControl(new GMapTypeControl());
			}
			
			if(this.gm_show_control_overview) {
				this.gm_map.addControl(new GOverviewMapControl());
			}

			if(this.gm_show_control_vergroessern) {
				this.gm_map.addControl(new ravVergroessern(this.mapid));
			}

			//http://maps.tafoni.net/MapTypeMenuControl/	
			if(this.gm_show_control_type_sm) {
				MTMC.addMapControl(this.gm_map, new MTMC.MapTypeMenuControl());
			}
			
			//overlays hinzufuegen
			// --  muss nach dem zentrieren passieren
			for(var iAddOverlay = 0; iAddOverlay < this.tempAddOverlay.length; iAddOverlay++) {
				this.gm_map.addOverlay(this.tempAddOverlay[iAddOverlay]);
			}

			//andere symbole vorbereiten
			this.private_gm_show_locations(clusterer,bounds);
			
			//ausgewaehlte markers - vorm zoom damit der clusterer die nochmal rendert
			if(this.selected > -1)
				this.selectMarker(this.selected);
			
			this.center_and_zoom(bounds);
			
			if(this.static_map) {
				map.gm_map.disableDragging();
				map.gm_map.disableInfoWindow();
			} else {
				//Mouse Zoom ermoeglichen
				this.gm_map.enableContinuousZoom();
				this.gm_map.enableScrollWheelZoom();
			}
			
			//Klicks abfangen
			GEvent.addListener(this.gm_map, 'click',
				ravMakeCaller_mitArg(ravMap.prototype.private_gm_click_listener, this.mapid) 
				); //mitArg fuer overlay-parameter, this fuer zugriff auf objekt aus funktion heraus
				
			//Scrollen der Seite verhindern
			GEvent.addDomListener(map_div, "DOMMouseScroll", wheelevent);
			map_div.onmousewheel = wheelevent;
			
			/*
			//Rauszoomen wenn Kartenmaterial fehlt
			G_NORMAL_MAP.getErrorMessage = function() {
				var z = gm_map.getZoom();
				if (z > 8 && !gm_tilesPending) {
					gm_map.setZoom(z - 1);
					//alert('Die Zoomstufe wurde automatisch verkleinert, da leider kein Kartenmaterial fuer eine so hohe Zoomstufe vorhanden ist.');
					
				}
				return "";
			};
			
			//Zu normaler Map wechseln wenn Kartenmaterial fehlt
			G_HYBRID_MAP.getErrorMessage = function () {
				//alert('mt1');
				gm_errorAtLevel = gm_map.getZoom();
				gm_errorOriginalType = gm_map.getCurrentMapType();
				gm_map.setMapType(G_NORMAL_MAP); 
				//alert('mt1k');
			};
			G_SATELLITE_MAP.getErrorMessage = G_HYBRID_MAP.getErrorMessage;
			*/			
		} else {
			//Eventuell Meldung anzeigen
		}
	//} catch(e) {
	//	alert('Es ist ein Fehler aufgetreten:' + e);
	//}
	
	this.loaded = true;
}


//Automatisch zoomen und zentrieren
ravMap.prototype.center_and_zoom = function(bounds) {	
	if(this.gm_center != null ) {
		var center = this.gm_center;
	} else {
		var center = bounds.getCenter();
	}
	
	//TODO: Derzeit ist hierdurch gm_zoom die maximale Zoomstufe
	//und kann durch die bounds ueberschrieben werden.
	//Dadurch ist sichergestellt, dass immer alle Marker angezeigt werden.
	//- ist das immer so gewollt?
	// 08-20: Nein
	if(this.gm_zoom != null) {
/* 		if(this.gm_map.getBoundsZoomLevel(bounds) < this.gm_zoom) {
			var zoom = this.gm_map.getBoundsZoomLevel(bounds);
		} else { */
			var zoom = this.gm_zoom;
/* 		} */
	} else {
		//Kein maximaler Zoom - soweit es geht ranzoomen
		var zoom = this.gm_map.getBoundsZoomLevel(bounds);
	}
	
	this.gm_map.setCenter(center, zoom);
}


ravMap.prototype.unload = function() {
	this.loaded = false;
	GUnload();
}


/**
	zoom is standard zoom factor
	if diff > 0 we might use it to extend selection
	a little be decreasing zoom factor
*/

ravMap.prototype.zoom_in_details = function(zoom,lat,lng,diff) {
	if (GBrowserIsCompatible() && this.gm_map != null) {
		// sicher stellen, dass alles zugemacht wird
		// wenn etwas offen ist - macht sonst probleme
		// aus einem Fenster raus zu justieren
		this.gm_map.closeInfoWindow();
		this.gm_map.setCenter(new GLatLng(lat,lng));

		if(zoom == null) {
			zoom = this.gm_zoom;
		}
		if(zoom == null) {
			zoom = 10;
		}
		
		if(diff) {
			var sub = Math.log(diff + 0.6)/Math.LN2;
			//alert("zoom: " + sub);
			// we assume we can cover about 1km
			if(sub > 0 ) { 
				zoom = Math.floor(zoom - sub);
				if(zoom < 1) {
					zoom = 1;
				}
			}
			//alert("zoom: " + zoom);
			this.gm_map.setZoom(zoom);
		}
		else {
			this.gm_map.setZoom(zoom);
		}
	}
}

ravMap.prototype.addDraggableMarker = function() {	
	var center = this.gm_map.getCenter();
	var marker = new GMarker(this.center, {draggable: true});
	
	GEvent.addListener(marker, 'dragstart',
		GEvent.callbackArgs(ravMap, ravMap.prototype.private_gm_drag_listener, this)
		);
	
	GEvent.addListener(marker, "dragend", function() {
	  	marker.openInfoWindowHtml("Momentane Koordinaten (L&auml;ngengrad,Breitengrad)<br>" + marker.getPoint());
	  });
	
	this.gm_map.addOverlay(marker);
}


ravMap.prototype.addTextOverlay = function(point,text,maxzoom) {
	var to = new TextOverlay(point,text,maxzoom);
	this.gm_map.addOverlay(to);
	return to;
}


ravMap.prototype.add_startmarker = function(lat,lng,txt,label,titel,url,hide,drag) {
	var loc = new RWLocation(new GLatLng(lat,lng),txt,label,titel,null,url,hide,drag);
	this.gm_start_marker.push(loc);	
	return loc;
}

ravMap.prototype.private_gm_show_start = function(bounds) {
	for(var i=0; i < this.gm_start_marker.length; ++i) {
		var gm = this.gm_start_marker[i];
		var marker = null;

		if(gm.draggable_) {
			marker = new GMarker(gm.latlng_, {icon: this.gm_start_icon, draggable: true});
			GEvent.addListener(marker, 'dragstart',
				GEvent.callbackArgs(ravMap, ravMap.prototype.private_gm_drag_listener, this)
				);
	
			if(gm.editable_) {					
                GEvent.addListener(this.gm_map, "zoomend", function(vorher, nachher) {
						if(vorher && nachher && vorher != nachher) {
							if(gm.edit_form_ != null) {
								gm.edit_form_.gm_edit_zoom.value = nachher;
/* 								gm.edit_form_.gm_edit_zoom.style.backgroundColor = "lightgreen";
								gm.edit_form_.gm_edit_button.style.backgroundColor = "lightgreen" */
							}
						}
					});
                GEvent.addListener(marker, "dragend", GEvent.callbackArgs(ravMap, function(m) {
                //GEvent.addListener(marker, "dragend", function() {
					var point =  marker.getPoint();
					if(false) {
						var html = "Momentane Koordinaten<br>" +point + "<br>"
							+ '<form action="" method="GET">'
							+ '<input type="hidden" name="gm_edit_lat" value="' + point.lat() + '">'
							+ '<input type="hidden" name="gm_edit_lng" value="' + point.lng() + '">'
							+ '<input type="hidden" name="gm_edit_zoom" value="' + m.gm_map.getZoom() + '">'
							+ '<input type="hidden" name="gm_edit_update" value="true">'
							+ '<input type="hidden" name="gm_edit_id" value="' + gm.edit_id_+ '">'
							+ '<input type="submit" name="dummy" value="eintragen">'
							+ '</form>'
							;
					  	marker.openInfoWindowHtml(html);
				  	}
					// oder	
					else {
						var html = "<b>" + gm.commonname_ + "</b><br>"
							+ "Momentane Koordinaten<br>" +point + "<br>"
					
						if(gm.edit_form_ != null) {
							gm.edit_form_.gm_edit_lng.value = point.lng();
							gm.edit_form_.gm_edit_lat.value = point.lat();
							gm.edit_form_.gm_edit_zoom.value = m.gm_map.getZoom();
/* 							gm.edit_form_.gm_edit_lat.style.backgroundColor  = "lightgreen"
							gm.edit_form_.gm_edit_lng.style.backgroundColor = "lightgreen"
							gm.edit_form_.gm_edit_zoom.style.backgroundColor = "lightgreen"
							gm.edit_form_.gm_edit_button.style.backgroundColor = "lightgreen" */
						}	
					  	marker.openInfoWindowHtml(html);
					  }
				  // });
                  },this));
 			}
			else {
				GEvent.addListener(marker, "dragend", function() {
				  	marker.openInfoWindowHtml("Momentane Koordinaten<br>" + marker.getPoint());
				  });
			}  
		}
		else {
			marker = new GMarker(gm.latlng_, this.gm_start_icon);
		}
		
		//this.gm_map.addOverlay(marker);
		this.tempAddOverlay.push(marker);
		
		if(gm.includeinbounds_) {
			bounds.extend(gm.latlng_);
		}
		
		if(gm.label_) {
			//  TODO 12 als zoomstufe festverdrahet
			var to = this.addTextOverlay(gm.latlng_,gm.label_,12);
		}
		
		if(gm.hide_) {
			marker.hide();
		}
		
		/*//Klicks abfangen
		GEvent.addListener(marker, 'click',
			GEvent.callbackArgs(ravMap, ravMap.prototype.private_gm_click_listener, marker, this)
			);*/
	}
}

ravMap.prototype.add_locationmarker = function(lat,lng,txt,label,title,clustertext,url,hide,drag) {
	//if(DEBUG) alert("Adding location marker: " + lat + "/" + lng + "");
	
	var latlng = new GLatLng(lat,lng);
	var loc = new RWLocation(latlng,txt,label,title,clustertext,url,hide,drag);
	return this.insert_locationmarker(loc);
}


ravMap.prototype.insert_locationmarker = function(loc) {	
	//Doppelte suchen
	for(var i = 0; i < this.gm_location_marker.length; i++) {			
		if(this.gm_location_marker[i].latlng_.equals(loc.latlng_)) {
			if(!this.gm_location_marker[i].isMulti) {
				var multi = new RWMultiLocation(loc.latlng_);
				multi.daten.push(this.gm_location_marker[i]);
			} else {
				var multi = this.gm_location_marker[i];
			}
				
			multi.daten.push(loc);
			multi.clustertext_ = multi.daten[0].clustertext_ + ' ' + 
				((multi.daten.length > 2)? lang_multiWeitere(multi.daten.length - 1) : lang_multiEinWeiteres);
					//: lang_und + ' ' + multi.daten[1].clustertext_);
			
			this.gm_location_marker[i] = multi;
			
			loc.i_ = i;
			return loc;
		}
	}
	
	//Wir sind noch hier - neu hinzufuegen
	this.gm_location_marker.push(loc);
	loc.i_ = this.gm_location_marker.length - 1;
	return loc;
}

ravMap.prototype.private_gm_show_locations = function(clusterer, bounds) {
	for(var i=0; i < this.gm_location_marker.length; ++i) {
		var gm = this.gm_location_marker[i];
		
		if(DEBUG) alert("Showing location marker: " + gm.latlng_);
		
		var icon;
		if(!(icon = this.findIcon(gm.getIcon())))
			icon = this.gm_locations_icon;
		
		if(gm.title_) {
			marker = new GMarker(gm.latlng_, {'icon': icon, 'title': gm.title_});
		} else {
			marker = new GMarker(gm.latlng_, icon);
		}
		
		//Daten im Objekt merken
		gm.mapid_ = this.mapid;
		gm.i_ = i;
		gm.marker_ = marker;
		
		//Fuer Liste im Clusterer
		gm.clustertext_ = this.mapid + "|" + i + "|" + gm.clustertext_;
		
		if(gm.clustertext_) {
			clusterer.AddMarker(marker, gm.clustertext_);
		}
		else if(gm.text_) {
			clusterer.AddMarker(marker, gm.text_);
		}
		else if(gm.title_) {
			clusterer.AddMarker(marker, gm.title_);
		}
		else if(gm.label_) {
			clusterer.AddMarker(marker, gm.label_);
		}
		else {
			clusterer.AddMarker(marker, '--');
		}
		
		/*GEvent.addListener(marker, 'click',
			GEvent.callbackArgs(ravMap, ravMap.prototype.private_gm_click_listener, marker, this)
			);*/
		
		if(gm.includeinbounds_) {
			bounds.extend(gm.latlng_);
		}
			
		if(gm.label_) {
			//  TODO 12 als zoomstufe festverdrahet
			var to = this.addTextOverlay(gm.latlng_,gm.label_,12);
			/*		
				TODO wie machen wir das
					GEvent.addListener(to, 'click',
							function(maker, point) {
			//					gm_click_listener(marker,point);
								alert("test");
							}
						);
			*/				
		}
	}
}

ravMap.prototype.selectMarker = function(index) {
	this.selected = index;
	
	var gm;
	for(var i = 0; i < this.gm_location_marker.length; i++) {
		gm = this.gm_location_marker[i];
		if(gm.selected) {
			if(i != index) {
				//andere markierung entfernen
				gm.unselect();
				break;
			} else {
				//ist schon markiert
				return;
			}
		}
	}
	
	this.gm_location_marker[index].select();
	
	//Clusterer refreshen
	//this.clusterer.DisplayLater();
}
	
ravMap.prototype.showRoute = function(index, adresse, external) {
	if(adresse) {
		if(!external && !this.directions) {
			this.directions = new GDirections(this.gm_map);
			GEvent.addListener( this.directions, "load", ravMakeCaller(ravMap_routeLoad, this.mapid) );
			GEvent.addListener( this.directions, "error", ravMakeCaller(ravMap_routeError, this.mapid) );
		}
	
		var dirString = "from: " + adresse + " to: " + this.gm_location_marker[index].latlng_.toUrlValue();
		
		if(!external) {
			this.directions.load( dirString, { 'locale': 'de' } );
		} else {
			window.open("http://maps.google.de/"
				+"?q="+encodeURIComponent(dirString)+"&t="+this.gm_map.getCurrentMapType().getUrlArg()
				, "_blank");
		}
	}
}
	
ravMap_routeLoad = function(mapid) {
	_maps[mapid].gm_map.closeInfoWindow();
}

ravMap_routeError = function(mapid) {
	var dir = _maps[mapid].directions;
	
	var msg;
	
	if (dir.getStatus().code == G_GEO_UNKNOWN_ADDRESS)
	msg = "No corresponding geographic location could be found for one of the specified addresses. This may be due to the fact that the address is relatively new, or it may be incorrect.\nError code: " + dir.getStatus().code;
	
	else if (dir.getStatus().code == G_GEO_SERVER_ERROR)
	msg = "A geocoding or directions request could not be successfully processed, yet the exact reason for the failure is not known.\n Error code: " + dir.getStatus().code;

	else if (dir.getStatus().code == G_GEO_MISSING_QUERY)
	msg = "The HTTP q parameter was either missing or had no value. For geocoder requests, this means that an empty address was specified as input. For directions requests, this means that no query was specified in the input.\n Error code: " + dir.getStatus().code;

	else if (dir.getStatus().code == G_GEO_BAD_KEY)
	msg = "The given key is either invalid or does not match the domain for which it was given. \n Error code: " + dir.getStatus().code;

	else if (dir.getStatus().code == G_GEO_BAD_REQUEST)
	msg = "A directions request could not be successfully parsed.\n Error code: " + dir.getStatus().code;
	    
	else
	msg = "An unknown error occurred.";
	
	alert('Es ist ein Fehler aufgetreten:'
		+ "\n\n" + msg);
}

/* ravMap.prototype.findMyMapType = function() {
	var curr = this.gm_map.getCurrentMapType();
	alert(curr);
} */


/*
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
||| Andere Objekte + Funktionen
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
*/

//Scrollen der Seite verhindern
//aus .load aufgerufen
function wheelevent(e) {
	if (!e) e = window.event;
	
	if (e.preventDefault) e.preventDefault();
	e.returnValue = false;
}

function gm_show_otherpage(url) {
	if(window.name == 'gminnermap') {
		window.parent.location = url;
	}
	else {
		window.location = url;
	}
}
	
//Vergroessern
function ravVergroessern(mapid) {
	this.mapid = mapid;
	this.initialize = function(gm_map) {
		var div = document.createElement("div");
			
		div.style.textDecoration = "underline";
		div.style.color = "#0000cc";
		div.style.backgroundColor = "white";
		div.style.font = "small Arial";
		div.style.borderTop = "1px solid black";
		div.style.borderLeft = div.style.borderTop;
		div.style.padding = "2px";
		div.style.textAlign = "center";
		div.style.width = "6em";
		div.style.cursor = "pointer";
			
		div.appendChild(document.createTextNode("Vollansicht"));
			
		GEvent.addDomListener(div, "click", function() {
			var map = _maps[mapid];
			window.open(map.my_url + 'gm_zoom=' + gm_map.getZoom() + '&gm_center_lat=' + gm_map.getCenter().lat()
				+ '&gm_center_lng=' + gm_map.getCenter().lng() + '&gm_type=' + ''
				 + '&gm_breite=700&gm_hoehe=500', '_blank', 'width=700,height=500');
		});
			
		gm_map.getContainer().appendChild(div);
		return div;
	}
}
ravVergroessern.prototype = new GControl();
ravVergroessern.prototype.getDefaultPosition = function() {
	return new GControlPosition(G_ANCHOR_BOTTOM_RIGHT, new GSize(0, 0));
}




/*
	Auswahl aus einer Liste mit gegebener lat,lng suchen 
*/
function submitSelectLocation(form, strasse, hausnr, plz, ort, lat, lng) {
	if(strasse) {	
		var hn = form.gm_hausnr.value;
		if( hn != '' && hausnr == '') {
			var idx = strasse.lastIndexOf(hn);
			if(idx == (strasse.length - hn.length) ) {
				hausnr = hn;
				strasse = strasse.substring(0,idx);
			}
		}
	}
	else {	strasse = "";	}
	form.gm_strasse.value = strasse;

	if(hausnr) {	}
	else {	hausnr = "";	}
	form.gm_hausnr.value = hausnr;

	if(ort) {	}
	else {		ort = "";	}
	form.gm_ort.value = ort;

	if(plz) {	}
	else {		plz = "";	}
	form.gm_plz.value = plz;

	if(lat) {	}
	else {		lat = "";	}
	form.gm_lat.value = lat;

	if(lng) {	}
	else {		lat = "";	}
	form.gm_lng.value = lng;
	
	form.submit();
}



// A Rectangle is a simple overlay that outlines a lat/lng bounds on the
// map. It has a border of the given weight and color and can optionally
// have a semi-transparent background color.
function TextOverlay(point,text,maxzoom,background) {
  this.latlng_ = point;
  this.text_ = text;
  this.maxzoom_ = 0 || maxzoom;
  this.background_ = background || 'white';  
}

TextOverlay.prototype = new GOverlay();

// Creates the DIV representing this rectangle.
TextOverlay.prototype.initialize = function(map) {
  // Create the DIV representing our rectangle
  var div = document.createElement("div");
  div.style.border = "1px solid black";
  div.style.position = "absolute";
  div.style.fontSize = "9px";
  div.style.paddingLeft = "2px";
  div.style.paddingRight = "2px";
  div.style.paddingTop = "0px";
  div.style.paddingBottom = "0px";
  //div.style.cursor = "pointer";
  div.style.backgroundColor = this.background_;
  div.appendChild(document.createTextNode(this.text_));
  // Our rectangle is flat against the map, so we add our selves to the
  // MAP_PANE pane, which is at the same z-index as the map itself (i.e.,
  // below the marker shadows)
  map.getPane(G_MAP_MAP_PANE).appendChild(div);

  this.map_ = map;
  this.div_ = div;
  
  
}

// Remove the main DIV from the map pane
TextOverlay.prototype.remove = function() {
  this.div_.parentNode.removeChild(this.div_);
}

// Copy our data to a new Rectangle
TextOverlay.prototype.copy = function() {
  return new TextOverlay(this.latlng_,this.text_);
}

// Redraw the rectangle based on the current projection and zoom level
TextOverlay.prototype.redraw = function(force) {
  // We only need to redraw 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 c1 = this.map_.fromLatLngToDivPixel(this.latlng_);

  // Now position our DIV based on the DIV coordinates of our bounds
  //this.div_.style.width = Math.abs(c2.x - c1.x) + "px";
  //this.div_.style.height = Math.abs(c2.y - c1.y) + "px";
  this.div_.style.left = c1.x + "px";
  this.div_.style.top = c1.y + "px";
  
  if(this.map_.getZoom() < this.maxzoom_) {
  	this.div_.style.visibility = 'hidden';
  }
  else {
  	this.div_.style.visibility = 'visible';
  }
}


function RWLocation(latlng,text,label,title,clustertext,url,hide,draggable) {
	this.mapid_ = 0;
	this.i_ = 0;
	this.marker_ = null
	
	this.latlng_ = latlng;
	this.text_ = text;
	this.label_ = label;
	this.title_ = title || null;
	this.clustertext_ = clustertext || null;
	this.gotlocation_ = url || null;
	this.hide_ = hide || false;
	this.draggable_ = draggable || false;

	this.includeinbounds_ = true;
	this.editable_ = false;
	this.edit_id_ = -1;
	this.edit_form_ = null;
	this.commonname_ = null;
	this.noinfowindow_ = false;
	this.onclick_ = null;
	this.icon_ = null;
  
	this.setLatLng = function(b) {
		this.latlng_ = b;
	}
	this.setText = function(b) {
		this.text_ = b;
	}
	this.setLabel = function(b) {
		this.label_ = b;
	}
	this.setTitle = function(b) {
		this.title_ = b;
	}
	this.setClusterText = function(b) {
		this.clustertext_ = b;
	}
	this.setGotLocation = function(b) {
		this.gotlocation_ = b;
	}
	this.setHide = function(b) {
		this.hide_ = b;
	}
	this.setDraggable = function(b) {
		this.draggable_ = b;
	}
  	
	this.setIncludeInBounds  = function( b )   {
		this.includeinbounds_ = b;
	};

	this.setEditable = function( b) {
		this.editable_ = b;
	};

	this.setEditId = function(i)  {
	this.edit_id_ = i;
	};

	this.setEditForm = function(f)  {
	this.edit_form_ = f;
	};

	this.setCommonName = function(n)  {
	this.commonname_ = n;
	};

	this.setOnclick = function(n)  {
		this.onclick_ = n;
	};
	
	this.setNoInfoWindow = function(n)  {
		this.noinfowindow_ = n;
	};
	
	this.setIcon = function(n)  {
		if(n) this.icon_ = n;
	};	
	this.getIcon = function(n)  {
		return this.icon_;
	};  
	
	this.oldmarker = null;
	this.selected = false;	
}

//Doch lieber so, setImage macht Probleme mit clusterer
RWMultiLocation.prototype.select = RWLocation.prototype.select = function() {		
	//Alten Marker entfernen und merken
	_maps[this.mapid_].clusterer.RemoveMarker(this.marker_);
	this.oldmarker = this.marker_;
	
	//Selected Marker erstellen
	this.marker_ = new GMarker(this.oldmarker.getPoint(), _maps[this.mapid_].icon_selected);
	//_maps[this.mapid_].gm_map.addOverlay(this.marker_);
	_maps[this.mapid_].clusterer.AddMarker(this.marker_, this.clustertext_);
	
	this.selected = true;
}

RWMultiLocation.prototype.unselect = RWLocation.prototype.unselect = function() {
	//Selected Marker entfernen
	//_maps[this.mapid_].gm_map.removeOverlay(this.marker_);
	_maps[this.mapid_].clusterer.RemoveMarker(this.marker_);
	
	//Alten Marker wiederherstellen
	this.marker_ = this.oldmarker;
	_maps[this.mapid_].clusterer.AddMarker(this.marker_, this.clustertext_);
	
	this.selected = false;
}

RWMultiLocation.prototype.getMap = RWLocation.prototype.getMap = function() {
	return _maps[this.mapid_];
}

/* RWMultiLocation.prototype.select = RWLocation.prototype.select = function() {
	try {
		if(this.marker_.getIcon()) {
			//Der Clusterer macht hier Aerger
			this.oldimage = this.marker_.getIcon().image;
			this.marker_.setImage(_maps[this.mapid_].iconfile_selected);
		}
	} catch(e) {  }
	
	this.selected = true;
}

RWMultiLocation.prototype.unselect = RWLocation.prototype.unselect = function() {
	if(this.oldimage) {
		this.marker_.setImage(this.oldimage);
	}
	
	this.selected = false;
} */

function RWMultiLocation(latlng) {
	this.isMulti = true;
	
	this.mapid_ = -1;
	this.i_ = -1;
	this.marker_ = null;
	this.includeinbounds_ = true;
	this.latlng_ = latlng;
	this.clustertext_ = null;
	this.onclick_ = function(gm) { return RWMultiLocation_handleOnclick(gm, 0) };
	this.icon_ = null;
	
	this.daten = new Array();
	
	this.getIcon = function(n)  {
		var icon = null;
		for(var i = 0; i < this.daten.length; i++) {
			if(this.daten[i].getIcon() == this.icon_) {
				//Kann nur noch Standardicon werden
				return this.icon_;
			} else if(icon == null) {
				//Icon erstmal setzen
				icon = this.daten[i].getIcon();
			} else if(this.daten[i].getIcon() != icon) {
				//Verschiedenen Icons, Standard zurueckgeben
				return this.icon_;
			}
		}
		
		//Gleiche Icons
		return icon;
	};  
}


RWMultiLocation_handleOnclick = function(multi, start) {
	if(start == null) start = 0;
	
	var html = '<div class="multi">';
	
	//Liste
	html += '<div class="multi_kopf">'+lang_multiKopf+'</div>';
	for(var i = start; i < multi.daten.length && i < start + _maps[multi.mapid_].multiObjekteProSeite; i++) {
		html += '<a class="multi_objekt" href="javascript:void(0);"'
			+ ' onclick="return RWMultiLocation_handleZeigeObjekt('+multi.mapid_+', '+multi.i_+', '+i+')">'
			+ multi.daten[i].clustertext_ + '</a>';
	}
	
	//Seitenanzeige
 	if(i < multi.daten.length) html += '<a class="vor" href="javascript:void(0);"'
		+ ' onclick="return RWMultiLocation_handleOnclick(' + mapid + ', ' + multiid + 
			', ' + (start + _maps[mapid].multiObjekteProSeite) +')">'
		+ lang_multiSeiteVor + '</a>';
	if(start > 0) html += '<a class="zurueck" href="javascript:void(0);"'
		+ ' onclick="return RWMultiLocation_handleOnclick(' + mapid + ', ' + multiid + 
			', ' + (start - _maps[mapid].multiObjekteProSeite) +')">'
		+ lang_multiSeiteZurueck + '</a>'; 
		
	html += '</div>';
	multi.marker_.openInfoWindowHtml(html);
	return false;
}

RWMultiLocation_handleZeigeObjekt = function(mapid, multiid, objektid) {
	var multi = _maps[mapid].gm_location_marker[multiid];
	//alert([mapid, multiid, objektid, multi]);
	multi.daten[objektid].marker_ = multi.marker_;
	_maps[mapid].private_handlemarkerclick_click(multi.daten[objektid]);
}

function clusterer_getMarkerFromTitle(clustertext) {
	var daten = clustertext.split("|", 3);
	return _maps[daten[0]].gm_location_marker[daten[1]];
}

