WebAppDir = '/SADB';
CMSWebAppDir = '/SADB';
YellowPageEntryURL = '/branchenbuch/hamburg/eintrag/';
POI_PATH = 'http://www.hamburg.de/';
MARKER_PATH = '/images/icons';
SITESTAT_URL = 'http://site.hamburg.de/hamburg/hamburg/s?sonstiges.de.de.stadtplan.stadtplan-1-1_1458&amp;amp;category=VB_RUB_stadtplan_AGOF_295_DOCT_topic_LID_1458_QUE_0_OID_0_DEB_0_FREE_0_THE_0_AKT_0_PROD_0_';

function getQueryArgs(query) {
	
	var args  = new Object();
	var str = query.search.substring(1);
	var pairs = str.split("&");

	for (var i=0; i < pairs.length; i++) {

		var pos = pairs[i].indexOf('=');
		if (pos == -1) continue;

		var argname  = pairs[i].substring(0,pos);
		var argvalue = pairs[i].substring(pos+1);

		args[argname] = argvalue;
	}
	return args;
}

PolyLine = new Class({
	initialize: function (map, points, fixed, optimize, color) {
	
		var isNew = (!points || (points.length == 0));
		if (null == points) points = [];
		this.fixed = false;
		this.map = map;
		this.isEdit = false;
		this.startLine(points,color?color:'red');
		GEvent.trigger(this.line,"lineupdated");
		if (optimize) this.setOptimizedView();
		this.fixed = !(fixed==false);
		if (!isNew || this.fixed) this.stopEdit()
		else this.line.enableDrawing();
		if (!this.fixed) {
			GEvent.addListener(this.map, "singlerightclick", this.removeLast.bind(this));
		}
	},
	setOptimizedView: function(result) {
		var len = this.line.getVertexCount() || 0;
		var minX = 0;
		var maxX = 0;
		var minY = 0;
		var maxY = 0;

		// get required view size
		for (var i=0; i < len; i++) {
		 	var point = this.line.getVertex(i);
		 	if (i==0) {
				minX = point.lng();
				maxX = point.lng();
				minY = point.lat();
				maxY = point.lat();
		 	} else {
				if (point.lng() < minX) minX = point.lng();
				if (point.lng() > maxX) maxX = point.lng();
				if (point.lat() < minY) minY = point.lat();
				if (point.lat() > maxY) maxY = point.lat();
		 	}
		}
		try {
			min = new GLatLng(minY,minX);
			max =  new GLatLng(maxY,maxX);
			var bounds = new GLatLngBounds(min,max);
			this.map.setCenter(bounds.getCenter(),this.map.getBoundsZoomLevel(bounds));
		} catch (e) {
		}
	},
	zoomIn: function () {
		this.map.zoomIn(this.map.getCenter(), false,false);
	},
	zoomOut: function () {
		this.map.zoomOut(this.map.getCenter(), false);
	},
	wheelZoom: function (a) {
		if (a.cancelable) a.preventDefault();
        if (a.detail || -a.wheelDelta) {
			var latlng = new GLatLng(this.mouselat,this.mouselng);
			if ((a.detail || -a.wheelDelta) < 0)
				this.map.zoomIn(latlng, false,false);
			else if ((a.detail || -a.wheelDelta) > 0)
				this.map.zoomOut(latlng, false);
        }
        return false;
	},
	transformCoords: function(x,y) {
		new Ajax(
			WebAppDir + '/LDAPProcessor?cmd=de.redero.ldap.sadb.cmd.SADBAjaxGeoTransformCommand' + 
			'&x=' + x + 
			'&y=' + y
			,
			{	
				method: 'get',
				requestHeaders: {Accept: 'application/json'},
				async: false,
				onSuccess: this.setValues
			}
		).request();
	},
	setValues: function(transport) {
		coords = Json.evaluate('(' + transport.responseText + ')');
		if ($('wgs84')) {
			$('wgs84').innerHTML += coords.wgs84_x + ',' + coords.wgs84_y + ';\n';
			$('gk3').innerHTML += coords.gk3_x + ',' + coords.gk3_y + '\n';
			$('gk4').innerHTML += coords.gk4_x + ',' + coords.gk4_y + '\n';
		}
	},
	newLine: function(pnts) {
        if (this.fixed) return;
		if (!pnts) pnts = [];
		if ($('wgs84')) {
			$('wgs84').innerHTML = '';
			$('gk3').innerHTML = '';
			$('gk4').innerHTML = '';
			$('length').innerHTML = '';
		}
		this.map.clearOverlays();
		this.startLine(pnts,'red');
        this.line.enableDrawing();
	},
	removeLast: function() {
        if (this.fixed) return;
		if (this.line && this.isEdit) {
			var len = this.line.getVertexCount() || 0;
			var pnts = [];
			for (i=0; i < len-1; i++) {
			 	pnts.push(this.line.getVertex(i));
			}
			this.newLine(pnts);
			GEvent.trigger(this.line,"lineupdated");
		}					
	},
	startDrawing: function(color) {
          if (this.fixed) return;
		  this.map.addOverlay(this.line);
		  this.line.enableEditing({onEvent: "mouseover"});
		  this.line.disableEditing({onEvent: "mouseout"});
		  this.isEdit=true;
		  GEvent.addListener(this.line, "lineupdated", 
			(function() {
				if ($('wgs84')) {
			    	$('wgs84').innerHTML = '';
			 		$('gk3').innerHTML = '';
			 		$('gk4').innerHTML = '';
				    $('length').innerHTML = (Math.round(this.line.getLength() / 100) / 10) + "&nbsp;km";
			 		var len = this.line.getVertexCount()||0;
			 		for(var i=0; i<len; i++){
			 			var point = this.line.getVertex(i);
			 			this.transformCoords(point.lng().toFixed(6), point.lat().toFixed(6));
			 		}
				}
			  }).bind(this)
		  );
		  GEvent.addListener(this.line, "endline",
		  	(function() {
		    	GEvent.addListener(this.line, "click", function(latlng, index) {
			      if ((typeof index == "number") && (this.line)) {
			    	  this.line.deleteVertex(index);
			      }
		    	});
		    	this.isEdit=false;
		 	}).bind(this)
		 );
	},
    startLine: function(pnts, color) {
        if (this.fixed) return;
        if (this.line) {
              this.line.disableEditing();
              this.line.hide();
        }
        var opacity=0.5;
        var thickness=4;
        if (color=='transparent') {
              opacity=0;
        }
        this.line = new GPolyline(pnts, color, thickness, opacity);
        this.startDrawing(color);
	}, 
	editLine: function() {
          if (this.fixed) return;
		  if (this.line) {
		  	this.line.enableEditing();
		  	this.line.enableDrawing();
		  	this.isEdit=true;
		  }
	},
	stopEdit: function() {
		  if (this.line) {
		  	this.line.disableEditing();
		  	this.line.disableEditing({onEvent: "mouseover"});
		  	this.isEdit=false;
		  }
	}
});

