function MapApplication(div)
{
	this.firstTimeRouting = 1;
	
	// Div Container of the MapApplication
	this.div = div;
	
	// Container for CitySearch
	this.divSearch
	
	// GMap2 Object
	this.map = null;
	
	// MapApplication Settings
	this.SelectedTrackobjectID = false;
	this.initializeMinimap = false;
	this.initializeMaptypeControl = false;
	this.initializeLargeNavigation = false
	this.initializeRouting = false;
	this.initializeCitySearch = false;
	if(location.href.search("edit_network")<0) this.initializePoi = true;
	else this.initializePoi = false;
	this.initializeNetEdit = false;
	this.initializeSearchBox = false;	
	this.initializePmio = false;
	this.initializeBikearena = false;
	this.initializeStreetview = false;
	this.openBettBikeLinkInParentWindow = false;	
	this.openBettBikeKnr = false;
	this.editTourID = false; // Nur NetEdit-Modus! Diese Tour wird im Tourmanager geöffnet
	
	this.guiUser = MMRegistry.guiDefault;	

	/* MapTypes */
	this.normalMap = null;
	this.satelliteMap = null;
	this.hybritMap = null;
	this.terrainMap = null;
	this.topoMap = null;
	
	this.bikeLayer = null;
	
	
	this.selectId = false;
	this.sid;
	this.showOnlySelectedTracks = false;
	
	// default: germany
	this.viewbox = new GLatLngBounds(new GLatLng(47.078665, 5.970464), new GLatLng(54.933123, 15.712364));	
}
MapApplication.prototype.setSelectedTrackobjectID = function(SelectedTrackobjectID){this.SelectedTrackobjectID = SelectedTrackobjectID;} 
MapApplication.prototype.setGuiUser = function(guiUser){this.guiUser = guiUser;}
MapApplication.prototype.setViewbox = function(latlngbounds){this.viewbox = latlngbounds;}
MapApplication.prototype.setSelectId = function(selectId, sid){this.selectId = selectId; this.sid = sid;}
MapApplication.prototype.setShowOnlySelectedTracks = function(bool){this.showOnlySelectedTracks = bool;}
MapApplication.prototype.setOpenBettBikeLinkInParentWindow = function(bool){this.openBettBikeLinkInParentWindow = bool;}
MapApplication.prototype.showBettBikeInfoWindow = function(knr){this.openBettBikeKnr = knr;}
MapApplication.prototype.editTour = function(id){this.editTourID = id;}


MapApplication.prototype.initStreetview = function(bool){this.initializeStreetview = bool;}
MapApplication.prototype.initMinimap = function(bool){this.initializeMinimap = bool;}
MapApplication.prototype.initRouting = function(bool){this.initializeRouting = bool;}
MapApplication.prototype.initCitySearch = function(bool){this.initializeCitySearch = bool;}
MapApplication.prototype.initMaptypeControl = function(bool){this.initializeMaptypeControl = bool;}
MapApplication.prototype.initLargeNavigationControl = function(bool){this.initializeLargeNavigation = bool;}

MapApplication.prototype.initBikearena = function(bool){this.initializeBikearena = bool;}
MapApplication.prototype.initPoi = function(bool){this.initializePoi = bool;}
MapApplication.prototype.initPmio = function(bool){this.initializePmio = bool;}
MapApplication.prototype.initNetEdit = function(bool){this.initializeNetEdit = bool;}
MapApplication.prototype.initSearchBox = function(bool){this.initializeSearchBox = bool;}

MapApplication.prototype.getMap = function(){return this.map;}
MapApplication.prototype.getNormalMapType = function(){return this.normalMap;}
MapApplication.prototype.getSatelliteMapType = function(){return this.satelliteMap;}
MapApplication.prototype.getHybritMapType = function(){return this.hybritMap;}
MapApplication.prototype.getTerrainMapType = function(){return this.terrainMap;}
MapApplication.prototype.getTopoMapType = function(){return this.topoMap;}



