/***
 * Creates new geobip map object
 */
function map() {
	this.root				= '';
	this.session			= '';
	this.url				= '';

	this.authorized			= false;

	this.mapId				= 'boxGeoBIPMap';
	this.mapObject			= null;
	this.mapBaseLayer		= null;
	this.mapHistory			= null;
	this.mapPanel			= null;
	this.mapInitalized		= false;

	this.markersResizing		= new Array();
	this.markersTown			= new Array();
	this.markersObject			= new Array();
	this.markersSearchObject	= new Array();
	this.markersLegend			= new Array();

	this.mapBuffer			= 0;
	this.mapTileWidth		= 300;
	this.mapTileHeight		= 300;
	this.mapDefinition		= '';
	this.mapExtent			= '';
	this.mapMinScale		= '';
	this.mapMaxScale		= '';
	this.mapZoomLevels		= 15;
	this.mapBaseLayers		= new Array();
	this.mapLayers			= new Array();
	this.mapThemes			= new Array();

	this.mapActiveObject	= null;

	this.mapStartPosX		= 0;
	this.mapStartPosY		= 0;
	this.mapStartZoom		= 8;

	this.mapLastPosX		= 0;
	this.mapLastPosY		= 0;
	this.mapLastZoom		= 8;

	this.mapCredentials	= "USERNAME=Anonymous&";
	this.mapUrlWMS		= "http://map.geobip.de/mapguide/mapagent/mapagent.fcgi?";
	this.mapUrls		= [	"http://map1.geobip.de/mapguide/mapagent/mapagent.php?" + this.mapCredentials,
			   		"http://map2.geobip.de/mapguide/mapagent/mapagent.php?" + this.mapCredentials,
			   		"http://map3.geobip.de/mapguide/mapagent/mapagent.php?" + this.mapCredentials,
			   		"http://map1.geobip.de/mapguide/mapagent/mapagent.php?" + this.mapCredentials,
			   		"http://map2.geobip.de/mapguide/mapagent/mapagent.php?" + this.mapCredentials,
			   		"http://map3.geobip.de/mapguide/mapagent/mapagent.php?" + this.mapCredentials,
			   		"http://map1.geobip.de/mapguide/mapagent/mapagent.php?" + this.mapCredentials,
			   		"http://map2.geobip.de/mapguide/mapagent/mapagent.php?" + this.mapCredentials,
			   		"http://map3.geobip.de/mapguide/mapagent/mapagent.php?" + this.mapCredentials ];
};

// Set root
map.prototype.setRoot = function (strRoot) {
	if(typeof strRoot == 'string') {
		this.root = strRoot;
	}
};

// Returns root
map.prototype.getRoot = function () {
	return this.root;
};

// Set url
map.prototype.setUrl = function (strUrl) {
	if(typeof strUrl == 'string') {
		this.url = strUrl;
	}
};

// Returns url
map.prototype.getUrl = function () {
	return this.url;
};

// Set session
map.prototype.setSession = function (strSession) {
	if(typeof strSession == 'string') {
		this.session = strSession;
	}
};

// Returns session
map.prototype.getSession = function () {
	return this.session;
};

// Returns true if map is initalized otherwise returns false 
map.prototype.isInitalized = function () {
	return (this.mapInitalized && this.mapObject) ? true : false;
}

// Set map definition
map.prototype.setMapDefinition = function (definition) {
	this.mapDefinition = definition;
};

// Set map extent
map.prototype.setExtent = function (extent) {
	if(getObjectName(extent) == '' && typeof OpenLayers != 'undefined') {
		eval("this.mapExtent = new OpenLayers.Bounds(" + extent + ");");
	} else {
		this.mapExtent = extent;
	}
};

// Set map min scale
map.prototype.setMinScale = function (scale) {
	this.mapMinScale = parseFloat(scale);
};

// Set map max scale
map.prototype.setMaxScale = function (scale) {
	this.mapMaxScale = parseFloat(scale);
};

// Returns true if map has themes
map.prototype.hasThemes = function () {
	return (this.mapThemes.length > 0) ? true : false;
}

// Add a theme to map
map.prototype.addTheme = function (type, name, description, standard) {
	var url = this.mapUrls;
	
	var themeParams = {
					mapdefinition: this.mapDefinition,
					basemaplayergroupname: name,
					transparent: true,
					format: 'image/png',
					SRS: 'EPSG:31467'
				};
				
	var themeOptions = {
					maxExtent: this.mapExtent,
		            projection: "EPSG:31467",
					displayProjection: "EPSG:4326", 
			    	singleTile: false,
					minScale: this.mapMinScale,
					maxScale: this.mapMaxScale,
					numZoomLevels: this.mapZoomLevels,
					isBaseLayer: true,
					alwaysInRange: false,
					transitionEffect: "resize",
					buffer: this.mapBuffer,
					'mapType': type,
					'standard': standard,
					defaultSize: new OpenLayers.Size(this.mapTileWidth,this.mapTileHeight)
				};

	this.mapThemes.push(new OpenLayers.Layer.MapGuide( description, url, themeParams, themeOptions));
};

// Returns true if map has themes
map.prototype.hasLayers = function () {
	return (this.mapLayers.length > 0) ? true : false;
}

