function googleMaps(element_id) {
	
	var defunct = false;
	var map;
	var map_div;
	var cords;
	var center_cords;
	var zoom;
	var geocoder;
	var gdir;
	var gdir_route_container;
	var controls;
	var marker_icon;
	
	var afterLoadFunction;
	
	if(!element_id) {
		this.defunct = true;
	}
	else {
		this.map_div = element_id;
		this.cords = new Array(0, 0);
		this.zoom = 1;
	}
	
}

googleMaps.prototype.loadMap = function() {
	
	if(!this.defunct) {
		var parent = this;
		this.map = new GMap2(document.getElementById(this.map_div));
		
		if(this.afterLoadFunction) {
			GEvent.addListener(this.map, "load", this.afterLoadFunction);
		}
		
		this.center_cords = new GLatLng(this.cords[0], this.cords[1])
		this.map.setCenter(this.center_cords, this.zoom);
		GEvent.addListener(this.map, "moveend", function() {
			parent.center_cords = parent.map.getCenter();
		}
		);
	}

}

googleMaps.prototype.setAfterLoad = function(funct) {
	this.afterLoadFunction = funct;
}

googleMaps.prototype.addControl = function(control) {
	
	if(!this.controls) {
		this.controls = new Object();
	}
	
	switch(control) {
		case("smallMapControl"):
			this.controls[control] = new GSmallMapControl();
		break;
		case("largeMapControl"):
			this.controls[control] = new GLargeMapControl();
		break;
		case("smallZoomControl"):
			this.controls[control] = new GSmallZoomControl();
		break;
		case("scaleControl"):
			this.controls[control] = new GScaleControl();
		break;
		case("mapTypeControl"):
			this.controls[control] = new GMapTypeControl();
		break;
	}

	if(this.controls[control]) {
		this.map.addControl(this.controls[control]);
	}
	
}

googleMaps.prototype.removeControl = function(control) {
	this.map.removeControl(this.controls[control]);	
}

googleMaps.prototype.checkResize = function() {
	this.map.checkResize();
	this.map.panTo(this.center_cords);
}

googleMaps.prototype.enableRouting = function(element) {
	
	if(!this.gdir_route_container) {
		this.gdir_route_container = document.getElementById(element);
	}
	
	this.gdir = new GDirections(this.map, this.gdir_route_container);
	GEvent.addListener(this.gdir, "error", this.routeHandleErrors);
}

googleMaps.prototype.calcRoute = function(start, end) {
	this.gdir.load("from: " + start + " to: " + end);
}

googleMaps.prototype.clearRouteResults = function() {
	this.gdir.clear();
}

googleMaps.prototype.routeHandleErrors = function() {
	if (this.gdir.getStatus().code == G_GEO_UNKNOWN_ADDRESS)
		this.throwRouteError("Die eingegebene Adresse konnte nich gefunden werden!");
	else if (this.gdir.getStatus().code == G_GEO_SERVER_ERROR)
		this.throwRouteError("Eine Routenberechnung ist zur Zeit nicht möglich!");
	else if (this.gdir.getStatus().code == G_GEO_MISSING_QUERY)
		this.throwRouteError("Es wurde keine Adresse angegeben!");
	else if (this.gdir.getStatus().code == G_GEO_BAD_KEY)
		this.throwRouteError("Der API Key ist nicht korrekt!");
	else if (this.gdir.getStatus().code == G_GEO_BAD_REQUEST)
		this.throwRouteError("Die Anfrage konnte nicht bearbeitet werden!");
	else 
		this.throwRouteError("Es ist ein unbekannter Fehler aufgetreten!");
}

googleMaps.prototype.throwRouteError = function(error) {
	if(this.gdir_route_container) {
		this.gdir_route_container.innerHTML = error;
	}
}

googleMaps.prototype.setCords = function(cords) {
	
	switch(typeof cords) {
		case("object"):
			this.cords = new Array(cords.lat(), cords.lng());
		break;
		case("string"):
			this.cords = cords.split(",");
		break;
	}
	
}