MapApplication.prototype.run = function()
{	

	if(!GBrowserIsCompatible()) return false;
	
	// create DIV Containers
	if(this.initializeCitySearch && this.initializeRouting)
	{		
		// create container for map
		var mapContainer = document.createElement("div");
		mapContainer.style.width = "100%";
		mapContainer.style.height = "90%";
		mapContainer.style.margin = "0px";
		mapContainer.style.padding = "0px";
		this.div.appendChild(mapContainer);
		
		//create container for citysearch
		this.divSearch = document.createElement("div");
		this.divSearch.style.height = "10%";
		this.div.appendChild(this.divSearch);
	}
	else
	{

		if(this.initializeSearchBox) {

			searchBoxContainer = new MMSearchBox(this.div);
			searchBoxContainer.initialize();
			searchBoxContainer.register();
		 	suggestAbility = new MMSuggestAbility('searchBox','searchHint',MMRegistry.urlPortal+'ajax/netEditSearchFeedback.php');
		 	
			var mapContainer = document.createElement("div");
			mapContainer.style.width = "100%";
			mapContainer.style.height = ((this.div.clientHeight-26)/this.div.clientHeight)*100+"%";
			mapContainer.style.margin = "0px";
			mapContainer.style.padding = "0px";
			this.div.appendChild(mapContainer);
			
		} else {
			// create container for map
			var mapContainer = document.createElement("div");
			mapContainer.style.width = "100%";
			mapContainer.style.height = "100%";
			this.div.appendChild(mapContainer);
		}
	}
	
		
	// create map object
	this.initializeMapLayers();
	this.map = new GMap2(mapContainer, {mapTypes: [this.terrainMap, this.satelliteMap, this.hybritMap, this.normalMap, this.topoMap]});
	
	
	
	// Viewbox settings
	var center = this.viewbox.getCenter();
	var zoom = this.map.getBoundsZoomLevel(this.viewbox);
	this.map.setCenter(center, zoom, this.terrainMap);
	this.map.savePosition();
	
	
	// Zoom settings
	this.map.enableScrollWheelZoom();
	this.map.enableDoubleClickZoom();
	this.map.enableContinuousZoom();
	
	mapContainer.onmousewheel = this.cancelZoomEvent; // IE
	GEvent.bindDom(mapContainer, "DOMMouseScroll", this, this.cancelZoomEvent);

	// initialize controls	
	this.initializeControls();
	
	// to prevent errors
	this.map.checkResize();
	
	if(this.selectId != false){
		window.sessionStorage.flag=1;

		var BBicon = new MMMenuIcon();
		BBicon.setImage(MMRegistry.urlPortal +"dateien/mapicons/BB.gif");
		BBicon.setTooltipText('alle fahrradfreundlichen Bett+Bike-Gastbetriebe an der Route');
		BBicon.setSize(40,40);
		BBicon.setPosition(new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(7,230)));	
		this.map.addControl(BBicon);
		
		BBWindow = new MMBBWindow();
		BBWindow.setPosition(new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(70,50)));		
		this.map.addControl(BBWindow);
		
		GEvent.bind(BBicon, "click", this, function(){			
			BBWindow.show2(this.SelectedTrackobjectID);
		});
		BBicon.show(); 
		
	}else window.sessionStorage.flag=2;
}


MapApplication.prototype.cancelZoomEvent = function(e)
{
	if (!e) e = window.event;
	if (e.preventDefault) e.preventDefault();
	e.returnValue = false;	
}