// Add a layer to map
map.prototype.addLayer = function (type, name, description, standard) {
	var url = this.mapUrls;

	/*var layerParams = {
					layers: name,
					transparent: true,
					format: 'image/png',
					SRS: 'EPSG:31467'
				};

	var layerOptions = {
					maxExtent: this.mapExtent,
		            projection: "EPSG:31467",
					displayProjection: "EPSG:4326", 
					displayInLayerSwitcher: true,
					singleTile: true,
					visibility: true,
					minScale: this.mapMinScale,
					maxScale: this.mapMaxScale,
					numZoomLevels: this.mapZoomLevels,
					isBaseLayer: false,
					alwaysInRange: false,
					transitionEffect: "resize",
					buffer: this.mapBuffer,
					'mapType': type,
					'standard': standard
				}

	this.mapLayers.push(new OpenLayers.Layer.WMS( description, url, layerParams, layerOptions));
	*/
	
	var layerParams = {
					mapdefinition: this.mapDefinition,
					basemaplayergroupname: name,
					transparent: true,
					format: 'image/png',
					SRS: 'EPSG:31467'
				};
				
	var layerOptions = {
					maxExtent: this.mapExtent,
		            projection: "EPSG:31467",
					displayProjection: "EPSG:4326", 
			    	singleTile: false,
					minScale: this.mapMinScale,
					maxScale: this.mapMaxScale,
					numZoomLevels: this.mapZoomLevels,
					isBaseLayer: false,
					alwaysInRange: false,
					transitionEffect: "resize",
					buffer: this.mapBuffer,
					visibility: standard,
					'mapType': type,
					'standard': standard,
					defaultSize: new OpenLayers.Size(this.mapTileWidth,this.mapTileHeight)
				};

	this.mapLayers.push(new OpenLayers.Layer.MapGuide( description, url, layerParams, layerOptions));
};

// Set start position of map
map.prototype.setStartPosition = function (posX, posY, zoom) {
	if(parseFloat(posX) > 0 && parseFloat(posY) > 0) {
		this.mapStartPosX	= parseFloat(posX);
		this.mapStartPosY	= parseFloat(posY);
		this.mapStartZoom	= parseInt(zoom);
	}
};

// Returns true if real map is loaded otherwise returns false
map.prototype.isGeoBIPMapLoaded = function () {
	return (this.mapInitalized) ? true : false;
}

// Returns true if map is loaded from google
map.prototype.isGoogleMap = function () {
	return (this.mapBaseLayer.mapType.substr(0, 6) == 'GOOGLE') ? true : false;
}

// Destroy current map
map.prototype.destroy = function () {
	if(this.isInitalized()) {
		this.mapInitalized		= false;

		if(this.mapObject.layers != null) {
            for(var i=0;i<this.mapObject.layers.length;i++) {
				if(this.mapObject.layers[i].markers != null) {
					for(var m=0;m<this.mapObject.layers[i].markers.length;m++) {
						this.mapObject.layers[i].markers[m].destroy();
					}
				}		
            } 
        } 
		
		this.mapObject.destroy();
		
		delete this.mapObject;
		delete this.mapBaseLayer;
		delete this.mapHistory;
		delete this.mapPanel;

		this.mapObject			= null;
		this.mapBaseLayer		= null;
		this.mapHistory			= null;
		this.mapPanel			= null;

		delete this.markersResizing;
		delete this.markersTown;
		delete this.markersObject;
		delete this.markersSearchObject;
		delete this.markersLegend;

		this.markersResizing		= new Array();
		this.markersTown			= new Array();
		this.markersObject			= new Array();
		this.markersSearchObject	= new Array();
		this.markersLegend			= new Array();

		delete this.mapBaseLayers;
		delete this.mapLayers;
		delete this.mapThemes;

		this.mapBaseLayers		= new Array();
		this.mapLayers			= new Array();
		this.mapThemes			= new Array();

		if(GUnload) { GUnload(); }
	}
}

// Initalize the map
map.prototype.initalize = function () {
	var mapOptions = {
	        units: "m",
            maxResolution: "auto",
			transitionEffect: "resize",
			controls: []
		};
		
	this.mapObject = new OpenLayers.Map( this.mapId, mapOptions );

	this.mapInitalized = true;

	// Initalize control
	this._initalizeControls();
	
	// Initalize authorized actions
	if(this.isAuthorized()) {
		this.initAuthorized();
	}

	// Initalize layers
	this._initalizeLayers();
	this._initalizeToolbar();
	this._initalizeEvents();
	this._initalizeOverview();

	// Initalize markers
	this._initalizeMarkersLegend();
	this._initalizeMarkersObject();
}