LocalSearch = new Class ({
	initialize: function(queryIO) {
		this.queryIO = queryIO;
		this.optimizeView=true;
		this.catkey = '';
		this.lastQuery = null;
		this.result = null;
		this.sStat = null;
		this.pStat = null;
		this.listeners = new Array();
		this.queryIO.queryInput.addEvent('change',(function () { this.catKey = '' }).bind(this));
		window.addEvent('unload',this.deregisterEvents.bind(this));
	},
	registerEvents: function() {
	},
	deregisterEvents: function() {
		for(i=this.listeners.length-1;i >= 0; i--) {
			GEvent.removeListener(this.listeners[i]);
			this.listeners.pop(i);
		}
	},
	checkSubmit: function(event) {
		var event = new Event(event);
		if (event.code == 13) this.gotoPage(0);
	},
	search: function(query,address,page,catkey,optimizeView, postListHandling) {

		if (null != postListHandling) this.plh = postListHandling

		var catParam = '';
		// do not query example text
		if (address) address = address.trim();
		if (query) query = query.trim();
		if (address==LocalSearchInOutControler.DEFAULT_WO) address='';
		if (query==LocalSearchInOutControler.DEFAULT_WAS) query='';
		if ((query + address).length == 0) return false;
		this.queryIO.setQuery(query);
		this.queryIO.setAddress(address);
		this.optimizeView=(optimizeView || (optimizeView==null));
		if (query != this.lastQuery) catkey = ''; 
		this.lastQuery = query 
		this.catkey = catkey;
		if ((page == null) || (page.length == 0)) page = 0;
		if (catkey) catParam = '&catkey=' + this.catkey;
		requestURL = WebAppDir + '/proxy.jsp?call=1&allowdistrict=false' +
			'&from=' + (page * LocalSearchInOutControler.HITS_PER_PAGE) +
			'&hitsperpage=' + LocalSearchInOutControler.HITS_PER_PAGE +
			'&query=' + encodeURIComponent(query).replace(/\+/g,'%20') + '&streetaddress=' + encodeURIComponent(address).replace(/\+/g,'%20') + catParam +
			'&cs=wgs84';
		
		if (this.requestURL != requestURL) {
			this.requestURL = requestURL;
			new Ajax(
				this.requestURL,
				{
					method: 'get',
					headers: ['Accept','text/json','If-Modified-Since', 'Sat, 1 Jan 2000 00:00:00 GMT'],
					async: true,
					onSuccess: (function (transport) {
						this.handleQueryResult(transport)
						if (this.plh) this.plh();
					}).bind(this)
				}
			).request();
			if (this.queryIO.queryInput.suggester) {
				this.queryIO.queryInput.suggester.autoSuggest();
			}
		} else if (this.result) {
				this.queryIO.displayResult(this.result,this.optimizeView);
				GEvent.trigger(this,'searchsubmit',this);
		}
		return false;
	},
	list: function(ids, postListHandling) {

		if (null != postListHandling) this.plh = postListHandling

		if (ids && (ids.length > 0)) {
			var requestURL = WebAppDir + '/proxy.jsp?call=4' +
				'&from=0' + 
				'&hitsperpage=-1' + 
				'&ids=' + encodeURIComponent(ids) + 
				'&cs=wgs84';

			new Ajax(
				requestURL,
				{
					method: 'get',
					headers: ['Accept','text/json','If-Modified-Since', 'Sat, 1 Jan 2000 00:00:00 GMT'],
					async: true,
					onSuccess: (function (transport) {
						this.handleListResult(transport)
						if (this.plh) this.plh();
					}).bind(this)
				}
			).request();
			GEvent.trigger(this.queryIO.mapControler.app,'useraction',this);
		}
	},
	handleQueryResult: function(transport) {
		this.deregisterEvents();
		GEvent.trigger(this,'searchsubmit',this);
		try {
			var result = Json.evaluate('(' + transport.replace(/[^[\x0A\0xD\x20-\xFF]/g,"") + ')');
			this.queryIO.displayResult(result,this.optimizeView);
			this.optimizeView=true;
			this.result = result;
		} catch (ex) {
		}
		this.registerEvents();
		GEvent.trigger(this,'searchsubmit',this);
		this.callSearchStatistics(result);
	},
	handleListResult: function(transport) {
		this.deregisterEvents();
		try {
			var result = Json.evaluate('(' + transport.replace(/[^[\x0A\0xD\x20-\xFF]/g,"") + ')');

			this.queryIO.displayResult(result,this.optimizeView);
			if (result.routes != null) {
				for (var i=0;i<result.routes.length; i++) {
					for (var j=0; j < result.routes[i].vertex.length; j++) {
						result.routes[i].vertex[j] = new GLatLng(result.routes[i].vertex[j][1], result.routes[i].vertex[j][0]);
					}
					new PolyLine(this.queryIO.mapControler.map, result.routes[i].vertex, true, this.optimizeView, this.queryIO.mapControler.routeColor);
				}
			}
			this.optimizeView=true;
			this.result = result;
		} catch (ex) {
		}
		this.registerEvents();
		GEvent.trigger(this,'searchsubmit',this);
	},
	setRoute: function (id, maxLayerDistance, color) {
		this.queryIO.mapControler.setRoute(id, maxLayerDistance, color)
	},
	hasRoute: function () {
		return null != this.queryIO.mapControler.routeID;
	},
	gotoPage: function(pageNo) {
		this.search(this.queryIO.queryInput.value, this.queryIO.addressInput.value,pageNo,this.catkey);
	},
	getLink: function() {
		var link = document.location.protocol + '//' + document.location.host + document.location.pathname + '?';
		var center = this.queryIO.mapControler.map.getCenter();
		link += 'c=' + center.x + ','  + center.y;
		link += '&z=' + this.queryIO.mapControler.map.getZoom();
		if (this.result && this.result.routes && (this.result.routes.length > 0)) {
			link += '&r=' + this.result.routes[0].id
			if (this.queryIO.mapControler.maxLayerDistance) 
				link += '&d=' + this.queryIO.mapControler.maxLayerDistance
			if (this.queryIO.mapControler.routeColor) 
				link += '&rc=' + this.queryIO.mapControler.routeColor.replace(/#/,'')
		}
		var pls = '';
		for (i=0;i < this.queryIO.mapControler.poiLayers.layers.length; i++) {
			if (pls.length > 0) pls += ',';
			pls += this.queryIO.mapControler.poiLayers.layers[i].id;
		}
		if (pls.length > 0) link += '&pl=' + pls;
		if (this.result) {
			if (this.result.address && this.result.address.name.length > 0) 
				link += '&wo=' + encodeURIComponent(this.result.address.name);
			if (this.result.currentPage != null) {
				if (this.result.query.length > 0) {
					link += '&was=' + encodeURIComponent(this.result.query);
					link += '&p=' + Math.max(0,this.result.currentPage+1);
					link += '&cat=' + this.result.catkey;
				}
			}
			if (this.result.hits && (this.result.query.length == 0)) {
				link += "&ids="
				for(i=0; i < this.result.hits.length; i++) {
					if (i > 0) link += ",";
					link += this.result.hits[i].id;
				}
			}
		}
		return link;
	},
	setLink: function(id) {
		var linkContainer = $(id); 
		if (linkContainer) linkContainer.value = this.getLink();
	},
	callSearchStatistics: function(result) {
		if (result.currentPage == 0) {
			if (null == this.sStat) {
				this.sStat = new Element('img');
				this.sStat.width=1;
				this.sStat.height=1;
				this.sStat.injectInside(document.body);
			}
			var imgURL = SITESTAT_URL + '&amp;ns_search_term=' + this.toASCII7woWhitespace(result.query);
			imgURL += '&amp;ns_search_result=' + result.numOfHits;
			this.sStat.src = imgURL;
		}
	},
	toASCII7woWhitespace:function (text) {
		var text = text.toLowerCase();
		var t = '';
		for(i=0;i<text.length;i++) {
			var c = text.charAt(i);
			var code = c.charCodeAt(0);
			if (code==228) c='ae';
			else if (code==246) c='oe';
			else if (code==252) c='ue';
			else if (code==223) c='ss';
			else if ((c < 'a') || (c > 'z')) {
				c='_'; 
			}
			t += c;
		}
		return t.replace(/__/g,'_');
	}
});


LocalSearchInOutControler = new Class({
	initialize: function(queryInput, addressInput, resultContainer, mapControler) {
		this.queryInput = queryInput;
		this.addressInput = addressInput;
		this.addressInput.value=LocalSearchInOutControler.DEFAULT_WO;
		this.queryInput.value=LocalSearchInOutControler.DEFAULT_WAS;
		
		this.resultContainer = resultContainer;
		this.mapControler = mapControler;
		GEvent.addDomListener(this.queryInput,'focus',this.	toggleDefault.bind(this,this.queryInput));
		GEvent.addDomListener(this.queryInput,'blur',this.toggleDefault.bind(this,this.queryInput));
		GEvent.addDomListener(this.addressInput,'focus',this.toggleDefault.bind(this,this.addressInput));
		GEvent.addDomListener(this.addressInput,'blur',this.toggleDefault.bind(this,this.addressInput));
	},
	setQuery: function (queryText) {
		var text = '';
		if (queryText) text = queryText;
		if (text.length == 0) text = LocalSearchInOutControler.DEFAULT_WAS;
		this.queryInput.value = text;
	},
	toggleDefault: function(field) {
		if (field == this.addressInput) {
			if (this.addressInput.value == LocalSearchInOutControler.DEFAULT_WO)
				this.addressInput.value = "";
			else if (this.addressInput.value == "")
				this.addressInput.value = LocalSearchInOutControler.DEFAULT_WO;
		} else if (field == this.queryInput) {
			if (this.queryInput.value == LocalSearchInOutControler.DEFAULT_WAS)
				this.queryInput.value = "";
			else if (this.queryInput.value == "")
				this.queryInput.value = LocalSearchInOutControler.DEFAULT_WAS;
		}
	},
	setAddress: function (addressText) {
		var text = '';
		if (addressText) text = addressText;
		if (text.length == 0) text = LocalSearchInOutControler.DEFAULT_WO;
		this.addressInput.value = text;
	},
	clearSimilarLocations: function() {
		if ($('similarLocationList')) {
			$('similarLocationList').setHTML('');
		}
	},
	showAddressInfo: function(result) {
		var html = '';
		if ($('similarLocationList')) {
		}
	},
	displayResult: function(result, optimizeView) {
		this.clearResult();
		this.writeHeader(result);
		if (result.hasHits) {
			this.writeHits(result);
		}
		this.mapControler.setResultMarkers(result,optimizeView);
	},
	clearResult: function() {
		this.resultContainer.empty();
		this.mapControler.clearResult();
	},
	writeHeader: function(result) {
		var html = '';
		var noHit = !result.hasHits && (result.query.length > 0);
		if ((this.addressInput.value.length > 0) && (result.query.length == 0)) {
			html = '<strong class="ergebnistext">';
			html += 'Sie suchten: "' + this.addressInput.value + '"';
			html += '</strong>';
		} else if (result.query.length > 0) {
			html = '<strong class="ergebnistext">';
			html += 'Sie suchten: "' + result.query + '"';
			if (result.address) {
				if (result.isPOI) html += ' in der N&auml;he von <strong>' + result.address.name + '</strong>';
				else html += ' in <strong>' + result.address + '</strong>';
			} else if (result.district) html += ' in <strong>' + result.district + '</strong>';
			html += '</strong>';
		}
		html += '<input type="submit" onclick="newSearchRequest();" class="btn red bg-yellow m_u05" value="&laquo; Neue Suche" />';
		if (noHit) html += '<p class="clear_important error">Ihre Suche ergab kein Ergebnis.</p>'

		this.clearSimilarLocations();

		if (result.similarLocations) {
			html += '<strong class="clear_important clearfix">Ihre Suchanfrage hat mehrere Treffer ergeben:</strong>';
			html += '<ul">'
			for(i=0;i < result.similarLocations.length; i++) {
				html += '<li><a title="\'' + result.similarLocations[i][2] + '\' ausw&auml;hlen" onclick="searcher.queryIO.addressInput.value=\'' + result.similarLocations[i][2] + '\';searcher.gotoPage(0);" href="javascript:void(0)">' + result.similarLocations[i][2] + '</a></li>';
			}
			html += '</ul>';
		} else if (result.address || result.district) {
			var location = result.address;
			if (!location) location = result.district;
			this.addressInput.value = location.name;
			html += '<ul id="position" class="ergebnis_opt clear_important clearfix standort">';
			var addressParts = location.name.split(',');
			

			html += '<li><span class="bild_float-2"><a title="Standort in Karte anzeigen" href="javascript:void(0)">';
			if (addressParts.length > 1) {
				html += '<img alt="' + location.name + '" class="float_left m_u05" src="' + MARKER_PATH + '/standort_flagge.gif"></a></span><span class="text_float-3">';
				html += '<a title="' + location.name + '" href="javascript:void(0)">' + addressParts[0] + '<br />';
				html += '<span class="adresse">' + addressParts[1] + '</span>';
			} else {
				html += '<br />';
			}
			html += '</a></span></li>';
		} else if (result.message){
			html += '<p class="clear_important error">Die eingegebene Adresse ist unbekannt.<br />Bitte &uuml;berpr&uuml;fen Sie die Schreibweise.</p>';
		}
		this.resultContainer.setHTML(html);
	},
    writeHits: function(result) {
		
		if (result.similarLocations || result.message) return;
        var hits = result.hits;
        var hitList = new Element('div');
        hitList.id = 'result_location';
        var html = '<ul class="clear_important clearfix ergebnis_opt">';
        for (i=0; hits && (i < hits.length) ; i++) {
            var img = MARKER_PATH;
            if (hits[i].customerType > 0) {
            	img += '/nadel_blau_' + hits[i].hitNo + '_k.png';
            } else {
            	img += '/nadel_orange_' + hits[i].hitNo + '_k.png';
            }
        	html += '<li id="hit_' + hits[i].hitNo + '">';
            html += '<span class="bild_float-2">';
            html += '<a href="javascript:void(0)" title="' + hits[i].name + '">';
            html += '<img alt="' + hits[i].name + '" class="float_left" src="' + img + '"></a>';
            html += '</a>';
            html += '</span>';
            var address = hits[i].street;
            if (hits[i].street.length > 0) address += '&nbsp;';
            address += hits[i].streetNo;
            if ((address.length > 0) && (hits[i].zip.length) > 0) address += ', ';
            address += hits[i].zip;
            if (hits[i].zip.length > 0) address += '&nbsp;';
            address += hits[i].city;
            var dist = hits[i].distance.replace(/ /g,'&nbsp;');;
            if (dist.length > 0) dist = '&nbsp;(' + dist + ')';
            html += '<span class="text_float-3 adresse">';
            html += '<a href="javascript:void(0)" title="' + hits[i].name + '">';
            html += '<strong>' + hits[i].name + '</strong>';
            html += '</a>';
            html += dist;
            html += '<br />' + address;
            html += '</span>';
            html += '</li>';
        }
        html += '</ul>';
        html += this.getPaginationHTML(result)
        hitList.setHTML(html);
        hitList.injectInside(this.resultContainer);
    },
    getPaginationHTML: function(result) {
		if (!result.hasHits) return;

		var cPage = result.currentPage;
		var maxPages = result.numOfPages;
		var startPage = 0;
		var endPage = maxPages;
		var html = '<ul class="pagination">';

		if ((maxPages > 1) && (result.numOfHits > result.pageSize)) {
			if ((result.numOfHits > (LocalSearchInOutControler.MAX_PAGELINKS-1)) && (maxPages >= LocalSearchInOutControler.MAX_PAGELINKS)) {
				startPage = ((cPage % LocalSearchInOutControler.MAX_PAGELINKS) > 0)?(((cPage-(cPage % LocalSearchInOutControler.MAX_PAGELINKS)) / LocalSearchInOutControler.MAX_PAGELINKS) * LocalSearchInOutControler.MAX_PAGELINKS):cPage;
				if (cPage == (LocalSearchInOutControler.MAX_PAGELINKS-1)) startPage = startPage+1;
				if ((maxPages - startPage) < LocalSearchInOutControler.MAX_PAGELINKS) startPage = maxPages - LocalSearchInOutControler.MAX_PAGELINKS;
				if ((startPage + LocalSearchInOutControler.MAX_PAGELINKS) < maxPages) {
					endPage = Math.min(startPage + LocalSearchInOutControler.MAX_PAGELINKS,maxPages);
				}
			}
			if (cPage > 0) {
				html += '<li><a class="prevnext" href="javascript:searcher.gotoPage('+ (Math.max(0,cPage-1)) + ')" title="vorherige">vorherige</a></li>';
			} 
			for (i=startPage; i < endPage; i++) {
				if (i!=cPage)
					html += '<li><a href="javascript:searcher.gotoPage(' +  i + ')" title="Zu Trefferseite ' + (i+1) + '">' + (i+1) + '</a></li>';
				else 
					html += '<li><a class="current" href="javascript:searcher.gotoPage(' +  i + ')" title="Zu Trefferseite ' + (i+1) + '">' + (i+1) + '</a></li>';
			} 
			if (cPage < (maxPages-1)) {
				html += '<li><a class="prevnext" href="javascript:searcher.gotoPage(' + Math.min(cPage+1,maxPages-1) + ')" title="n&auml;chste">n&auml;chste</a></li>';
			} 
		} 
		html += '</ul>';
		return html;
	}
});
LocalSearchInOutControler.DEFAULT_WO = '';
LocalSearchInOutControler.DEFAULT_WAS = '';
LocalSearchInOutControler.MAX_PAGELINKS = 5;
LocalSearchInOutControler.HITS_PER_PAGE = 4;



LayerContainer = new Class({
	initialize: function(mapControler) {
		this.layers = new Array();
		this.mapControler = mapControler;
		this.layerBounds = this.mapControler.map.getBounds();
		GEvent.addListener(this.mapControler.map,'moveend',this.refreshAll.bind(this));
		GEvent.addListener(this.mapControler.map,'zoomend',this.refreshAll.bind(this));
	},
	loadLayer: function(layerID) {
		var size = this.mapControler.map.getSize();
		
		var sw = this.mapControler.map.fromContainerPixelToLatLng(
			new GPoint(
				0 - size.width * LayerContainer.PRELOAD_FACTOR,
				size.height * LayerContainer.PRELOAD_FACTOR
			)
		);
		var ne = this.mapControler.map.fromContainerPixelToLatLng(
			new GPoint(
				size.width * LayerContainer.PRELOAD_FACTOR,
				0 - size.height * LayerContainer.PRELOAD_FACTOR
			)
		);
		this.layerBounds = new GLatLngBounds(sw,ne);
		var url = WebAppDir + '/proxy.jsp?call=2&layer=' + layerID +
			'&ll=' + this.layerBounds.getSouthWest().lng() + ',' +  this.layerBounds.getSouthWest().lat() +
			'&ur=' + this.layerBounds.getNorthEast().lng() + ',' +  this.layerBounds.getNorthEast().lat() + 
			'&cs=wgs84';
		if (mapControler.routeID) {
			url += '&r=' + mapControler.routeID + "&d=" + mapControler.maxLayerDistance
		}
		new Ajax (
             url,	
			 {
				method: 'get',
				headers: ['Accept','text/json','If-Modified-Since', 'Sat, 1 Jan 2000 00:00:00 GMT'],
				async: true,
				onSuccess: this.addLayer.bind(this)
			 }
		).request();
	},
	addLayer: function(transport) {
		var jsonResponse = Json.evaluate('(' + transport.replace(/[^[\x0A\0xD\x20-\xFF]/g,"") + ')');

		var pois = jsonResponse.pois;
		var id = jsonResponse.id;

		this.removeLayer(id);

		var layer = new MarkerManager(this.mapControler.map);
		Object.extend({isvalid: true, isactive: true, id: id },layer);
		layer.id = id;
		layer.isvalid = true;
		layer.isactive = true;

		var markers = new Array();
		var unlimitedZoom = false;
		if (jsonResponse.pois && (jsonResponse.pois.length > 0)) {
			for (i=0; i < pois.length; i++) {
				var poiIcon = new GIcon();
				unlimitedZoom = unlimitedZoom || pois[i].unlimitedZoom;
				if ((!unlimitedZoom && (this.mapControler.map.getZoom() < LayerContainer.VISIBILITY_MAX_ZOOM))
					||
					(unlimitedZoom && (this.mapControler.map.getZoom() < LayerContainer.VISIBILITY_UNLIMITED_ZOOM))
				) {
					layer.isvalid = false;
					layer.isactive = false;
					markers = new Array();
					i = pois.length;
				} else {
					poiIcon.image = POI_PATH + pois[i].icon;
					poiIcon.iconSize = new GSize(pois[i].iconHeight,pois[i].iconWidth);
					poiIcon.iconAnchor = new GPoint(pois[i].iconOffsetX,pois[i].iconOffsetY);
					poiIcon.infoWindowAnchor = new GPoint(pois[i].bubbleOffsetX,pois[i].bubbleOffsetY);
					var marker = new GMarker(new GLatLng(pois[i].gcY, pois[i].gcX), { icon: poiIcon, draggable: false, title: pois[i].name });
					marker.bindInfoWindow(this.mapControler.getInfoWindowHtml(pois[i]), { maxTitle: pois[i].name, maxContent: this.mapControler.maxContentDiv, maxWidth: 300 });
					GEvent.addListener(marker,'infowindowopen', (function(hit) {
						this.hitInInfoWindow = hit;
					}).bind(this.mapControler,pois[i]));
					markers.push(marker);
				}
			}
		}
		if (unlimitedZoom) {
			layer.addMarkers(markers,LayerContainer.VISIBILITY_UNLIMITED_ZOOM);
			if (markers.length > 0) {
				uLayer = new Array(markers[Math.floor(markers.length/2)]);
				layer.addMarkers(uLayer,0);
			}
			layer.maxZoom = LayerContainer.VISIBILITY_UNLIMITED_ZOOM;
		} else {
			layer.addMarkers(markers,LayerContainer.VISIBILITY_MAX_ZOOM);
			layer.maxZoom = LayerContainer.VISIBILITY_MAX_ZOOM;
		}
		this.layers.push(layer);
		if (layer.isvalid) this.showLayer(id);
	},
	getLayer: function(id) {
		for (i=0;i < this.layers.length; i++) {
			if (this.layers[i].id == id) 
				return this.layers[i];
		}
		return null;
	},
	refreshAll: function() {
		var currentBounds = this.layerBounds; 
		for (i=0;i < this.layers.length; i++) {
			var layer = this.layers[i];
			if (!currentBounds.containsBounds(this.mapControler.map.getBounds())) {
				layer.isvalid = false;
				this.refreshLayer(layer.id);
			} else if (!layer.isvalid && !layer.isactive) {
				this.refreshLayer(layer.id);
			}
		}
	},
	refreshLayer: function(id) {
		var layer = this.getLayer(id);
		if (layer) {
			if (((layer.maxZoom != LayerContainer.VISIBILITY_UNLIMITED_ZOOM) && (this.mapControler.map.getZoom() < LayerContainer.VISIBILITY_MAX_ZOOM)) ||
				((layer.maxZoom == LayerContainer.VISIBILITY_UNLIMITED_ZOOM) && (this.mapControler.map.getZoom() < LayerContainer.VISIBILITY_UNLIMITED_ZOOM))) {
				this.hideLayer(layer.id);
				
			} else if (!layer.isvalid || !layer.isactive) {
				this.loadLayer(layer.id);
			}
			else {
				this.showLayer(layer.id);
			}
		}
	},
	showLayer: function(id) {
		var layer = this.getLayer(id);
		if (layer) {
			if (((layer.maxZoom != LayerContainer.VISIBILITY_UNLIMITED_ZOOM) && (this.mapControler.map.getZoom() >= LayerContainer.VISIBILITY_MAX_ZOOM)) ||
				((layer.maxZoom == LayerContainer.VISIBILITY_UNLIMITED_ZOOM) && (this.mapControler.map.getZoom() >= LayerContainer.VISIBILITY_UNLIMITED_ZOOM))) {
				layer.refresh();
				layer.isactive = true;
	            GEvent.trigger(this.mapControler.app,'poilist_show',id);
			}
		} else this.loadLayer(id);
	},
	hideLayer: function(id) {
		var layer = this.getLayer(id);
		if (layer) {
			layer.clearMarkers();
			layer.refresh();
			layer.isactive=false;
		}
	},
	setVisible: function(id, visible) {
		if (visible) {
			if (this.mapControler.map.getZoom() < LayerContainer.VISIBILITY_MAX_ZOOM) {
				this.mapControler.map.setCenter(this.mapControler.map.getCenter(),LayerContainer.VISIBILITY_MAX_ZOOM);
			}
			this.showLayer(id);
		}
		else this.removeLayer(id);
        GEvent.trigger(this.mapControler.app,'poilist_change',id);
	},
	hasVisibleLayers: function() {
		for (i=0;i < this.layers.length; i++) {
			if (this.layers[i].isactive) 
				return true;
		}
		return false;
	},
	removeAllLayers: function() {
		for (i=0;i < this.layers.length; i++)
			this.removeLayer(this.layers[i].id);
	},
	removeLayer: function(id) {
		for (i=0;i < this.layers.length; i++) {
			if (this.layers[i].id == id) {
				this.layers[i].clearMarkers();
				this.layers[i].refresh();
				this.layers.splice(i,1);
	            GEvent.trigger(this.mapControler.app,'poilist_hide',id);
				return;
			}
		}
	}
});
LayerContainer.VISIBILITY_MIN_ZOOM = 17;
LayerContainer.VISIBILITY_MAX_ZOOM = 15;
LayerContainer.VISIBILITY_UNLIMITED_ZOOM = 9;
LayerContainer.PRELOAD_FACTOR = 1.3;	

LocalSearchMapControler = new Class({
	initialize: function(mapApplication) {
		this.app = mapApplication;
		this.map = mapApplication.map;
		this.searchResultLayer = new MarkerManager(this.map);
		this.resultDisplayed = false;
		this.isAddressChanged = false;
		this.poiLayers = new LayerContainer(this);
		this.mapCenter = this.map.getCenter();
		this.maxContentDiv = new Element('div');

		GEvent.addListener(this.map.getInfoWindow(),'maximizeclick', this.getMaxInfoWindowHtml.bind(this));
	},
	refreshLayers: function() {
		this.poiLayers.refreshAll();
	},
	getMaxContentDiv: function() {
		return this.maxContentDiv;
	},
	focusHit: function (hitNo) {
		try {
			hitMarker = this.searchResultLayer.findMarkerById('hit_' + hitNo);
			if (hitMarker) {
				this.map.setCenter(hitMarker.position);
				hitMarker.showInfoWindow();
			}
		} catch (e) {
		} 
		GEvent.trigger(this.app,'useraction',this);
	},
	centerHome: function() {
		this.map.setCenter(this.mapCenter,LocalSearchMapControler.POSITION_ONLY_ZOOM);
		this.refreshLayers();
		GEvent.trigger(this.app,'useraction',this);
	},
	centerMap: function(position) {
		if (!position) position = new GLatLng(this.app.DefaultMapCenter.x, this.app.DefaultMapCenter.y);
		this.map.setCenter(position);
		this.refreshLayers();
		this.mapCenter = position;
	},
	setCurrentPosition: function(address, addressText) {
		this.isAddressChanged=false;
		if (this.app.CurPosMarker) this.map.removeOverlay(this.app.CurPosMarker);
		if (address || this.app.CurPosMarker) {
			if (address && this.app.CurPosMarker) {
				if ((address.gcY != this.app.CurPosMarker.getLatLng().lat()) ||
					(address.gcX != this.app.CurPosMarker.getLatLng().lng()))
						this.isAddressChanged = true;
			} else this.isAddressChanged = true;
		} else this.isAddressChanged = true;
		if (address) {
			var position = new GLatLng(address.gcY, address.gcX);
			this.centerIcon = new GIcon();
			this.centerIcon.image = MARKER_PATH + "/standort_1_schatten.png";
			this.centerIcon.iconSize = new GSize(41,55);
			this.centerIcon.iconAnchor = new GPoint(5,50);
			this.centerIcon.infoWindowAnchor = new GPoint(30,15);
			if (!addressText) addressText = 'Ihr Standort'; 
			var toolTip = addressText + ': ' + address.name;
			this.app.CurPosMarker = new GMarker(position, { icon: this.centerIcon, draggable: false, title: toolTip });
			var bubbleHtml = '<span>' + addressText + ':<br/><strong>' + address.name + '</strong></span>';
			bubbleHtml += '<br/><form onsubmit="return false;">'
			bubbleHtml += '<label>Suche in der N&auml;he</label>';
			bubbleHtml += '<input style="width: 200px" name="bquery" type="text" autocomplete="off"/>';
			bubbleHtml += '<input type="submit" value="Suchen" onclick="searcher.search(this.form.bquery.value,\'' + address.name + '\',0,\'\')"/><br />';
			bubbleHtml += '<span class="f_grau80">Was? (z.B. "Hotel" oder "Restaurant")</span>'
			bubbleHtml += '</form>';
			this.app.CurPosMarker.bindInfoWindow(bubbleHtml);
			this.map.addOverlay(this.app.CurPosMarker);
			this.mapCenter = position;
			
			if ($('position')) {
				GEvent.addDomListener($('position'),'click',
					this.app.CurPosMarker.openInfoWindow.bind(
						this.app.CurPosMarker,
						bubbleHtml
					)
				);
			}
		} else this.app.CurPosMarker = null;
	},
    setRoute: function (id, maxLayerDistance, color) {
            this.routeID = id;
            this.maxLayerDistance = maxLayerDistance;
            if (color && (0 != color.indexOf('#')) && (color != 'transparent')) {
                    color = '#' + color
            }
            this.routeColor = color;
    },
	setResultMarkers: function (result, optimizeView) {
		this.setCurrentPosition(result.address);
		if (!result.hits && optimizeView) this.centerHome();

		if (result.hits) {
			for (i=0; i < result.hits.length; i++) {
				this.addResultMarker(result.hits[i]);
			}
			this.searchResultLayer.refresh();
			this.resultDisplayed = true;
			if (optimizeView) this.setOptimizedView(result);
		}
		if (this.isAddressChanged && this.app.CurPosMarker) GEvent.trigger($('position'),'click');
	},
	clearResult: function() {
		this.searchResultLayer.clearMarkers();
		this.resultDisplayed = false;
	},
	addResultMarker: function (hit){
		if (hit.gcX && hit.gcY && (hit.gcX > 0) && (hit.gcY > 0) ) {
			var iconID = hit.hitNo;
			var position = new GLatLng(hit.gcY,hit.gcX);
			var hitIcon = new GIcon();
			if (hit.customerType > 0) { 
				hitIcon.image = MARKER_PATH + '/nadel_blau_' + iconID + '.png';
			} else {
				hitIcon.image = MARKER_PATH + '/nadel_orange_' + iconID + '.png';
			}
			hitIcon.shadow = MARKER_PATH + '/nadel_schatten.png';
					hitIcon.shadowSize = new GSize(46,44);
			hitIcon.iconSize = new GSize(22,44);
			hitIcon.iconAnchor = new GPoint(11,44);
			hitIcon.infoWindowAnchor = new GPoint(15,15);
			var marker = new GMarker(position, { icon: hitIcon, draggable: false, title: hit.name });
			var bubbleHtml = this.getInfoWindowHtml(hit);
			marker.bindInfoWindow(bubbleHtml, { maxTitle: hit.name, maxContent: this.maxContentDiv, maxWidth: 300 });
			
			GEvent.addListener(marker,'infowindowopen', (function(hit) {
				this.hitInInfoWindow = hit;
			}).bind(this,hit));
			
			GEvent.addDomListener($('hit_' + hit.hitNo),'click', 
				(function() {
					marker.openInfoWindow(
						bubbleHtml,
						{ maxTitle: hit.name, maxContent: this.maxContentDiv, maxWidth: 300 }
					)
					this.map.getInfoWindow().enableMaximize();
				}).bind(this)
			);
			this.searchResultLayer.addMarker(marker,LocalSearchMapControler.RESULT_MAX_ZOOM);
		}
	},
	getInfoWindowHtml: function (hit) {
		var trefferIcon = "images/treffer_info_icon.gif";
		html = '<h3><div style="width: 250px; margin-right: 1em;">' + hit.name + '</div></h3>';
		html += '<div class="pl_blau80_o m_o03" style="width: 360px">';
		if (hit.logo && (hit.logo.length > 0)) {
			if (hit.logolink && (hit.logolink.length > 0)) {
				html += '<a href="' + hit.logolink + '" rel="nofollow">';
			}
			html += '<img src="' + hit.logo + '&width=150&height=150&keepRatio=true" alt="' + hit.name + '" class="noborder float_right m_140">'
			if (hit.logolink && (hit.logolink.length > 0)) {
				html += '</a>';
			}
		}
		html += '<p class="m_o03">'
		html += hit.street + '&nbsp;' + hit.streetNo + '<br/>';
		if (hit.locationInfo && (hit.locationInfo.length > 0)) {
			html += hit.locationInfo + '<br/>';
		}
		html += hit.zip + ' ' + hit.city + '<br/>';

		if ((hit.bookinglink==null) || (hit.bookinglink.length == 0)) {
			if (hit.phone && (hit.phone.length > 0))
				html += '<br/>' + hit.phone;
		} else {
			html += '<br/><a href="' + hit.bookinglink + '" target="_blank">&Uuml;bernachtungen buchen</a>';
		}
		html += '</p>';
        if ((hit.bookinglink==null) || (hit.bookinglink.length == 0)) {
			if (hit.mail && (hit.mail.length > 0))
				 html += 'E-Mail: <a href="mailto:' + hit.mail + '">' + hit.mail + '</a><br/>';
			if (hit.homepage && (hit.homepage.length > 0) && (hit.homepage != hit.detailsLink)) {
				 if (hit.homepage.indexOf("http") != 0) hit.homepage = "http://" + hit.homepage;
				 html += '<a title="Homepage" href="#" onclick=window.open("' + hit.homepage + '","hitdetails","height=600,width=600,resizable=yes,scrollbars=yes,status=no,toolbar=yes,location=yes,menubar=yes").focus()>' + (hit.homepageLabel.length>0?hit.homepageLabel:'Homepage von ' + hit.name) + '</a><br/>';
			}
		}
		if (hit.description && (hit.description.length > 0))
			 html += '<a title="weitere Details" href="javascript:void(0);" onclick="mapControler.map.getInfoWindow().maximize()">weitere Details</a><br/>';
		if (hit.id) {
			if (hit.entrytype != "befi") {
				html += '<a href="' + YellowPageEntryURL + hit.id + '/" title="Eintrag im Branchenbuch anzeigen">Eintrag im Branchenbuch anzeigen</a><br/>';
			} else {
				html += '<a href="http://www.hamburg.de/behoerdenfinder/hamburg/' + hit.id + '/" title="Eintrag im Beh&ouml;rdenfinder anzeigen">Eintrag im Beh&ouml;rdenfinder anzeigen</a><br/>';
			}
		}
		if (favControler && favControler.isLoggedIn())
			html += '<div id="favAnchor"><a title="Zu Lieblingsliste hinzuf&uuml;gen" href="javascript:void(0);" onclick="favControler.displayWindow($(\'favAnchor\'))">Zu Lieblingsliste hinzuf&uuml;gen</a></div>';
		html += '<br/><form onsubmit="return false;">'
		html += '<label>Suche in der N&auml;he</label>';
		html += '<input style="width: 200px" name="bquery" type="text" autocomplete="off"/>';
		html += '<input type="submit" value="Suchen" onclick="searcher.search(this.form.bquery.value,\'' + hit.street + ' ' + hit.streetNo + ',' + hit.zip + ' ' + hit.city + '\',0,\'\')"/><br />';
		html += '<span class="f_grau80">Was? (z.B. "Hotel" oder "Restaurant")</span>'
		html += '</form>';
		html += '</div>';
		return html;
	},
	 getMaxInfoWindowHtml: function () {
	 	var hit = this.hitInInfoWindow;
		if (!hit) return '';
		var trefferIcon = "images/treffer_info_icon.gif";
		html = '<h3><div style="width: 420px; margin-right: 1em;">' + hit.name + '</div></h3>';
		html += '<div class="pl_blau80_o m_o03" style="width: 450px">';
		if (hit.logo && (hit.logo.length > 0)) {
			if (hit.logolink && (hit.logolink.length > 0)) {
				html += '<a href="' + hit.logolink + '" target="blank" rel="nofollow">';
			}
			html += '<img src="' + hit.logo + '&width=150&height=150&keepRatio=true" alt="' + hit.name + '" class="noborder float_right m_140">'
			if (hit.logolink && (hit.logolink.length > 0)) {
				html += '</a>';
			}
		}
		html += '<p class="m_o03">'
		html += hit.street + '&nbsp;' + hit.streetNo + '<br/>';
		if (hit.locationInfo && (hit.locationInfo.length > 0)) {
			html += hit.locationInfo + '<br/>';
		}
		html += hit.zip + ' ' + hit.city + '<br/>';
        if ((hit.bookinglink==null) || (hit.bookinglink.length == 0)) {
			if (hit.phone && (hit.phone.length > 0))
				html += '<br/>' + hit.phone;
		} else {
			html += '<br/><a href="' + hit.bookinglink + '" target="_blank">&Uuml;bernachtungen buchen</a>';
		}
		html += '</p>';
        if ((hit.bookinglink==null) || (hit.bookinglink.length == 0)) {
			if (hit.mail && (hit.mail.length > 0))
				 html += 'E-Mail: <a href="mailto:' + hit.mail + '">' + hit.mail + '</a><br/>';
			if (hit.homepage && (hit.homepage.length > 0) && (hit.homepage != hit.detailsLink)) {
				 if (hit.homepage.indexOf("http") != 0) hit.homepage = "http://" + hit.homepage;
				 html += '<a title="Homepage" href="#" onclick=window.open("' + hit.homepage + '","hitdetails","height=600,width=600,resizable=yes,scrollbars=yes,status=no,toolbar=yes,location=yes,menubar=yes").focus()>' + (hit.homepageLabel.length>0?hit.homepageLabel:'Homepage von ' + hit.name) + '</a><br/>';
			}
		}
		if (hit.id) {
			if (hit.entrytype != "befi") {
				html += '<a href="' + YellowPageEntryURL + hit.id + '/" title="Eintrag im Branchenbuch anzeigen">Eintrag im Branchenbuch anzeigen</a><br/>';
			} else {
				html += '<a href="http://www.hamburg.de/behoerdenfinder/hamburg/' + hit.id + '/" title="Eintrag im Beh&ouml;rdenfinder anzeigen">Eintrag im Beh&ouml;rdenfinder anzeigen</a><br/>';
			}
		}
		if (favControler && favControler.isLoggedIn())
			html += '<div id="favAnchor"><a title="Zu Lieblingsliste hinzuf&uuml;gen" href="javascript:void(0);" onclick="favControler.displayWindow($(\'favAnchor\'))">Zu Lieblingsliste hinzuf&uuml;gen</a></div>';
		if (hit.description && (hit.description.length > 0)) {
			html += '<p class="m_o03">'
			html += hit.description;
			html += '</p>';
		} 	
		html += '<form onsubmit="return false;">'
		html += '<label>Suche in der N&auml;he</label>';
		html += '<input style="width: 200px" name="bquery" type="text" autocomplete="off"/>';
		html += '<input type="submit" value="Suchen" onclick="searcher.search(this.form.bquery.value,\'' + hit.street + ' ' + hit.streetNo + ',' + hit.zip + ' ' + hit.city + '\',0,\'\')"/><br />';
		html += '<span class="f_grau80">Was? (z.B. "Hotel" oder "Restaurant")</span>'
		html += '</form>';
		html += '</div>';
		this.maxContentDiv.setHTML(html);
	},
	setOptimizedView: function(result) {
		if (!(result.hasHits || result.address)) return;

		var hasCenter = result.address && result.address.gcX && (result.address.gcX > 0) && result.address.gcY && (result.address.gcY > 0);

		// get required view size
		var minX = 0;
		var maxX = 0;
		var minY = 0;
		var maxY = 0;

		var added = false;
		if (result.hasHits) {
			for (i=0; i < result.hits.length; i++) {
				if (result.hits[i].gcX && result.hits[i].gcX && (result.hits[i].gcX > 0) && (result.hits[i].gcY > 0)) {
					if (!added) { 
						minX = result.hits[i].gcX;
						maxX = result.hits[i].gcX;
						minY = result.hits[i].gcY;
						maxY = result.hits[i].gcY;
						added = true;
					} else {
						if (result.hits[i].gcX < minX) minX = result.hits[i].gcX;
						if (result.hits[i].gcX > maxX) maxX = result.hits[i].gcX;
						if (result.hits[i].gcY < minY) minY = result.hits[i].gcY;
						if (result.hits[i].gcY > maxY) maxY = result.hits[i].gcY;
					}
				}
			}
		}
		
		if (hasCenter) {
			if (!added) { 
				minX = result.address.gcX;
				maxX = result.address.gcX;
				minY = result.address.gcY;
				maxY = result.address.gcY;
				added = true;
			} else {
				if (result.address.gcX < minX) minX = result.address.gcX;
				if (result.address.gcX > maxX) maxX = result.address.gcX;
				if (result.address.gcY < minY) minY = result.address.gcY;
				if (result.address.gcY > maxY) maxY = result.address.gcY;
			}
		}

		if ((minX == 0) || (maxX == 0) || (minY == 0) || (maxY == 0)) return;
		
		try {
			min = new GLatLng(minY,minX);
			max =  new GLatLng(maxY,maxX);
			var bounds = new GLatLngBounds(min,max);
			this.map.setCenter(bounds.getCenter(),Math.min(LocalSearchMapControler.RESULT_MIN_ZOOM,this.map.getBoundsZoomLevel(bounds)));
			this.mapCenter = bounds.getCenter();
		} catch (e) {
		}
	}
});
LocalSearchMapControler.DEFAULT_ZOOM = 14;
LocalSearchMapControler.RESULT_MIN_ZOOM = 15;
LocalSearchMapControler.RESULT_MAX_ZOOM = 9;
LocalSearchMapControler.POSITION_ONLY_ZOOM = 15;


GMapApp = new Class({
	initialize: function(mapElem, size, options) {
		this.map = new GMap2($(mapElem), { size: size });
		this.DefaultMapCenter = new GLatLng(GMapApp.DefaultMapCenterX,GMapApp.DefaultMapCenterY);
		if (options.center) this.mapCenter = options.center;
		else this.mapCenter = this.DefaultMapCenter;
		var zoom = LocalSearchMapControler.DEFAULT_ZOOM;
		if (options.zoom) zoom = options.zoom;
		if (options.defaultLayer) this.defaultLayer = options.defaultLayer 
		this.map.setCenter(this.mapCenter,zoom);
		this.CurPosMarker = new GMarker(this.mapCenter);
	}
});
GMapApp.DefaultMapCenterX = 53.55052821972251;
GMapApp.DefaultMapCenterY = 9.992684353061003;


FavListCategory = new Class ({
	initialize: function(internalName,name) {
		this.internalName=internalName;
		this.name=name;
	}
});
FavList = new Class ({
	initialize: function(uuid,name,category, description) {
		this.uuid=uuid;
		this.name=name;
		this.category=category;
		this.description=description;
	},
	display: function (container) {
	}
});
FavList.DEFAULT_NAME='Neue Lieblingsliste';
FavList.DEFAULT_DESCRIPTION='Dies ist meine Lieblingsliste';


FavListControler = new Class ({
	initialize: function() {
		this.lists = null;
		this.categories = null;
		this.favListWindow = null;
		this.cContainer = null;
		this.getLists();	  		
		new Ajax(
			FavListControler.URL_CATEGORIES,
			{
				method: 'get',
				headers: ['Accept','text/json','If-Modified-Since', 'Sat, 1 Jan 2000 00:00:00 GMT'],
				async: true,
				onSuccess: this.handleCategoryResult.bind(this),
				onError: ( function () {
					this.categories = null;
				}).bind(this)
			}
		).request();
		GEvent.addListener(mapControler.map,'infowindowclose',this.closeWindow.bind(this));
		GEvent.addListener(mapControler.map.getInfoWindow(),'maximizeclick',this.closeWindow.bind(this));
		GEvent.addListener(mapControler.map.getInfoWindow(),'restoreclick',this.closeWindow.bind(this));
	},
	getLists: function() {
		new Ajax(
			FavListControler.URL_LISTS,
			{
				method: 'get',
				headers: ['Accept','text/json','If-Modified-Since', 'Sat, 1 Jan 2000 00:00:00 GMT'],
				async: true,
				onSuccess: this.handleListResult.bind(this),
				onError: ( function () {
					this.lists = null;
				}).bind(this)
			}
		).request();
	},
	isLoggedIn: function() {
		return (this.categories && (this.categories.length > 0));
	},
	handleListResult: function (transport) {
		try {
			var result = Json.evaluate('(' + transport.replace(/[^[\x0A\0xD\x20-\xFF]/g,"") + ')');
			this.lists = new Array();
			for(var i=0; i < result.length; i++) {
				this.lists.push(new FavList(result[i].uuid,result[i].name,result[i].category,result[i].description));
			}
		} catch (e) {
			this.lists = null;
		}
	},
	handleCategoryResult: function (transport) {
		try {
			var result = Json.evaluate('(' + transport.replace(/[^[\x0A\0xD\x20-\xFF]/g,"") + ')');
			this.categories = new Array();
			for(var i=0; i < result.length; i++) {
				this.categories.push(new FavListCategory(result[i].categoryInternalName,result[i].name));
			}
		} catch (e) {
			this.categories = null;
		}
	},
	addToList: function(sadbid, listid, listname, listcategory) {
		if (null != sadbid) {
			var createURL = FavListControler.URL_STORE + '&locationId=' + sadbid;
			if (null != listid) {
				createURL += '&listId=' + listid; 
				createURL += '&createList=false'; 
			} else {
				createURL += '&createList=true'; 
				if (null != listname) createURL += '&listName=' + listname; 
				else createURL += '&listName=' + FavList.DEFAULT_NAME;
				if (null != listcategory) createURL += '&listCategory=' + listcategory; 
				else createURL += '&listCategory=' + FavList.CATEGORY;
			}
			new Ajax(
				createURL,
				{
					method: 'get',
					headers: ['Accept','text/json','If-Modified-Since', 'Sat, 1 Jan 2000 00:00:00 GMT'],
					async: true,
					onSuccess: this.handleListResult.bind(this),
					onError: ( function () {
						this.lists = null;
					}).bind(this)
				}
			).request();
			var html = '<div style="font-style: italic; color: #3D3D3D">Eintrag wurde zur Lieblingsliste hinzugef&uuml;gt</div>';
			this.cContainer.setHTML(html);
			this.closeWindow();
			this.getLists();	  		
		}
	},
	displayWindow: function(container) {
		if (container && this.isLoggedIn()) {
	  		if (!this.favListWindow) {
				this.favListWindow = new Element("div");
				this.favListWindow.setAttribute('id', 'favLists');
				this.favListWindow.setAttribute('class', 'favlistDiv');
				this.favListWindow.style.visibility = "hidden";
				this.favListWindow.style.display = "none";
				this.favListWindow.injectInside(document.body);
			}	

			var coords = container.getCoordinates();
			this.favListWindow.setStyle('position','absolute');
			this.favListWindow.setStyle('left',coords.left);
			this.favListWindow.setStyle('width',coords.width);
			this.favListWindow.setStyle('padding','0.3em');
			this.favListWindow.setStyle('background-color','#E7EEF3');
			this.favListWindow.setStyle('border-style','solid');
			this.favListWindow.setStyle('border-color','#105D8D');
			this.favListWindow.setStyle('border-width','1px');
			this.favListWindow.setStyle('top',coords.top + coords.height -1);
			this.favListWindow.style.visibility = "visible";
			this.favListWindow.style.width = coords.width;
			this.favListWindow.style.display = "block";
			this.favListWindow.style.zIndex = 10000;
			
			var html='<img src="http://maps.google.de/intl/de_de/mapfiles/iw_close.gif" alt="Schliessen" title="Schlie&szlig;en" style="float: right" onclick="favControler.closeWindow()"/>'
			for(var i=0;i<this.lists.length;i++) {
				if (i==0) html+= '<strong>Eintrag einer bestehenden Lieblingsliste hinzuf&uuml;gen:</strong><br/><ul style="list-style-type: none">';
				html += '<li><a href="javascript:void(0)" onclick="favControler.addToList(\'' + mapControler.hitInInfoWindow.id + '\',\'' + this.lists[i].uuid + '\',\'' + this.lists[i].name + '\',\'' + this.lists[i].listCategory + '\')" title="' + this.lists[i].description + '">' + this.lists[i].name + '</a></li>';
				if (i==this.lists.length-1) html+= '</ul>';
			}
			html += '<strong>Neue Lieblingsliste anlegen:</strong><br/>';
			html += '<div style="float: left; width: 80px; margin-top: .3em; padding: 0;">';
			html += '<label for="favListName">Listenname</label>';
			html += '</div>';
			html += '<div style="float: left; margin-top: .3em; margin-left: 0px; padding: 0;">';
			html += '<input id="favListName" type="text" value="' + FavList.DEFAULT_NAME + '" style="width: 14em" title="Name der neuen Lieblingsliste eingeben"/>';
			html += '</div>';
			html += '<div style="clear: both"></div>';
			html += '<div style="float: left;width: 80px; margin-top: .3em; padding: 0;">';
			html += '<label for="favListCategory">Kategorie</label>';
			html += '</div>';
			html += '<div style="float: left; margin-top: .3em; margin-left: 0px; padding: 0;">';
			html += '<select id="favListCategory" style="width: 14.5em" title="Kategorie der neuen Lieblingsliste ausw&auml;hlen">';
			for(var i=0;this.categories && i<this.categories.length;i++) {
				html += '<option value="' + this.categories[i].internalName + '">' + this.categories[i].name + '</option>';
			}
			html += '</select>';
			html += '</div>';
			html += '<div style="clear: both"></div>';
			html += '<div style="float: left; margin-top: .3em; margin-left: 0px; padding-left: 80px; margin-bottom: .3em;">'
			html += '<input style="margin-right: .3em;" type="button" value="Hinzuf&uuml;gen" title="Eintrag der neuen Lieblingsliste hinzuf&uuml;gen" onclick="favControler.addToList(\'' + mapControler.hitInInfoWindow.id + '\',null,$(\'favListName\').value,$(\'favListCategory\').value,\'' + FavList.DEFAULT_DESCRIPTION + '\')"/>';
			html += '<input style="margin-right: .3em;" type="button" value="Abbrechen" title="Abbrechen" onclick="favControler.closeWindow()"/>';
			html += '</div>';
			html += '<div style="clear: both"></div>';
			this.favListWindow.setHTML(html);
			this.cContainer = container;
		}
	},
	closeWindow: function() {
  		if (this.favListWindow) {
			this.favListWindow.style.visibility = "hidden";
			this.favListWindow.style.display = "none";
		}	  			
	}
});
FavListControler.URL_LISTS = CMSWebAppDir + '/servlet/export/sse/favoriteLists?view=asJson';
FavListControler.URL_CATEGORIES = CMSWebAppDir + '/servlet/export/sse/favoriteListCategories?view=asJson';
FavListControler.URL_STORE = CMSWebAppDir + '/servlet/feedback/favoriteList?action=createEntry&sadbEntry=true';


var HHDELocalSearch = new Class({
	Implements: [LocalSearch],
	registerEvents: function() {
		this.listeners.push(GEvent.addListener(this.queryIO.mapControler.map,'moveend', function() {
			searcher.setLink('stadtplan_bookmark');
			try {simulatePI();} catch (e) {}
			try {simulateAI();} catch (e) {}
		}));
		
		this.listeners.push(GEvent.addListener(this.queryIO.mapControler.map,'maptypechanged', function() {
			searcher.setLink('stadtplan_bookmark');
			try {simulatePI();} catch (e) {}
			try {simulateAI();} catch (e) {}
		}));
		
		this.listeners.push(GEvent.addListener(this.queryIO.mapControler.app,'poilist_change', function() {
			searcher.setLink('stadtplan_bookmark');
			try {simulatePI();} catch (e) {}
			try {simulateAI();} catch (e) {}
		}));
		
		this.listeners.push(GEvent.addListener(this.queryIO.mapControler.app,'useraction', function() {
			try {simulatePI();} catch (e) {}
			try {simulateAI();} catch (e) {}
		}));

		this.listeners.push(GEvent.addListener(this,'searchsubmit',function() {
			searcher.setLink('stadtplan_bookmark');
			$('stadtplan_input').addClass('dsp_none');
			$('stadtplan_result').removeClass('dsp_none');
		}));
	}
});
	
function hoverURLLink(){
	try {
		var a = $('kartenfunktionen').getElement('.fn_link');
		var div = $('kartenfunktionen').getElement('div.dsp_none');
	} 
	catch (e) {
		return false;
	}
	if (!(a || div) || !((window.ie) && (!window.ie7)) && !window.webkit) {
		return false;
	}
	try {
		if ($type(a) == "element" && $type(div) == "element") {
			a.addEvent('click', function(){
				div.setStyle('display', 'block');
			}).addEvent('mouseenter', function(){
				div.setStyle('display', 'block');
			}).addEvent('mouseleave', function(){
				div.setStyle('display', 'none');
			});
			div.addEvent('mouseenter', function(){
				div.setStyle('display', 'block');
			}).addEvent('mouseleave', function(){
				div.setStyle('display', 'none');
			});
		}
	} 
	catch (e) {
		return false;
	}
}

function initLayout(){
	
	hoverURLLink();
	
	$('main_poi_list').getElements('li').each(function (el) {
		el.addEvent('click', function () { 
			el.toggleClass('current');
			mapControler.poiLayers.setVisible(el.id,el.hasClass('current'));
		})
	});
	new Ajax(
			WebAppDir + '/proxy.jsp?call=5&imgpfx=' + POI_PATH,
			{
				method: 'get',
				headers: ['Accept','text/html','If-Modified-Since', 'Sat, 1 Jan 2000 00:00:00 GMT'],
				async: true,
				onSuccess: (function (transport) {
					$('stadtplan_expandsuche').setHTML(transport);
					
					var poiList = new StadtPlan( {
						expander: $$('.stadtplan_suchauswahl .stadtplan_expander a')[0],
						expander_body: $$('.stadtplan_suchauswahl .stadtplan_expandsuche'),
						
						container: $$('.stadtplan_suchauswahl'),
						flyout: $('flyout')
					} );
					
					$('flyout').getElements('ul input').each( function(el){
						el.addEvent('click', function(input) {
							mapControler.poiLayers.setVisible(el.id,el.getProperty('checked'));
						})
						$('flyout').getElements('ul label.' + el.id).each( function(label){
							label.addEvent('click', function() {
								mapControler.poiLayers.setVisible(el.id,!el.getProperty('checked'));
							})
						})
					})
					$$('.stadtplan_main_list')[0].getElements('li').each( function(li){
						$('flyout').getElements('ul.' + li.id + ' input').each( function(input) {
							li.addEvent('click', function() {
								input.fireEvent('click');
							})
						})
					})
					
/*						GEvent.addListener(mapControler.app,'poilistaction', function(listid) {
							$('flyout').getElements('#' + listid).each(function (poilistCheckBox) {
								poilistCheckBox.setProperty('checked',!poilistCheckBox.getProperty('checked'));
								$('flyout').getElements('.'+poilistCheckBox.className + " ." + listid).each (
										function(li) {
											li.toggleClass('active');
										}
								);
								poiList.check(
										$$('.stadtplan_main_list')[0].getElements('li.'+poilistCheckBox.className)[0],
										$('flyout').getElements('ul.'+poilistCheckBox.className)[0]
									);
							})
							searcher.setLink('stadtplan_bookmark');
						});*/

				}).bind(this)
			}
		).request();
};


function initMap(defaultOptions) {
	//create the main map control
	 if (!GBrowserIsCompatible()) return;
	 	
	// get GET-Parameters
	var args = getQueryArgs(document.location);
	 	
	var optimize = true;
	
	var mapOptions = defaultOptions;
	if (!mapOptions) mapOptions = new Object();

 	// set map center
	if (args.c && (args.c.length > 0)) {
		center=args.c.split(',');
		if (center.length==2) {
			mapOptions.center=new GLatLng(center[1], center[0]);
			optimize=false;
		}
	}
	// set map zoomlevel
		if (args.z && (args.z.length > 0)) {
			try { mapOptions.zoom=parseInt(args.z);} catch(e) {}
		}
 
		var mapApp = new GMapApp('map',new GSize(484,414), mapOptions);
	mapApp.map.enableScrollWheelZoom();

	//add some default controls supported by the API
	mapApp.map.addControl(new GSmallMapControl());
	mapApp.map.addControl(new GMapTypeControl());
	mapApp.map.addControl(new GScaleControl());
	mapApp.map.addControl(new GOverviewMapControl());


	// initialize mapcontroler and register relevant events
	mapControler = new LocalSearchMapControler(mapApp);
	// initialize favcontroler and register relevant events
	favControler = new FavListControler();		
	// initialize search controler
	var searchIO = new LocalSearchInOutControler(
		$('stadtplan_location'),
		$('stadtplan_adress'),
		$('stadtplan_result'),
		mapControler
	);
	// initialize searcher
	searcher = new HHDELocalSearch(searchIO);
	searcher.optimizeView=optimize
	searcher.setLink('stadtplan_bookmark');

	var autoSearch = false;
	if (args.wo && (args.wo.length > 0)) {
		searcher.queryIO.addressInput.value = decodeURIComponent(args.wo);
	}
	if (args.was && (args.was.length > 0)) {
		searcher.queryIO.queryInput.value = decodeURIComponent(args.was);
	}

	// if map is invoked with search parameters, execute search
	if (searcher.queryIO.addressInput.value!=LocalSearchInOutControler.DEFAULT_WO) autoSearch = true;
	if (searcher.queryIO.queryInput.value!=LocalSearchInOutControler.DEFAULT_WAS) {
		autoSearch = true;
		if ($('branche_link')) $('branche_link').fireEvent('click');
	}

	if (args.r) {
		searcher.setRoute(args.r, args.d, args.rc);
		if (!args.ids) args.ids = [];
		args.ids.push(args.r);
	}
	
	if (autoSearch) {
		searcher.search(searcher.queryIO.queryInput.value, searcher.queryIO.addressInput.value,Math.max(0,args.p-1),args.cat,optimize);
	} else if (args.ids) {
		searcher.list(args.ids);
	} else {
		if (mapApp.defaultLayer && !(args.pl && (args.pl.length > 0))) {
			mapControler.poiLayers.showLayer(mapApp.defaultLayer);
			var listener1 = GEvent.addListener(searcher,'searchsubmit', function() {
				mapControler.poiLayers.removeLayer(mapApp.defaultLayer);
				GEvent.removeListener(listener1);			
				});
			var listener2 = GEvent.addListener(mapApp,'poilist_change', function() {
				mapControler.poiLayers.removeLayer(mapApp.defaultLayer);
				GEvent.removeListener(listener2);			
				});
		}
		searcher.registerEvents();
	}
	// display pois
	if (args.pl && (args.pl.length > 0)) {
		var plist = args.pl.split(',');
		for(var i=0; i < plist.length; i++) mapControler.poiLayers.showLayer(plist[i]);
	}

	// focus address input
	searcher.queryIO.addressInput.focus();
}		


var adlWallPaperLeft = '819';

function init() {
	initMap({ center: new GLatLng('53.56106','9.98923'), zoom: 13, defaultLayer: '10282905' });
	initLayout();
}

function newSearchRequest() {
	$('stadtplan_input').removeClass('dsp_none');
	$('stadtplan_result').addClass('dsp_none');
	$('stadtplan_location').select();
	$('stadtplan_location').focus();
	searcher.queryIO.clearResult();
	
}

var searcher = null;
var mapControler = null;
var favControler = null;

window.addEvent('domready',init);
window.addEvent('unload',GUnload);
// eof