googleMaps.prototype.setZoom = function(zoom) {
	
	if(typeof zoom != "number") {
		zoom = parseInt(zoom);
	}
	
	if(zoom > 18) {
		zoom = 18;
	}
	
	this.zoom = zoom;
	
	if(this.map) {
		this.map.setZoom(this.zoom);
	}
	
}

googleMaps.prototype.addMarker = function(cords, content, show_content) {
	
	switch(typeof cords) {
		case("object"):
			point = new GLatLng(cords.lat(), cords.lng());
		break;
		case("string"):
			cords = cords.split(",");
			point = new GLatLng(cords[0], cords[1]);
		break;
	}
	
	var marker = this.createMarker(point, content);
	
	this.map.addOverlay(marker);
	
	if(show_content) {
		marker.openInfoWindowHtml(content);
	}
	
	return marker;
}

googleMaps.prototype.addCustomMarker = function(marker) {
	this.map.addOverlay(marker);
}

googleMaps.prototype.addMarkersFromXml = function(xmlFile) {
	var parent = this;
	GDownloadUrl(xmlFile+"?"+Math.ceil(Math.random()*10000), function(data, responseCode) {
			parent.parseMarkersXml(data);
		}
	);
}

googleMaps.prototype.parseMarkersXml = function(xmlText) {
	var xml = GXml.parse(xmlText);
	var markers = xml.documentElement.getElementsByTagName("marker");
	
	for(var i=0; i<markers.length; i++) {
		var tmp = markers[i].getElementsByTagName("text")[0];
		if(tmp.firstChild) {
			var text = tmp.firstChild.data;
		}
		tmp = markers[i].getElementsByTagName("geo")[0];
		var geo_lat = parseFloat(tmp.getElementsByTagName("lat")[0].firstChild.data);
		var geo_lng = parseFloat(tmp.getElementsByTagName("lng")[0].firstChild.data);
		var point = new GLatLng(geo_lat, geo_lng);
		
		this.map.addOverlay(this.createMarker(point, text));
	}
	
}

googleMaps.prototype.createMarker = function(point, infoContent) {
	if(this.marker_icon) {
		var marker = new GMarker(point, this.marker_icon);
	}
	else {
		var marker = new GMarker(point);
	}
	
	if(infoContent) {
	if(infoContent.length > 0) {
		
		GEvent.addListener(	marker,
							"click",
							function() {
								marker.openInfoWindowHtml(infoContent);
							}
						)
		
	}
	}
	return marker;
}

googleMaps.prototype.setMarkerIcon = function(file, width, height) {
	this.marker_icon = new GIcon();
	this.marker_icon.image = file;
	this.marker_icon.iconSize = new GSize(width, height);
	this.marker_icon.infoWindowAnchor = new GPoint(width/2, height/2);
	this.marker_icon.iconAnchor = new GPoint(width/2, height/2);
	
}

googleMaps.prototype.addPolylineFromEncoded = function(points, levels, params) {
	
	if(!params) {
		var params = new Object();
	}
	
	if(!params.color) {
		params.color = "#ff0000";
	}
	
	if(!params.weight) {
		params.weight = 5;
	}
	
	if(!params.zoomFactor) {
		params.zoomFactor = 2;
	}
	
	if(!params.numLevels) {
		params.numLevels = 18;
	}
	
	if(!params.opacity) {
		params.opacity = 1;
	}
	
	var encodedPolyline = new GPolyline.fromEncoded(
	{
		color: params.color,
		weight: params.weight,
		points: points,
		levels: levels,
		opacity: params.opacity,
		zoomFactor: params.zoomFactor,
		numLevels: params.numLevels
	}
	);
	
	if(params.fitMap) {
		this.setZoom(this.map.getBoundsZoomLevel(encodedPolyline.getBounds()));
	}
	
	this.map.addOverlay(encodedPolyline);
	
}