// Initalize layers
map.prototype._initalizeLayers = function () {
	this.mapBaseLayers	= new Array();

	var physicalOptions = {
		                	type: G_PHYSICAL_MAP,
		                	'GoogleMap': true,
		                	isBaseLayer: true,
		                	numZoomLevels: 16,
		                	projection: "EPSG:900913",
		                	displayProjection: "EPSG:4326",
		                	maxExtent: new OpenLayers.Bounds(-180, -90, 180, 90),
		                	scales: [],
		                	transitionEffect: "resize",
			               'mapType': 'GOOGLE_PHYSICAL'
		                };

	var normalOptions = {
		                	type: G_NORMAL_MAP,
		                	'GoogleMap': true,
		                	isBaseLayer: true,
		                	numZoomLevels: 18,
		                	projection: "EPSG:900913",
		                	displayProjection: "EPSG:4326",
		                	maxExtent: new OpenLayers.Bounds(-180, -90, 180, 90),
		                	scales: [],
		                	transitionEffect: "resize",
			               'mapType': 'GOOGLE_STREET'
	                	};

	var satteliteOptions = {
		                	type: G_SATELLITE_MAP,
		                	'GoogleMap': true,
		                	isBaseLayer: true,
		                	numZoomLevels: 19,
		                	projection: "EPSG:900913",
		                	displayProjection: "EPSG:4326",
		                	maxExtent: new OpenLayers.Bounds(-180, -90, 180, 90),
		                	scales: [],
		                	transitionEffect: "resize",
			               'mapType': 'GOOGLE_SATELLITE'
		                };

	var hybridOptions = {
		                	type: G_HYBRID_MAP,
		                	'GoogleMap': true,
		                	isBaseLayer: true,
		                	numZoomLevels: 19,
		                	projection: "EPSG:900913",
		                	displayProjection: "EPSG:4326",
		                	maxExtent: new OpenLayers.Bounds(-180, -90, 180, 90),
		                	scales: [],
		                	transitionEffect: "resize",
			               'mapType': 'GOOGLE_HYBRID'
		                };

	this.mapBaseLayers.push(new OpenLayers.Layer.Google("Google - Physikalische Ansicht", physicalOptions));
	this.mapBaseLayers.push(new OpenLayers.Layer.Google("Google - Strassen Ansicht", normalOptions));
	this.mapBaseLayers.push(new OpenLayers.Layer.Google("Google - Satelliten Ansicht", satteliteOptions));
	this.mapBaseLayers.push(new OpenLayers.Layer.Google("Google - Hybride Ansicht", hybridOptions));

	var StandardBaseLayerType = '';
	if(this.hasThemes()) {
		for(var t=0;t<this.mapThemes.length;t++) {
			if(this.mapThemes[t].standard && this.mapThemes[t].standard == true) {
				StandardBaseLayerType = this.mapThemes[t].mapType;
				break;
			}
		}
	} else {
		StandardBaseLayerType = 'GOOGLE_PHYSICAL';
	}

	for(var l=0;l<this.mapBaseLayers.length;l++) {
		this.mapObject.addLayer(this.mapBaseLayers[l]);
	}

	for(var t=0;t<this.mapThemes.length;t++) {
		this.mapObject.addLayer(this.mapThemes[t]);
	}

	for(var l=0;l<this.mapLayers.length;l++) {
		this.mapObject.addLayer(this.mapLayers[l]);
	}

	if(!isEmpty(StandardBaseLayerType)) {
		this.setBaseLayer(StandardBaseLayerType);
	}

	// Create first the layer for active objects to active hover settings for other objects
	var layer = this._createLayer("Markierung für aktive Objekte", "GEOBIP_MARKERS_ACTIVEOBJECT");
}

// Initalize layers
map.prototype.switchLayer = function (type, visibility) {
	for(var l=0;l<this.mapLayers.length;l++) {
		if(this.mapLayers[l].mapType == type) {
			this.mapLayers[l].setVisibility(visibility);
			break;
		}
	}
}

// Initalize map controls
map.prototype._initalizeControls = function () {
	if(!this.isInitalized()) { return; };

	// Add custom panzoombar to map
	var mapPanZoomBar = new OpenLayers.Control.PanZoomBarCustom();
	this.mapObject.addControl(mapPanZoomBar);

	// Add mouse defualts to map
	var mapMouseDefaults = new OpenLayers.Control.MouseDefaults();
	this.mapObject.addControl(mapMouseDefaults);

	// Add mouse click to map
	var mapClick = new OpenLayers.Control.Click();
	this.mapObject.addControl(mapClick);

	// Activate special controls
	mapClick.activate();
}

// Initalize mapevents
map.prototype._initalizeEvents = function () {
	var current = this;
	
	if(!this.isInitalized()) { return; };

	// Register event for marker icons
	this.mapObject.events.register("zoomend", this.mapObject, function (evt) {
              	current._initalizeMarkerIcons();
                OpenLayers.Event.stop(evt);
            } );
            
	delete current;
}

// Initalize layers
map.prototype._initalizeToolbar = function () {
	var current = this;

	if(!this.isInitalized()) { return; };

	// Add history control to map
	this.mapHistory = new OpenLayers.Control.NavigationHistory();
	this.mapObject.addControl(this.mapHistory);

	var ToolTipListener = { "activate": function(e) { current._initalizeCursors(e); } };

	var panelMouseDefaults = new OpenLayers.Control.MouseDefaults( { title: "Karte mit Maus verschieben", eventListeners: ToolTipListener } );
	var panelZoomBox = new OpenLayers.Control.ZoomBox( { title: "Kartenausschnitt wählen", eventListeners: ToolTipListener } );
	var panelZoomIn = new OpenLayers.Control.ZoomIn( { title: "Kartenausschnitt vergrössern" } );
	var panelZoomOut = new OpenLayers.Control.ZoomOut( { title: "Kartenausschnitt verkleinern" } );
	var panelStartMap = new OpenLayers.Control.StartMap( { title: "Anfangskarte zeigen", allowSelection: 'True', eventListeners: ToolTipListener } );

	this.mapPanel = new OpenLayers.Control.Panel( { defaultControl: panelMouseDefaults } );

	this.mapPanel.addControls([	panelStartMap,
								this.mapHistory.previous,
		             			this.mapHistory.next,
								panelMouseDefaults,
				                panelZoomBox,
								panelZoomIn,
								panelZoomOut ] );

	for(var c=0;c<this.mapPanel.controls.length;c++) {
		this.mapPanel.controls[c].panel_div.onmouseover = function() { this.style.cursor = "pointer"; };
		this.mapPanel.controls[c].panel_div.onmouseout = function() { this.style.cursor = ''; };
	}

	this.mapObject.addControl(this.mapPanel);
	
	delete current;
}