MapApplication.prototype.initializeMapLayers = function()
{
	/* initialize layers */
	var mapLayer = G_NORMAL_MAP.getTileLayers()[0];
	var streetLayer = G_HYBRID_MAP.getTileLayers()[1];
	var satelliteLayer = G_SATELLITE_MAP.getTileLayers()[0];
	var terrainLayer = G_PHYSICAL_MAP.getTileLayers()[0];

	var topoLayer = new MMWmsTileLayer(new GCopyrightCollection("MM_Topo"), 4, 14, 1.0);
	topoLayer.baseURL = MMRegistry.urlGetMapRequest +"?";
	topoLayer.layers = "MM_TOPO";	
	
	this.bikeLayer = new MMWmsTileLayer(new GCopyrightCollection("MM_BIKETRACKS"), 4, 14, 0.7);
		
	if(this.selectId)
	{		
		this.bikeLayer = new MMWmsTileLayer(new GCopyrightCollection("MM_BIKETRACKS"), 4, 14, 0.7);
		this.bikeLayer.baseURL = MMRegistry.urlGetMapRequest +"?selectId="+ this.selectId +"&sid="+ this.sid;
		
		if(this.showOnlySelectedTracks) this.bikeLayer.layers = "MM_BIKEROUTE";
		else this.bikeLayer.layers = "MM_BIKETRACKS,MM_BIKEROUTE";		
	}
	else
	{
		this.bikeLayer.baseURL = MMRegistry.urlGetMapRequest +"?";
		this.bikeLayer.layers = "MM_BIKETRACKS";
	}
	
	
	/* initialize maps */
	this.normalMap = new GMapType([mapLayer, this.bikeLayer], G_NORMAL_MAP.getProjection(), "Karte", {alt:"Stadtplan anzeigen", errorMessage:"No data available", maxResolution:17, minResolution:1});
	this.satelliteMap = new GMapType([satelliteLayer, this.bikeLayer], G_SATELLITE_MAP.getProjection(), "Satellit", {alt:"Satellitenbilder anzeigen", errorMessage:"No data available", maxResolution:18, minResolution:1});
	this.hybritMap = new GMapType([satelliteLayer, this.bikeLayer, streetLayer], G_SATELLITE_MAP.getProjection(), "Hybrit", {alt:"Satellitenbilder mit StraÃŸennamen anzeigen", errorMessage:"No data available", maxResolution:18, minResolution:1});
	this.terrainMap = new GMapType([terrainLayer, this.bikeLayer], G_PHYSICAL_MAP.getProjection(), "GelÃ¤nde", {alt:"Stadtplan mit GelÃ¤nde anzeigen", errorMessage:"No data available", maxResolution:15, minResolution:1});
	this.topoMap = new GMapType([topoLayer, this.bikeLayer], G_NORMAL_MAP.getProjection(), "Topo", {alt:"Topographie anzeigen", errorMessage:"No data available", maxResolution:14, minResolution:1});
}
	
