
function adr(GMap, StatusZeile, verschiebbar) {
	//alert("Constructor("+GMap+", "+Status+")");
	google.load("maps", "2.x");
	obj = new Object();
	obj.gmap_div = GMap;
	obj.status_div = StatusZeile;
	obj.draggable = verschiebbar;
	
	//Default-Werte
	var normflagFile = "/img/normflag.png";
	var newflag  = "/img/newflag.png";
	var dragflag = "/img/dragflag.png";
	obj.dfault = new Object();
	obj.dfault.lat = 13.5;
	obj.dfault.lng = 47.5;
	obj.dfault.zoom = 6;
	//obj.dfault.mapType = "G_PHYSICAL_MAP";	//Seufz... ist noch hard-codiert
	
	//Instanzvariable
	obj.initcallback;	//Initialisierung fertich?
	obj.foundcallback;	//ggf. die Koordinaten zurückliefern
	obj.status = 0;	//= Uninitialized
	obj.address;
	obj.coords;
	obj.place;
	obj.dragged = false;
	obj.marker = null;
	
	obj.map;
	obj.geocoder;
	google.setOnLoadCallback(init);
	function init() {
		//alert("Init:"+obj.gmap_div+google.maps.BrowserIsCompatible());
		if(obj.gmap_div) {
			normflag = new google.maps.Icon(G_DEFAULT_ICON, normflagFile);
			obj.map = new google.maps.Map2(obj.gmap_div);
			//google.maps.Event.addListener(obj.map, 'load', mapReady);
			obj.geocoder = new google.maps.ClientGeocoder();
			obj.map.addControl(new google.maps.SmallMapControl());
		//	obj.map.addControl(new google.maps.SmallZoomControl());
			obj.map.addControl(new google.maps.MapTypeControl());
			obj.map.addControl(new google.maps.OverviewMapControl());
			//obj.map.enableScrollWheelZoom();
			obj.map.enableContinuousZoom();
			//obj.map.setMapType(G_HYBRID_MAP);	//geht ned!!!
			obj.map.setCenter(new google.maps.LatLng(obj.dfault.lng, obj.dfault.lat), obj.dfault.zoom, G_PHYSICAL_MAP);	//Default
//			google.maps.Event.addListener(obj.map, 'zoomend', obj.zoomEnd);	//geht ned!!
			//map.setCenter(new google.maps.LatLng(37.4419, -122.1419), 13);
		//	google.maps.Event.addListener(map, 'moveend', getFlags(map.getBounds(), maxFlags));
			//google.maps.Event.addListener(map, 'moveend', getFlags);
			//google.maps.Event.addListener(map, 'zoomend', getFlags);
		//	google.maps.Event.addListener(map, 'load', setFlags);
		}
		if(obj.map && obj.geocoder) {	//Versuch geglückt? (Netzwerk)
			google.maps.Event.clearInstanceListeners(obj.map);	//evtl. Reste entsorgen
/*			if(!obj.map.isLoaded())
				google.maps.Event.addListener(obj.map, 'load', mapReady);
			else */
				mapReady();
		}
		
		function mapReady() {
			if(obj.status<2) obj.showStatus(++obj.status);	//Ready
			obj.update();	//falls (schon) möglich
			if(obj.initcallback && obj.status>1) obj.initcallback(obj.status);	//Jetz aber!...
		}
	}
	
	obj.showStatus = function(stat) {
		//alert("ShowStatus("+stat+document.getElementById(obj.status_div));
		if(stat) obj.status = stat;
	//	if(obj.status>1 && obj.dragged) obj.status = 5;	//Manuell versetzt
		
		var out = "Status: "+obj.status+" (";
		switch(obj.status) {
			case 0: out += "Uninitialized)"; break;
			case 1: out += "Init)"; break;
			case 2: out += "Ready)"; break;
			case 3: out += "Found)"; break;
			case 4: out += "¡Not found!)"; break;
			case 5: out += "Manual)"; break;
			case 6: out += "Predefined)"; break;
			default: out += "¡Geocoder Error "+obj.status+"!)";
		}
		if(obj.status>1) out += "\nAdresse: "+ (obj.place? obj.place.address: obj.address);
		if(obj.status>2) {
			out += "\nKoordinaten: "
			if(obj.dragged) out += "MAN";	//manuell erstellt (oder "gedraggt")
			out += obj.coords;
		}
		if(obj.status_div) obj.status_div.firstChild.nodeValue = out;
//		obj.status_div.firstChild.nodeValue = "Status: "+obj.status+" ("+obj.place+","+obj.land+")";
		//document.write( "Stadus: "+status);
		return obj.status;
	}
	obj.showStatus();
	
	obj.street= obj.zip= obj.city= obj.land= obj.area= obj.subarea= null;
	obj.setFields = function(street_, zip_, city_, land_, area_, subarea_) {
		obj.street = street_;
		obj.zip = zip_;
		obj.city = city_;
		obj.land = land_;
		obj.area = area_;
		obj.subarea = subarea_;
		obj.update();	//falls (schon) möglich
		if(obj.status<2) obj.showStatus(++obj.status);
		if(obj.initcallback && obj.status>1) initcallback(obj.status);	//Jetz aber!...
	}

	obj.update = function(useAreaInfo) {
		//alert("Update: "+obj.status);
		obj.address = "";
		if(obj.street)	obj.address += obj.street.value;
		if(obj.zip)	obj.address += ", "+obj.zip.value;
		if(obj.city)	obj.address += ", "+obj.city.value;
		if(obj.area && useAreaInfo)	obj.address += ", "+obj.area.value;
		if(obj.subarea && useAreaInfo)	obj.address += ", "+obj.subarea.value;
		if(obj.land)	obj.address += ", "+obj.land.value;
			else	obj.address += ", Europa";	//Default
		if(obj.status>1) {
			obj.geocoder.getLocations(obj.address, geocoded);
			google.maps.Event.addListener(obj.map, 'click', obj.leftClick);
		}
		return obj.showStatus();
	
		function geocoded(point) {
		if(point && obj.status>1)
			switch (point.Status.code) {
				case G_GEO_SUCCESS:	//Flag erstellen
					obj.place = point.Placemark[0];
					var coord = new google.maps.LatLng(obj.place.Point.coordinates[1],
							obj.place.Point.coordinates[0]);
					obj.dragged = false;
					obj.status = 3;
					obj.setFlag(coord, null);
					if(obj.foundcallback) //Callback
						if(obj.foundcallback(obj.coords, obj.dragged)) obj.status=4;	//Error aus HTML
					break;
				case G_GEO_UNKNOWN_ADDRESS:
					if((!obj.marker || !obj.dragged) && (obj.status != 6)) {
						obj.map.clearOverlays();
						obj.marker = obj.dragged = obj.coords = obj.place = null;
						obj.map.setCenter(new google.maps.LatLng(obj.dfault.lng, obj.dfault.lat), obj.dfault.zoom, G_PHYSICAL_MAP);	//Default
						obj.showStatus(4);
						if(obj.foundcallback) //Callback
							if(obj.foundcallback(obj.coords, obj.dragged)) obj.status=4;	//Error aus HTML
					}
				//	google.maps.Event.addListener(obj.map, 'click', obj.leftClick);
					break;
				case G_GEO_MISSING_QUERY:	//dann eben nicht, Frau Google!
				case G_GEO_UNAVAILABLE_ADDRESS:
				case G_GEO_UNKNOWN_DIRECTIONS:
				case G_GEO_TOO_MANY_QUERIES:
				case G_GEO_SERVER_ERROR:
				default:	//Nix.
					obj.map.clearOverlays();
					obj.marker = obj.dragged = obj.coords = obj.place = null;
			//		google.maps.Event.addListener(obj.map, 'click', obj.leftClick);
					obj.map.setCenter(new google.maps.LatLng(obj.dfault.lng, obj.dfault.lat), obj.dfault.zoom, G_PHYSICAL_MAP);	//Default
					obj.showStatus(point.Status.code);	//Error!
					if(obj.foundcallback) //Callback
						if(obj.foundcallback(null)) obj.status=4;	//Error aus HTML
			}
		}
	}
	
	obj.setFlag = function(coord_, address_, zoom_) {
		if(coord_ && obj.status>1) {
			if(!address_ && obj.place) {
				address_ = obj.place.address;
				zoom_ = obj.place.AddressDetails.Accuracy;
			}
			if(zoom_) obj.map.setZoom(6 + zoom_);
			obj.map.panTo(coord_);
			obj.map.clearOverlays();
			obj.address = address_;
			obj.coords = coord_;
			obj.dragged = false;
			var txt = '<b>Adresse gefunden:</b><br/>';
			if(obj.status == 5) txt = '<b>Manuell platziert:</b><br/>';
			if(obj.status == 6) txt = '<b>Definierte Koordinaten:</b><br/>';
			var loc;
			if((loc=obj.place) && (loc=loc.AddressDetails) && (loc=loc.Country) && (loc=loc.AdministrativeArea) && (loc=loc.SubAdministrativeArea) && (loc=loc.Locality)) {
				var depLoc = loc;
				if(loc.DependentLocality) depLoc = loc.DependentLocality;	//manchmal... ach Guugl...:(
				if(depLoc && depLoc.Thoroughfare)
					txt += depLoc.Thoroughfare.ThoroughfareName + '<br/>';
				if(depLoc && depLoc.PostalCode)
					txt += '<u>' + depLoc.PostalCode.PostalCodeNumber + '&nbsp;&nbsp;</u>';
				if(loc.LocalityName)
					txt += '<u>' + loc.LocalityName + ',&nbsp;</u>';
				txt += '<u>' + obj.place.AddressDetails.Country.CountryNameCode + '</u>';
				if(obj.place.AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.SubAdministrativeAreaName)
					txt += "<br/><small>"+obj.place.AddressDetails.Country.AdministrativeArea.AdministrativeAreaName+", "+
						obj.place.AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.SubAdministrativeAreaName+
						"</small>";
				if((obj.status == 3) || (obj.status == 6))
 					txt += '<br/>('+zoom_+') <i>Coords = '+coord_+'</i>';
				if(obj.status == 3)
					txt += '<br/><a style="font-size:x-small; color:green; text-decoration:underline" href="javascript:void addr.getAddress()">Adresse &uuml;bernehmen</a>';
			} else {
				txt += obj.address;
				if(obj.status == 6)
 					txt += '<br/>('+zoom_+') <i>Coords = '+coord_+'</i>';
 			}
			obj.marker = new google.maps.Marker(coord_, {title: obj.address, draggable: obj.draggable, icon: normflag});
			obj.marker.bindInfoWindowHtml(txt);
			if(obj.draggable) {
				google.maps.Event.addListener(obj.marker, 'dragstart', dragStart);
				google.maps.Event.addListener(obj.marker, 'dragend', dragEnd);
			}
			obj.map.addOverlay(obj.marker);
			if(obj.status == 5) obj.marker.setImage(newflag);
			if(obj.dragged) obj.marker.setImage(dragflag);
			obj.showStatus();
		} else return false;

		function dragStart() {	//Callback
			if(obj.draggable) {
				obj.dragged = true;
				this.setImage(dragflag);
				google.maps.Event.addListener(obj.map, 'singlerightclick', obj.rightClick);
			}
		}
	
		function dragEnd() {	//Callback
			obj.dragged = true;
			obj.coords = this.getLatLng();
		//	if(obj.status != 5)
				this.bindInfoWindowHtml('<b>Marker verschoben:<br/><small>(mit Rechzklick zur urspr&uuml;nglichen Position)</small></b><br/>'+obj.address+'<br/><i>'+obj.coords+'</i>');
			obj.showStatus();
			if(obj.foundcallback) //Callback
				if(obj.foundcallback(obj.coords, obj.dragged)) obj.status=4;	//Error aus HTML
		}
		
	}

	obj.leftClick = function(overlay, point) {
		//alert("Klick! point="+point+", overlay="+(overlay==obj.marker)+" ("+obj.address+")");
		if((obj.draggable || !obj.marker) && !overlay) {	//unbekannte Position definieren
			obj.dragged = true;
			obj.status = 5;
			obj.setFlag(point, obj.address);
			if(obj.foundcallback) //Callback
				if(obj.foundcallback(obj.coords, obj.dragged)) obj.status=4;	//Error aus HTML
//			obj.showStatus();
		//	google.maps.Event.clearListeners(obj.map, 'click');
			google.maps.Event.addListener(obj.map, 'singlerightclick', obj.rightClick);
		}
	}
		
	obj.rightClick = function(point, src, overlay) {
		//alert("Rechzklick! point="+point+", src="+src+", overlay="+overlay+" ("+(overlay==obj.marker)+")");
		if(overlay == obj.marker) {
			obj.update();
			google.maps.Event.clearListeners(obj.map, 'singlerightclick');
		}
	}
	
	obj.zoomEnd = function(old_, new_) {	//GM, wird nie aufgerufen (?!)
		alert("zoomend old="+old_+" end="+end);
		if(obj.map && obj.marker) 
			obj.map.panTo(obj.marker.getLatLng());
	}
	
	obj.setCoords = function(lat_, lng_, addr_, zoom_) {
		//alert("setCoords("+lat_+", "+lng_+", "+addr_+", "+zoom_+"), address="+obj.address);
		if(!zoom_) zoom_ = 7;
		if(!addr_) addr_ = obj.address;
		if(!!(lat_*1) && !!(lng_*1) && obj.map) {
			obj.status = 6;	//Predefiniert (aus DB?)
			obj.dragged = false;
			obj.coords = new google.maps.LatLng(lat_, lng_);
			obj.setFlag(obj.coords, addr_, zoom_);
			obj.showStatus();
			return true;
		} else 
			return false;
	}

	obj.getAddress = function() {
		if((obj.status == 3) || (obj.status == 5)) {
			var loc;
			if((loc=obj.place) && (loc=loc.AddressDetails) && (loc=loc.Country) && (loc=loc.AdministrativeArea) && (loc=loc.SubAdministrativeArea)&& (loc=loc.Locality)) {
				if(obj.area) obj.area.value = obj.place.AddressDetails.Country.AdministrativeArea.AdministrativeAreaName;
				if(obj.subarea) obj.subarea.value = obj.place.AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.SubAdministrativeAreaName;
				var depLoc = loc;
				if(loc.DependentLocality) depLoc = loc.DependentLocality;	//manchmal... ach Guugl...:(
				if(depLoc && depLoc.Thoroughfare)
					if(obj.street) obj.street.value = depLoc.Thoroughfare.ThoroughfareName;
				if(depLoc && depLoc.PostalCode)
					if(obj.zip) obj.zip.value = depLoc.PostalCode.PostalCodeNumber;
				if(loc.LocalityName)
					if(obj.city) obj.city.value = loc.LocalityName;
				if(obj.land) obj.land.value = obj.place.AddressDetails.Country.CountryNameCode;
			}
		}
	}
	
	obj.setFoundCallback = function(where) {obj.foundcallback = where;}
	obj.setInitCallback = function(where) {obj.initcallback = where;}
	
	return obj;
}