// Initalize map toolbar
map.prototype._initalizeCursors = function (e) {
	var activeTool = '';

	for(var i=0;i<this.mapPanel.controls.length;i++) {
		if(this.mapPanel.controls[i].active) {
			activeTool = this.mapPanel.controls[i].CLASS_NAME;
			break;
		}
	}

	// Set Cursor
	var newCursor = '';
	switch(activeTool) {
		case "OpenLayers.Control.Identify": // Select object 
			newCursor = 'help';
			break;
		case "OpenLayers.Control.ZoomBox": // Zoom to rectangle 
			newCursor = 'url(/' + this.getUrl() + '/layout/images/cursors/zoom_rectangle.cur), crosshair';
			break;
		case "OpenLayers.Control.MouseDefaults": // Enter Pan mode
			newCursor = 'all-scroll';
			break;
		case "OpenLayers.Control.Button": // Enter Pan mode
			newCursor = 'all-scroll';
			break;
		default: // Enter selection mode 
			newCursor = 'all-scroll';
			break;
	}

	newCursor = newCursor.replace(/(\/+)/g, "/");

	// check if memory leaks
	var divMap = GetLayer(this.mapId);			
	if(!isEmpty(newCursor) && divMap) {
		//divMap.onmouseover = function() { this.style.cursor = newCursor; };
		//divMap.onmousedown = function() { this.style.cursor = newCursor; };
		//divMap.onmouseup = function() { this.style.cursor = newCursor; };
		divMap.onmousemove = function() { this.style.cursor = newCursor; };
		divMap.onmouseout = function() { this.style.cursor = 'default'; };
	}
};

map.prototype._initalizeOverview = function () {
	return;
//	var mapOptions = this.mapBaseLayer.options;
/* 	            mapOptions:	{
		           				maxExtent: this.mapBaseLayer.getExtent(),
	            				projection: this.mapObject.getProjection(), 
	            				displayProjection: "EPSG:4326",
	            				units: "m"
	            			},*/

//	var overviewLayer = this.mapBaseLayer;
//	OpenLayers.Util.extend(overviewLayer, this.mapBaseLayer);
	
	var overviewOptions = {
	            mapOptions:	{
		           				maxExtent: this.mapObject.getExtent(),
	            				projection: this.mapObject.getProjection(), 
	            				displayProjection: "EPSG:4326",
	            				units: "m"
	            			},
	            minRectSize: 10,
	            minRatio: 100,
	            maxRatio: 200,
	            size: new OpenLayers.Size(180, 120),  
	     		title: "Überblickskarte mit aktuell dargestelltem Kartenausschnitt"
	        }

	var overviewMap = new OpenLayers.Control.OverviewMap(overviewOptions);
	        
	this.mapObject.addControl(overviewMap); 
}

// Initalize the size of the marker icons
map.prototype._initalizeMarkerIcons = function () {
	if(!this.isInitalized()) { return; };

	var units = this.mapBaseLayer.units;
	var originalResolution = 1200 / (OpenLayers.INCHES_PER_UNIT[units] * OpenLayers.DOTS_PER_INCH);
	var currentResolution = this.mapObject.getResolution();
	       	
	for(var m=0;m<this.markersResizing.length;m++) {
		var marker = this.markersResizing[m];

		var newSize = this._getResolutionIconSize(marker.iconWidth, marker.iconHeight);
	
		if(newSize.w < 5 || newSize.h < 5) {
			marker.display(false);
		} else {
			marker.icon.setSize(newSize);
			marker.display(true);
		}
   	}
}

// Initalize the legend markers on map
map.prototype._initalizeMarkersLegend = function () {
	var current = this;
	
	if(!this.isInitalized() || !this.hasThemes()) { return; };
	
	var url =  MAP.getRoot() + "map_legends.php?" + MAP.getSession();

	OpenLayers.loadURL(url, '', this,
					function (response) {
						var XML = GXml.parse(response.responseText);

						var layer = current._createLayer("Ortsinformationen", "GEOBIP_MARKERS_LEGEND");
						
						for(var m=0;m<current.markersLegend.length;m++) {
							layer.removeMarker(current.markersLegend[m]);
							current.markersLegend[m].destroy();
						}
						
						delete current.markersLegend;
						current.markersLegend = new Array();

						if(XML && XML.documentElement) {
							var xmlMarkers = XML.documentElement.getElementsByTagName("marker");

							for(var m=0;m<xmlMarkers.length;m++) {
								var xmlMarker = xmlMarkers[m];

								var legendName		= xmlMarker.getAttribute('legendentryname') || '';
								var legendTooltip	= xmlMarker.getAttribute('legendentrytooltip') || '';

								legendName = legendName.replace(/&amp;/g, '&');
								legendTooltip = legendTooltip.replace(/&amp;/g, '&');
								legendTooltip = legendTooltip.replace(/&lt;/g, '<');
								legendTooltip = legendTooltip.replace(/&gt;/g, '>');

								var html = '<div style="padding: 10px;">';
								html += '<div class="TextfettOrange">' + legendName + '</div><br/>';
								if(legendTooltip != '') {
									html += '<div class="Textnormal">' + legendTooltip + '</div><br/>';
								}
								html += '</div>';

								var marker = current._createMarker(layer, xmlMarker, html);
								current.markersLegend.push(marker);
							}

							for(var m=0;m<current.markersLegend.length;m++) {
								layer.addMarker(current.markersLegend[m]);
							}
							
							delete xmlMarkers;
								
							// Show layer							
							layer.setVisibility(true);
						}
						
						delete XML;
					} );

	delete current;
}

