function PlantMap(ajax) {
	var self = this;
	
	this._ajax = ajax;
	this._el = $("#map");
	this._replace = $("#map-ajax");
	this._map = null;
	this._geocoder = null;
	this._clusterer = null;
	this._marker = null;
	this._single = null;
	this._icon = null;
	this._project = null;
	this._lat = $("input[name='latitude']");
	this._lon = $("input[name='longitude']");
	this._locator = $("#locator");
	
	this._init = function() {
		if (GBrowserIsCompatible()) {
			self._map = new GMap2(self._el.get(0));
			self._map.enableScrollWheelZoom();
			self._map.addControl(new GLargeMapControl());
			self._map.addControl(new GMapTypeControl());

			// single icon
			var bicon = new GIcon();
			bicon.iconSize = new GSize(27, 26);
			bicon.iconAnchor = new GPoint(4, 26);
			bicon.infoWindowAnchor = new GPoint(9, 0);
			
			self._single = new GIcon(bicon);
			self._single.image = "/gfx/reloaded/marker.png";
			
			// normal icon
			bicon = new GIcon();
			bicon.iconSize = new GSize(29, 26);
			bicon.iconAnchor = new GPoint(4, 26);
			bicon.infoWindowAnchor = new GPoint(0, 0);
			
			self._icon = new GIcon(bicon);
			self._icon.image = "/gfx/reloaded/marker.png";
			
			// project icon
			self._project = new GIcon(bicon);
			self._project.image = "/gfx/reloaded/marker-project.png";
			
			var lat = self._lat.val();
			var lon = self._lon.val();
			if (lat && lon) {
				self._createMarker(lat, lon, true);
			} else if (self._ajax) {
				self._map.setCenter(new GLatLng(51.1, 11.5), 5);
				self._bindEvents($("#preview"));
				GEvent.addListener(self._map, "moveend", function() {
					self._ajaxLoad();
				});
			} else {
				self._map.setCenter(new GLatLng(50.4419, 9.1419), 5);
			}
			
			self._geocoder = new GClientGeocoder();
		}
	}
	
	this.getMap = function() {
		return self._map;
	}
	
	this.setClusterer = function(clusterer) {
		self._clusterer = clusterer;
	}
	
	this.add = function(lat, lon, message, project) {
		var point = new GLatLng(lat, lon);
		
		var options = {};
		if (project) options.icon = self._project;
		else options.icon = self._icon;
		
		var marker = new GMarker(point, options);
		GEvent.addListener(marker, "click", function() {
			marker.openInfoWindowHtml(message);
		});
		if (self._clusterer && !project) {
			self._clusterer.SetIcon(self._icon);
			self._clusterer.AddMarker(marker, message);
		} else {
			self._map.addOverlay(marker);
		}
	}
	
	this.mark = function(lat, lon) {
		var point = new GLatLng(lat, lon);
		self._marker = new GMarker(point, {
			zIndexProcess: function() {
				return 300;
			}
		});
		self._map.addOverlay(self._marker);
	}
	
	this.demark = function() {
		if (self._marker) {
			self._map.removeOverlay(self._marker);
			self._marker =  null
		}
	}
	
	this.center = function(lat, lon) {
		var zoom = self._map.getBoundsZoomLevel(self._map.getBounds());
		self._map.setCenter(new GLatLng(lat, lon), zoom + 2);
	}
	
	this._createMarker = function(lat, lon, draggable) {
		if (self._map) {
			var point = new GLatLng(lat, lon);
			self._map.setCenter(point, draggable ? 10 : 12);
			
			self._marker = new GMarker(point, {icon: self._single, draggable: draggable});
			if (draggable) {
				GEvent.addListener(self._marker, "dragstart", function(){
					self._map.closeInfoWindow();
				});
				GEvent.addListener(self._marker, "dragend", function() {
					self._refresh();
				});
			}
			self._map.addOverlay(self._marker);
			self._refresh();
		}
	}
	
	this._refresh = function() {
		if(self._marker) {
			var latLng = self._marker.getLatLng();
			self._lat.val(latLng.lat());
			self._lon.val(latLng.lng())
		}
	}
	
	this.addMarker = function(lat, lon, draggable) {
		self._createMarker(lat, lon, draggable);
	}
	
	this._clearAddSingleMarker = function() {
		if (self._map) {
			self._map.clearOverlays();
			var latLng = self._map.getCenter();
			self._createMarker(latLng.lat(), latLng.lng(), true);
		}
	}
	$(".marker-add").click(this._clearAddSingleMarker);
	
	this._resetMap = function() {
		if (self._map) {
			self._map.clearOverlays();
			self._lat.val("");
			self._lon.val("");
		}
	}
	$(".marker-remove").click(this._resetMap);
	
	this._locate = function() {
		if (self._geocoder) {
			self._geocoder.getLocations(self._locator.val(), function(response) {
				self._resetMap();
				if (!response || response.Status.code != 200) {
					alert("Sorry, wir konnten den Standort nicht finden. Versuchs nochmal mit einer anderen Anfrage.");
				} else {
					var place = response.Placemark[0];
					var point = place.Point;
					self._createMarker(point.coordinates[1], point.coordinates[0], true);
					self._marker.openInfoWindowHtml("<span class='black' style='font-size: 14px;'>" + place.address + "</span>");
				}
			});
		}
	}
	$(".locator-search").click(this._locate);
	this._locator.keydown(function(event) {
		if (event.keyCode == 13) {
			event.preventDefault();
			self._locate();
		}
	});
	
	this._ajaxLoad = function() {
		var bounds = self._map.getBounds();
		var sw = bounds.getSouthWest();
		var ne = bounds.getNorthEast();
		var params = {
			ajax: true,
			lat1: sw.lat(),
			lat2: ne.lat(),
			lon1: sw.lng(),
			lon2: ne.lng()
		}
		$.get(self._ajax, params, function(data) {
			var next = $(data);
			self._bindEvents(next);
			self._replace.replaceWith(next);
			self._replace = next;
		});
	}
	
	this._bindEvents = function(from) {
		from.find("li").each(function() {
			var el = $(this);
			var info = el.find(".plant-info").hide();
			var plant = el.find(".plant");
			var lat = plant.attr("lat");
			var lon = plant.attr("lon");
			plant.mouseover(function() {
				info.show();
				self.mark(lat, lon);
			}).mouseout(function() {
				info.hide();
				self.demark();
			});
		});
	}
	
	this._init();
}