MapApplication.prototype.initializeControls = function()
{	
	
	var mapItemControl = new MMMapItemsControl();
	mapItemControl.InitializePanoramio(this.initializePmio);	
	mapItemControl.InitializeBettBike(this.initializePoi, this.openBettBikeKnr);
	mapItemControl.InitializeBikearena(this.initializeBikearena);

	//mapItemControl.InitializeStreetview(true);
	
	this.map.addControl(mapItemControl);

	
	
	
	if(this.initializeMinimap) this.map.addControl(new GOverviewMapControl());

	if(this.initializeMaptypeControl)
	{
		var mapTypeControl = new GHierarchicalMapTypeControl();
		mapTypeControl.addRelationship(this.satelliteMap, this.hybritMap, "Labels anzeigen", true);
		
		this.map.addControl(mapTypeControl);		
	}
	
	if(this.initializeLargeNavigation) this.map.addControl(new StreetViewControl());	
	else this.map.addControl(new GSmallMapControl());

	
	if(this.initializeRouting || this.initializeNetEdit)
	{
		
		///// START - Segment-Filter
		var filtericon = new MMMenuIcon();	
		filtericon.setImage(MMRegistry.urlPortal + "dateien/icon_filter.gif");
		filtericon.setTooltipText("Filter zur Selektion von Strecken");
		filtericon.setSize(32,32);
		filtericon.setPosition( new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(20,312)) );
		
		this.map.addControl(filtericon);
		filtericon.show();
		
		var filterWindow = new MMFilterWindow();
		filterWindow.setPosition(new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(70,50)));		
		this.map.addControl(filterWindow);
			
		GEvent.bind(filtericon, 'click', this, function(){
			filterWindow.show();
		});
		
		
		// Ergebnis des Segment-Filters überwachen und Karte aktualisieren
		document.observe("widget:refreshMap", function (event){
			
			filterWindow.hideWindow();
			var json = event.memo.evalJSON();
			
			this.selectId = json.selectId;
			this.sid = json.sid;
				
			// zoome heraus und setze neue URL für die Bildkacheln
			this.map.zoomOut();
						
			if(this.selectId)
			{
				this.bikeLayer.baseURL = MMRegistry.urlGetMapRequest +"?selectId="+ this.selectId +"&sid="+ this.sid;
				
				if(this.showOnlySelectedTracks) this.bikeLayer.layers = "MM_SEGMENT";
				else this.bikeLayer.layers = "MM_BIKETRACKS,MM_SEGMENT";
				
			}
			else
			{
				this.bikeLayer.baseURL = MMRegistry.urlGetMapRequest +"?";
				this.bikeLayer.layers = "MM_BIKETRACKS";
			}		

			// gehe zur vorherigen Zoomstufe zurück (neue Kartenkacheln werden geladen))
			this.map.zoomIn();			
				
			
		}.bindAsEventListener(this));		
		
		///// ENDE - Segment-Filter	
		
	
	}
	
	
	// Routing
	if(this.initializeRouting)
	{
		
		// Messwerkzeug
		this.map.addOverlay(new MMMeasureTool());

		var routing = new MMDirections(this.map);
			
		// Warenkorb	
		var basketIcon = new MMMenuIcon();
		basketIcon.setImage(MMRegistry.urlPortal +"dateien/mapicons/basket.gif");
		basketIcon.setTooltipText('Tour in den Warenkorb legen');
		basketIcon.setSize(40,40);
		basketIcon.setPosition(new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(7,170)));	
		this.map.addControl(basketIcon);
						
		GEvent.bind(basketIcon, "click", this, function(){			
			basketIcon.hide();
			
			var comma = false;
			var routeIds = "";
			for(var i=0; i<routing.CountRoutes(); i++)
			{
				if(comma) routeIds += ",";
				else comma = true;
				routeIds += routing.GetRoute(i).getId();
			}
			
			var url = MMRegistry.urlPortal +"basket.php";
			var para = "action=addPolylineResponse&responseIds="+ routeIds; 
			
			this.infoBuyInProcess = new MMTooltip("Bitte warten Sie: Tour wird gerade aufbereitet<br>und in den Warenkorb gelegt...");
			this.map.addControl(this.infoBuyInProcess);
			this.infoBuyInProcess.show({x:60,y:17});
		
			new Ajax.Request(
				url,
				{
					method: 'get',	
					parameters: para,
					onSuccess: function(transport)
					{							
						this.map.removeControl(this.infoBuyInProcess);
						
						var buySuccessInfo = new MMHTMLTooltip("<table><tr><td>Die Tour wurde in den Warenkorb gelegt.</td></tr><tr><td align=\"center\"><input id=\"btnClose\" type=\"button\" value=\"Ok\"></form></td></tr></table>");
						
						this.map.addControl(buySuccessInfo);
						buySuccessInfo.show(new GPoint(200, 200));
						
						GEvent.bindDom($('btnClose'), 'click', this, function(){
							this.map.removeControl(buySuccessInfo);
						});
						
					}.bind(this)
				});
				
				
				
		});
		
		
		// Download	
		var downloadIcon = new MMMenuIcon();
		downloadIcon.setImage(MMRegistry.urlPortal +"dateien/mapicons/TourDownload.gif");
		downloadIcon.setTooltipText('Tour herunterladen');
		downloadIcon.setSize(40,40);
		downloadIcon.setPosition(new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(7,170)));	
		this.map.addControl(downloadIcon);
		
		GEvent.bind(downloadIcon, "click", this, function(){
			
			var comma = false;
			var routeIds = "";
			for(var i=0; i<routing.CountRoutes(); i++)
			{
				if(comma) routeIds += ",";
				else comma = true;
				routeIds += routing.GetRoute(i).getId();
			}
			
			var url = MMRegistry.urlPortal +"commands.php";
			url += "?cmd=routingToGpx&responseIds="+ routeIds; 			
			window.open(url);
			
	
		});
		

		GEvent.bind(routing, "routechanged", this, function(){			
			var invalidPath = false;
			for(var i=0; i<routing.CountRoutes(); i++)
			{
				if(routing.GetRoute(i).getVertexCount() <= 2) invalidPath = true;
			}
			if(routing.CountWaypoints()<2)invalidPath = true;
			if(invalidPath)
			{
				basketIcon.hide();
				downloadIcon.hide();
			}
			else
			{
				if(routing.IsCostfree())downloadIcon.show();
				else basketIcon.show();
			}
		});
		
		
		// Toureigenschaften
		var tourIcon = new MMMenuIcon();
		tourIcon.setImage(MMRegistry.urlPortal +"dateien/mapicons/Info.gif");
		tourIcon.setTooltipText('Streckeninformation');
		tourIcon.setSize(40,40);
		tourIcon.setPosition(new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(7,215)));	
		this.map.addControl(tourIcon);
		
		infoWindow = new MMRoutingInfoWindow();
		infoWindow.setPosition(new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(70,50)));		
		this.map.addControl(infoWindow);
				
		GEvent.bind(tourIcon, "click", this, function(){			
			infoWindow.show(routing);
		});
		
		
		// BBicon
		var BBicon = new MMMenuIcon();
		BBicon.setImage(MMRegistry.urlPortal +"dateien/mapicons/BB.gif");
		BBicon.setTooltipText('alle fahrradfreundlichen Bett+Bike-Gastbetriebe an der Route');
		BBicon.setSize(40,40);
		BBicon.setPosition(new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(7,260)));	
		this.map.addControl(BBicon);
		
		BBWindow = new MMBBWindow();
		BBWindow.setPosition(new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(70,50)));		
		this.map.addControl(BBWindow);
		
		GEvent.bind(BBicon, "click", this, function(){			
			BBWindow.show(routing);
		});
		//BBicon.show();
		
		GEvent.bind(routing, "routechanged", this, function(){			
			var invalidPath = false;
			for(var i=0; i<routing.CountRoutes(); i++)
			{
				if(routing.GetRoute(i).getVertexCount() <= 2) invalidPath = true;
			}
			if(routing.CountWaypoints()<2)invalidPath = true;
			if(invalidPath){
				BBicon.hide();
				tourIcon.hide();
			}
			else{
				BBicon.show();
				tourIcon.show();
			}
		});
		
		
		if(this.initializeCitySearch)
		{
			var citySearch = new MMCitySearchControl(routing);
			citySearch.initialize(this.divSearch);		
		}
				
		// Routing Kontextmenu				
		var routingContextMenu = new MMContextmenu(this.map, "singlerightclick");
		this.map.addControl(routingContextMenu);
		
		routingContextMenu.addItem("Route von hier", this, function(point){
			routing.AddStart(point);
			if(routing.CountWaypoints() > 1){
				if(this.firstTimeRouting)routing.bikeToolWindow.show(routing.GetRoute(0));	
				this.firstTimeRouting = 0;
			}
		});
		
		routingContextMenu.addItem("Route hierher", this, function(point){
			routing.AddEnd(point);
			if(routing.CountWaypoints() > 1){
				if(this.firstTimeRouting)routing.bikeToolWindow.show(routing.GetRoute(0));	
				this.firstTimeRouting = 0;
			}
		});
		
		routingContextMenu.addSeparator();
		
		routingContextMenu.addItem("Vergr&ouml;&szlig;ern", this, function(point){
			this.map.setCenter(point, this.map.getZoom()+1);
		});
		
		routingContextMenu.addItem("Verkleinern", this, function(point){
			this.map.zoomOut();
		});
		
		routingContextMenu.addItem("Karte hier zentrieren", this, function(point){
			this.map.panTo(point);
		});	
	};
	
	//Netzwerk editieren
	if(this.initializeNetEdit) {
		this.netedit = new MMNetEdit(this.map, this.guiUser);
		
		GEvent.bind(this.netedit, "routechanged", this, function(){			
			var invalidPath = false;
			for(var i=0; i<this.netedit.CountRoutes(); i++)
			{
				if(this.netedit.GetRoute(i).getVertexCount() <= 2) invalidPath = true;
			}
		});
				
		//Kontextmenu				
		var neteditContextMenu = new MMContextmenu(this.map, "singlerightclick");
		this.map.addControl(neteditContextMenu);
		
/*
		neteditContextMenu.addItem("POI hier setzen", this, function(point){
			this.netedit.AddPOI(point);
		});		
		
		neteditContextMenu.addSeparator();
*/		
		neteditContextMenu.addItem("alle Markierungen aufheben", this, function(point){
			var someNode = $('searchBox');
			someNode.fire("widget:removeselection");
		});		
		
		neteditContextMenu.addSeparator();
		
		neteditContextMenu.addItem("Route von hier", this, function(point){
			this.netedit.AddStart(point, true);
		});
		
		neteditContextMenu.addItem("Route hierher", this, function(point){
			this.netedit.AddEnd(point, true);
		});
		
		neteditContextMenu.addSeparator();
		
		neteditContextMenu.addItem("Vergr&ouml;&szlig;ern", this, function(point){
			this.map.setCenter(point, this.map.getZoom()+1);
		});
		
		neteditContextMenu.addItem("Verkleinern", this, function(point){
			this.map.zoomOut();
		});
		
		neteditContextMenu.addItem("Karte hier zentrieren", this, function(point){
			this.map.panTo(point);
		});	
		
		if(this.initializeSearchBox) {
		searchBoxContainer.setMap(this.map);
		Event.observe($('actionButton'),'click', function() {
			if($F('hiddenType')=='place'){
				this.map.setCenter(new GLatLng($F('hiddenMinLat'),$F('hiddenMinLng')));
				this.map.setZoom(13);
			} else if($F('hiddenType')=='tour'){
				this.map.setCenter(new GLatLng( (parseFloat($F('hiddenMinLat'))+parseFloat($F('hiddenMaxLat')))/2 ,(parseFloat($F('hiddenMinLng'))+parseFloat($F('hiddenMaxLng')))/2));
				this.map.setZoom( this.map.getBoundsZoomLevel( new GLatLngBounds( new GLatLng($F('hiddenMinLat'),$F('hiddenMinLng')) , new GLatLng($F('hiddenMaxLat'),$F('hiddenMaxLng')) ) ) );
				//this.FetchSegment(0,0,2,$('hiddenId').value);
				
				this.netSelector.Clear();
				this.netSelector.SelectSegmentByLatLng(this.map.getCenter());
				//wie komme ich hier ran ???
			}
		$('searchHint').hide();
		}.bindAsEventListener(this.netedit));
		}
		
		
		// öffne Tour im Editiermodus
		if(this.netedit && this.editTourID)
		{
			this.netedit.etappeToolWindow.changeTour(this.editTourID);
			this.netedit.etappeToolWindow.showWindow();
		}		
	}
	
	
	
	if(this.initializeStreetview) {
		
		  var myPano = new GStreetviewPanorama(document.getElementById("map"));
		  fenwayPark = new GLatLng(52.519913,13.372036);
		  myPOV = {yaw:51.5, pitch:0};
		  myPano.setLocationAndPOV(fenwayPark, myPOV);
		
		  this.map.getContainer().style.display = "none";
	}

	



}