// Initalize the object markers on map
map.prototype._initalizeMarkersObject = function () {
	var current = this;
	
	if(!this.isInitalized() || !this.hasThemes()) { return; };
	
	var url =  MAP.getRoot() + "map_objects.php?" + MAP.getSession();

	OpenLayers.loadURL(url, '', this,
					function (response) {
						var XML = GXml.parse(response.responseText);

						var layer = current._createLayer("Markierung für Objekte", "GEOBIP_MARKERS_OBJECT");
						
						for(var m=0;m<current.markersObject.length;m++) {
							layer.removeMarker(current.markersObject[m]);
							current.markersObject[m].destroy();
						}

						delete current.markersObject;
						current.markersObject = new Array();

						if(XML && XML.documentElement) {
							var xmlMarkers = XML.documentElement.getElementsByTagName("marker");

							for(var m=0;m<xmlMarkers.length;m++) {
								var xmlMarker = xmlMarkers[m];

								var marker = current._createMarker(layer, xmlMarker, '');
								current.markersObject.push(marker);
							}

							for(var m=0;m<current.markersObject.length;m++) {
								layer.addMarker(current.markersObject[m]);
							}
							
							delete xmlMarkers;
								
							// Show layer							
							layer.setVisibility(true);
						}
						
						delete XML;
					} );

	delete current;
}

// Initalize the object markers on map
map.prototype.setActiveObject = function (posX, posY) {
	if(!this.isInitalized() || !this.hasThemes()) { return; };
	
	var layer = this._createLayer("Markierung für aktive Objekte", "GEOBIP_MARKERS_ACTIVEOBJECT");

	if(this.mapActiveObject != null) {
		layer.removeMarker(this.mapActiveObject);
	}

	this.mapActiveObject = null;

	var iconUrl			= 'layout/images/pins/object_active.png';
	var iconWidth		= 50;
	var iconHeight		= 50;
	var iconResize		= 'true';

	var point = new OpenLayers.LonLat(posX, posY);
	var iconSize = this._getResolutionIconSize(parseInt(iconWidth),parseInt(iconHeight));
	var calculateOffset = function(size) { return new OpenLayers.Pixel(-(size.w/2), -(size.h/2)); };

	var icon = new OpenLayers.Icon(MAP.getRoot() + iconUrl, iconSize, null, calculateOffset);
	icon.imageDiv.style.cursor = 'pointer';

	var marker = null;
	marker = new OpenLayers.Marker(point, icon);

	marker.iconWidth = parseInt(iconWidth);
	marker.iconHeight = parseInt(iconHeight);
	marker.iconOffsetX = 0;
	marker.iconOffsetY = 0;
	marker.iconResize = true;
	marker.iconLink = '';

	if(iconSize.w < 5 || iconSize.h < 5) {
		marker.display(false);
	} else {
		marker.display(true);
	}
	
	this.markersResizing.push(marker);

	if(marker) {
		this.mapActiveObject = marker;
		layer.addMarker(this.mapActiveObject);
	}
}

// Initalize the object markers on map
map.prototype.setMarkersSearchObject = function (strBase64Search, strBase64Options) {
	var current = this;
	
	if(!this.isInitalized() || !this.hasThemes()) { return; };
	
	var url =  MAP.getRoot() + "map_search_objects.php?" + MAP.getSession() + "&search=" + strBase64Search + "&options=" + strBase64Options;

	OpenLayers.loadURL(url, '', this,
					function (response) {
						var XML = GXml.parse(response.responseText);

						var layer = current._createLayer("Markierung für gesuchte Objekte", "GEOBIP_MARKERS_SEARCH_OBJECT");
						
						for(var m=0;m<current.markersSearchObject.length;m++) {
							layer.removeMarker(current.markersSearchObject[m]);
							current.markersSearchObject[m].destroy();
						}

						delete current.markersSearchObject;
						current.markersSearchObject = new Array();

						if(XML && XML.documentElement) {
							var xmlMarkers = XML.documentElement.getElementsByTagName("marker");

							for(var m=0;m<xmlMarkers.length;m++) {
								var xmlMarker = xmlMarkers[m];

								var marker = current._createMarker(layer, xmlMarker, '');
								current.markersSearchObject.push(marker);
							}

							for(var m=0;m<current.markersSearchObject.length;m++) {
								layer.addMarker(current.markersSearchObject[m]);
							}
							
							delete xmlMarkers;
								
							// Show layer							
							layer.setVisibility(true);
						}
						
						delete XML;
					} );

	delete current;
}

// Set Base Layer
map.prototype.setBaseLayer = function (type) {
	if(!this.isInitalized()) { return; };
	
	var newBaseLayer = null;
	if(!newBaseLayer) {
		for(var i=0;i<this.mapBaseLayers.length;i++) {
			if(type == this.mapBaseLayers[i].mapType) {
				newBaseLayer = this.mapBaseLayers[i];
				break;
			}
		}
	}
	if(!newBaseLayer) {
		for(var i=0;i<this.mapThemes.length;i++) {
			if(type == this.mapThemes[i].mapType) {
				newBaseLayer = this.mapThemes[i];
				break;
			}
		}
	}
	if(!newBaseLayer) { return; };

	// Delete existing copyright for geobip
	var copyrightCtrls = this.mapObject.getControlsByClass("OpenLayers.Control.Copyright");
	for(var c=0;c<copyrightCtrls.length;c++) {
		copyrightCtrls[c].destroy();
	}

	// Set visibility for layers and set copyright
	if(newBaseLayer.mapType.substr(0, 6) == 'GOOGLE') {
		for(var i=0;i<this.mapLayers.length;i++) {
			this.mapLayers[i].setVisibility(false);
		}
	} else if(newBaseLayer.mapType.substr(0, 6) == 'GEOBIP') {
		for(var i=0;i<this.mapLayers.length;i++) {
			this.mapLayers[i].setVisibility(true);
		}
		
		this.mapObject.addControl(new OpenLayers.Control.Copyright());
	}

	// Last position and zoom
	if(this.mapBaseLayer != null) {
		var center = this.mapObject.getCenter();
		this.mapLastPosX = center.lon;
		this.mapLastPosY = center.lat;
		this.mapLastZoom = this.mapObject.getZoom();
	}

	this.mapObject.setBaseLayer(newBaseLayer);

	// Set new position by changing
	if(this.mapBaseLayer == null) {
		this.doStartMap();
	} else if(this.mapBaseLayer.mapType.substr(0, 6) == newBaseLayer.mapType.substr(0, 6)) {
		this.doCenter(this.mapLastPosX, this.mapLastPosY, this.mapLastZoom);
	} else if(newBaseLayer.mapType.substr(0, 6) == 'GOOGLE') {
		this.doCenter(this.mapLastPosX, this.mapLastPosY, this.mapLastZoom);
	} else if(newBaseLayer.mapType.substr(0, 6) == 'GEOBIP') {
		// Checks if new last point is in extent if not start map new
		this.mapBaseLayer = newBaseLayer;
		
		var lastPoint = new OpenLayers.LonLat(this.mapLastPosX, this.mapLastPosY);
		lastPoint = lastPoint.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:31467"));
		var maxExtent = this.mapObject.getMaxExtent() || this.mapBaseLayer.maxExtent;

		if(maxExtent.containsLonLat(lastPoint)) {
			this.doCenter(lastPoint.lon, lastPoint.lat, (this.mapLastZoom-11));
		} else {
			this.doStartMap();
		}
	}

	// Set current base layer
	this.mapBaseLayer = newBaseLayer;

	// Set town markers
	this.setMarkersTown();
}

// Returns an marker
map.prototype._createLayer = function (layerName, mapType) {
	if(!this.isInitalized()) { return; };
	
	var layer = null;
	for(var i=0;i<this.mapLayers.length;i++) {
		if(this.mapLayers[i].mapType == mapType) {
			layer = this.mapLayers[i];
			break;
		}
	}

	if(!layer) {
		var layer = new OpenLayers.Layer.Markers(layerName, { 'mapType': mapType }  );

		this.mapLayers.push(layer);
		this.mapObject.addLayer(layer);
	}
	
	return layer;
}

// Returns the new size by current resolution
map.prototype._getResolutionIconSize = function (width, height) {
	var units = this.mapBaseLayer.units;
	var originalResolution = 1200 / (OpenLayers.INCHES_PER_UNIT[units] * OpenLayers.DOTS_PER_INCH);
	var currentResolution = this.mapObject.getResolution();
	       	
	var newWidth = width * originalResolution / currentResolution;
	var newHeight = height * originalResolution / currentResolution;
		
	return new OpenLayers.Size(newWidth, newHeight);
}

// Returns an marker
map.prototype._createMarker = function (layer, xmlMarker, popupHTML) {
	var current = this;

	var posX	= xmlMarker.getAttribute('positionX') || '';
	var posY	= xmlMarker.getAttribute('positionY') || '';
	var zoom	= xmlMarker.getAttribute('zoom') || '';

	var iconUrl			= xmlMarker.getAttribute('iconUrl') || '';
	var iconUrlHover	= xmlMarker.getAttribute('iconUrlHover') || '';
	var iconWidth		= xmlMarker.getAttribute('iconWidth') || '';
	var iconHeight		= xmlMarker.getAttribute('iconHeight') || '';
	var iconOffsetX		= xmlMarker.getAttribute('iconOffsetX') || '';
	var iconOffsetY		= xmlMarker.getAttribute('iconOffsetY') || '';
	var iconResize		= xmlMarker.getAttribute('iconResize') || '';
	var iconTitle		= xmlMarker.getAttribute('iconTitle') || '';
	var iconLink		= xmlMarker.getAttribute('iconLink') || '';

	var point = new OpenLayers.LonLat(posX, posY);
	if(iconResize == 'true') {
		var iconSize = this._getResolutionIconSize(parseInt(iconWidth),parseInt(iconHeight));
	} else {
		var iconSize = new OpenLayers.Size(parseInt(iconWidth), parseInt(iconHeight));
	}

	if(iconOffsetX != '' && iconOffsetY != '') {
		if(iconResize == 'true') {
			var iconOffset = null;	//new OpenLayers.Pixel(-(iconSize.w/2), -(iconSize.h/2));
			var calculateOffset = function(size) {
				return new OpenLayers.Pixel(-(size.w/2), -(size.h/2));
			};
		} else {
			var iconOffset = new OpenLayers.Pixel(-(parseInt(iconOffsetX)), -(parseInt(iconOffsetY)));
			var calculateOffset = null;
		}
	} else {
		var iconOffset = null;	//new OpenLayers.Pixel(-(iconSize.w/2), -(iconSize.h/2));
		var calculateOffset = function(size) { return new OpenLayers.Pixel(-(size.w/2), -(size.h/2)); };
	}

	var icon = new OpenLayers.Icon(MAP.getRoot() + iconUrl, iconSize, iconOffset, calculateOffset);
	icon.imageDiv.title = iconTitle;
	icon.imageDiv.style.cursor = 'pointer';
	if(!isEmpty(iconUrlHover)) {
		icon.imageDiv.onmouseover = function(e) { icon.setUrl(iconUrlHover); };
		icon.imageDiv.onmouseout = function(e) { icon.setUrl(iconUrl); };
	}

	var marker = null;
	if(isEmpty(popupHTML)) {
		marker = new OpenLayers.Marker(point, icon);
	} else {
		var popUp = OpenLayers.Class(OpenLayers.Popup.FramedCloud, {
			            autoSize: true,
			            minSize: new OpenLayers.Size(300,220),
			            maxSize: new OpenLayers.Size(350,350),
			            isAlphaImage: true
			        } );
        
		var feature = new OpenLayers.Feature(layer, point); 
		feature.closeBox = true;
		feature.popupClass = popUp;
		feature.data.popupContentHTML = popupHTML;
		feature.data.icon = icon;
		feature.data.overflow = "auto";
		feature.data.height = "auto";
                    
		marker = feature.createMarker();
	}

	marker.iconWidth = parseInt(iconWidth);
	marker.iconHeight = parseInt(iconHeight);
	marker.iconOffsetX = parseInt(iconOffsetX);
	marker.iconOffsetY = parseInt(iconOffsetY);
	marker.iconResize = iconResize;
	marker.iconLink = iconLink;

	if(iconSize.w < 5 || iconSize.h < 5) {
		marker.display(false);
	} else {
		marker.display(true);
	}

	if(!isEmpty(popupHTML) && isEmpty(iconLink)) {
		marker.events.register("mousedown", feature, function (evt) {
                if (this.popup == null) {
                    this.popup = this.createPopup(this.closeBox);
                    current.mapObject.addPopup(this.popup);
                    this.popup.show();
                } else {
                    this.popup.toggle();
                }
                currentPopup = this.popup;
                OpenLayers.Event.stop(evt);
            } );
	} else if(!isEmpty(popupHTML) && !isEmpty(iconLink)) {
		marker.events.register("mousedown", feature, function (evt) {
                if (this.popup == null) {
                    this.popup = this.createPopup(this.closeBox);
                    current.mapObject.addPopup(this.popup);
                    this.popup.show();
                } else {
                    this.popup.toggle();
                }
                currentPopup = this.popup;

   				eval(this.iconLink);

                OpenLayers.Event.stop(evt);
            } );
	} else if(!isEmpty(iconLink)) {
		marker.events.register("mousedown", marker, function (evt) {
   				eval(this.iconLink);

    			OpenLayers.Event.stop(evt);
    		} );
	}
	
	if(iconResize == 'true') {
		this.markersResizing.push(marker);
	}
	
	delete current;
	
	return marker;
}

// Set towns and quarters in google maps
map.prototype.setMarkersTown = function () {
	var current = this;

	if(!this.isInitalized() || !this.isGoogleMap()) { return; };
	
	var url =  MAP.getRoot() + "map_towns.php?" + MAP.getSession();

	OpenLayers.loadURL(url, '', this,
					function (response) {
						var XML = GXml.parse(response.responseText);

						var layer = current._createLayer("Städte und Gemeinden mit Objekten", "GOOGLE_MARKERS_TOWN");
						
						for(var m=0;m<current.markersTown.length;m++) {
							layer.removeMarker(current.markersTown[m]);
							current.markersTown[m].destroy();
						}

						delete current.markersTown;
						current.markersTown = new Array();

						if(XML && XML.documentElement) {
							var xmlMarkers = XML.documentElement.getElementsByTagName("marker");

							for(var m=0;m<xmlMarkers.length;m++) {
								var xmlMarker = xmlMarkers[m];

								var townPk			= xmlMarker.getAttribute('townPk') || '';
								var townname		= xmlMarker.getAttribute('townname') || '';
								var towndistance	= xmlMarker.getAttribute('towndistance') || '';
								var townobjects		= xmlMarker.getAttribute('townobjects') || '';
								var towntooltip		= xmlMarker.getAttribute('towntooltip') || '';
								var posX			= xmlMarker.getAttribute('positionX') || '';
								var posY			= xmlMarker.getAttribute('positionY') || '';
								var zoom			= xmlMarker.getAttribute('zoom') || '';
								var projectX		= xmlMarker.getAttribute('projectX') || '';
								var projectY		= xmlMarker.getAttribute('projectY') || '';
								var projectZoom		= xmlMarker.getAttribute('projectZoom') || '';

								townname = townname.replace(/&amp;/g, '&');
								towntooltip = towntooltip.replace(/&amp;/g, '&');
								towntooltip = towntooltip.replace(/&lt;/g, '<');
								towntooltip = towntooltip.replace(/&gt;/g, '>');

								var html = '<div style="padding: 10px;">';
								html += '<div class="TextfettOrange">' + townname + '</div><br/>';
								if(parseInt(towndistance) > 0) {
									html += '<div class="Textnormal">Entfernung: ' + parseInt(towndistance) + ' km</div>';
								}
								html += '<div class="Textnormal">Objekte: <b>' + parseInt(townobjects) + '</b></div><br/>';
								if(towntooltip != '') {
									html += '<div class="Textnormal">' + towntooltip + '</div><br/>';
								}
								if(projectX != '' && projectY != '') {
									html += '<div align="center" style="margin:0px; padding:0px;"><a href="javascript:GeoBIP.loadMap(\'' + townPk + '\', \'\', \'' + projectX + '\', \'' + projectY + '\', \'' + projectZoom + '\');" class="SelectObject"><b>Objekte in Karte anzeigen</b></a></div>';
								}
								html += '</div>';

								var marker = current._createMarker(layer, xmlMarker, html);
								current.markersTown.push(marker);
							}

							for(var m=0;m<current.markersTown.length;m++) {
								layer.addMarker(current.markersTown[m]);
							}
							
							delete xmlMarkers;
	
							// Show layer							
							layer.setVisibility(true);
						}
						
						delete XML;
					} );

	delete current;
}

// Center map to start position with start zoom
map.prototype.doStartMap = function () {
	this.doCenter(this.mapStartPosX, this.mapStartPosY, this.mapStartZoom);
}

// Center map to position with zoom
map.prototype.doCenterBySelectfield = function (field) {
	var option = field.options[field.selectedIndex];

	if(option.getAttribute("positionX") != '' &&
		option.getAttribute("positionY") != '' &&
		option.getAttribute("zoom") != '') {
		this.doCenter(option.getAttribute("positionX"), option.getAttribute("positionY"), option.getAttribute("zoom"));
	}
}

// Center map to position with zoom
map.prototype.doCenter = function (posX, posY, zoom) {
	if(!this.isInitalized()) { return; }

	if(!isEmpty(posX) && !isEmpty(posY)) {
		this.mapLastPosX = posX;
		this.mapLastPosY = posY;
	
		var newPoint = new OpenLayers.LonLat(posX, posY);
		var currentExtent = this.mapObject.getExtent();
		var maxExtent = this.mapObject.getMaxExtent() || this.mapBaseLayer.maxExtent;

		if(maxExtent.containsLonLat(newPoint)) {
			if(currentExtent == null) {
				this.mapObject.setCenter(newPoint);
			} else {
				this.mapObject.panTo(newPoint);
			}
		} else {
			// Transform point from Gauss to LatLon
			var newPoint = newPoint.transform(new OpenLayers.Projection("EPSG:31467"), new OpenLayers.Projection("EPSG:4326"));
			if(maxExtent.containsLonLat(newPoint)) {
				if(currentExtent == null) {
					this.mapObject.setCenter(newPoint);
				} else {
					this.mapObject.panTo(newPoint);
				}
				
				zoom += 11;
			} else {
				var newPoint = new OpenLayers.LonLat(posX, posY);
				var newPoint = newPoint.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:31467"));
				if(maxExtent.containsLonLat(newPoint)) {
					if(currentExtent == null) {
						this.mapObject.setCenter(newPoint);
					} else {
						this.mapObject.panTo(newPoint);
					}

					zoom += 5;
				}
			}
		}
	}	

	if(!isEmpty(zoom) && zoom != this.mapObject.getZoom()) {
		var numZoomLevels = this.mapObject.getNumZoomLevels();

		if(numZoomLevels <= zoom) {
			zoom = numZoomLevels - 1;
		}
		if(zoom < 0) {
			zoom = 0;
		}
	
		this.mapLastZoom = zoom;
		this.mapObject.zoomTo(zoom);
	}
};

// Center map to position with zoom
map.prototype.doAddress = function (city, address) {
	var current = this;

	if(!this.isInitalized()) { return; }

	var googleGeocoder = new GClientGeocoder();
	googleGeocoder.getLatLng(city + ', ' + address,
							function(point) {
								if (point) {
									current.doCenter(point.lng(), point.lat(), 17);
								}
							} );
							
	delete current;
};

// Returns value for authorized
map.prototype.isAuthorized = function () {
	return this.authorized;
};

// Set value
map.prototype.initAuthorized = function () {
	this.authorized = true;
	
	if(this.isInitalized()) {
		this.mapObject.addControl(new OpenLayers.Control.MousePosition());
		this.mapObject.addControl(new OpenLayers.Control.ScaleLine());
		this.mapObject.addControl(new OpenLayers.Control.Scale());
	}
};

