/**
 * Stellt die Druckfunktion zu verfügung
 */
function IWPrintMap(map) {

    var _map = map;
    var _markerCoordArray = null;
    /**
     * Force to keep the ratio of the map
     */
    this.keepRatio = false;

    var nPaperWidthA4 = 0;
    var nPrintableWidth = 0;
    var nPrintableHeight = 0;
    var ratio = 0;

    /**
     * showRoute: if false, a route is not printed, even if there is one
     * keepScale: if true, the scale from the map is kept. Beware, you do not get what you see on the map
     */
    this.Print = function(showRoute, keepScale, adressTabelle,routingBounds,routeSegments)
    {
        if (navigator.appName == "Microsoft Internet Explorer")
        {
            nPaperWidthA4 = 610;
        }
        else
        {
            nPaperWidthA4 = 1000;
        }
        
        if (this.keepRatio) {
            ratio = 1.0;
        } else {
            ratio = _map.getOptions().getSize().getWidth() / _map.getOptions().getSize().getHeight();
        }
        nPrintableWidth = nPaperWidthA4;
        nPrintableHeight = parseInt(nPrintableWidth / ratio);
        var printWinWidth = nPrintableWidth + 30;
        var sStyle = "left=100,top=50,width=" + printWinWidth + ",height=750,resizable=yes,status=yes,scrollbars=yes,menubar=yes"; // menubar=yes
        var PrintWindow = window.open(appPath+"PrintMap.jsp", "iwPrintWindow", sStyle);

        var oThis = this;
        window.setTimeout(function() {
            oThis.PrintInit(PrintWindow, nPrintableWidth, nPrintableHeight, showRoute, ratio, keepScale, adressTabelle,routingBounds,routeSegments);
        }, 500);

        return false;
    };

    this.PrintInit = function(PrintWindow, PrintableWidth, PrintableHeight, showRoute, ratio, keepScale, adressTabelle,routingBounds,routeSegments)
    {
        var nPrintableWidth = PrintableWidth;
        var nPrintableHeight = PrintableHeight;

        var divMapArea = PrintWindow.document.getElementById('divMapArea');
        var divContentArea = PrintWindow.document.getElementById('divContentArea');
        var divCopyrightArea = PrintWindow.document.getElementById('divCopyrightArea');

        if (divMapArea && divContentArea)
        {        	
            //
            // Generate the map
            //
            var includeOverlayLayerFromMap = false;
            var sURL = '';
            if (showRoute ) {

                var mapWidth = Math.abs(routingBounds.getNorthWest().getX() - routingBounds.getSouthEast().getX());
                var mapHeight = Math.abs(routingBounds.getNorthWest().getY() - routingBounds.getSouthEast().getY());

                var scaleFactor = 1.1;
                mapWidth = (mapWidth < 1000) ? 1000 : mapWidth * scaleFactor;
                mapHeight = (mapHeight < 1000) ? 1000 : mapHeight * scaleFactor;
                includeOverlayLayerFromMap = false;
            } else if (keepScale) {
                //
                // no route, force to keep the scale
                //
                var forceScale = _map.getOptions().getSize().getWidth() / nPrintableWidth;
                var forceMapWidthInMeter = parseInt(_map.getMapWidthInMeter() / forceScale);
                var forceMapHeigthInMeter = parseInt(_map.getMapWidthInMeter() / ratio / forceScale);
                includeOverlayLayerFromMap = true;
            } else {
                includeOverlayLayerFromMap = true;
            }
		// Die Größe des Bild divs hier setzten (Höhe konnte sich noch ändern)
//            divMapArea.style.width = nPrintableWidth + 'px';
//            divMapArea.style.height = nPrintableHeight + 'px';

		// Karte laden
            if (showRoute)
            {	
               PrintWindow.bindRouteLayer(routeSegments.getShape());
            }
            
            var center = _map.getCenter();
            PrintWindow.init(center.getX(), center.getY(), _map.getZoom(), mapMode, nPrintableWidth, nPrintableHeight, mapApiName, mapApiHost);
            
            if (includeOverlayLayerFromMap) {
                // Overlay Layer richtig positionieren
                // Overlay layer holen und schon einbinden, sonst mag das ie nicht
                var div = _map.getOverlayContainer().cloneNode(true);
                var dx = Math.abs(_map.getOptions().getSize().getWidth() - nPrintableWidth) / 2;
                var dy = Math.abs(_map.getOptions().getSize().getHeight() - nPrintableHeight) / 2;
                var offsety = parseInt(div.style.top);
                var offsetx = parseInt(div.style.left);

                var offsetFullY = offsety + dy;
                var offsetFullX = offsetx + dx;

              /*alert("offsetx "+offsetx+" offsety "+offsety+" dx "+dx);*/
               if(_map.getOptions().getSize().getWidth()<= nPrintableWidth) {
                   div.style.left = +offsetx + dx + 'px';
               }
               else {
                   div.style.left = +offsetx - dx + 'px';
               }
                if(_map.getOptions().getSize().getHeight() <= nPrintableHeight){
                     div.style.top = offsety + dy + 'px';
                }
                else   {
                    div.style.top = offsety - dy + 'px';
                }

                var bounds = map.getBounds();
                var contains = false;
                var removedIds = new Array();
                var table = null;

                if (_markerCoordArray && _markerCoordArray.length > 0) {
                    if (adressTabelle) {
                        var sAdressTable = "";
                        sAdressTable += '<table id=' + adressTabelle.id
                                + '>'
                                + adressTabelle.innerHTML
                                + '</table>';

                        divContentArea.innerHTML = sAdressTable;
                        var tables = iw.tag('table', divContentArea);
                        if (tables && tables.length > 0) {
                            table = tables[0];
                            
                        }
                    }

                var bottomRightX = _map.getOptions().getSize().getWidth()/2 + nPrintableWidth/2;
                var bottomRightY = _map.getOptions().getSize().getHeight()/2 + nPrintableHeight/2;
                var bottomRight = new IWPoint(bottomRightX, bottomRightY); 
				var bottomRightCord = map.getCurrentMapType().getProjection().pixelToMeter(bottomRight);
				
                 // ueberprüfen, ob overlay liegt auf dem map
                for(var i =_markerCoordArray.length-1; i >=0; i--)
                {
                	if (_markerCoordArray[i] && _markerCoordArray[i] !='undefined')
                	{
                		var coord = _markerCoordArray[i];
                		var logoUrl = map.getOverlayManager().getLayer(i).getOverlays()[0].getDefaultIcon().getUrl();

                		//TODO: mapMode is better, getLayer(0) is not null in birdview?
                		if (_map.getCurrentMapType().getName() != "birdsview")
                		{
                			PrintWindow.addMarker(coord.getX(), coord.getY(), logoUrl);
                		}
                	}
                }

               }
            }

            var divSpecialContent = document.getElementById('divSpecialContent');

            if (showRoute)
            {	
               var routeTable = document.getElementById("routePrintErgebnis");
               var route =  routeSegments;

               PrintWindow.bindRouteLayer(route.getShape());
               
               var formatter = new IWRouteFormatter(route);
           		formatter.setLanguage('de');
           	
               var tableRows = routeTable.rows;
               while(tableRows && tableRows.length > 1)
                    routeTable.deleteRow(tableRows.length-1);
               
           		var totalTime = 0;
           		var totalDistance = 0;

           		if(route && route.getSegments())
                {            	
                	var rows = route.getSegments();

                    for(var i = 0; i < rows; i++)
                    {
                    	var segment = route.getEntry(i); 

                        var tr = routeTable.insertRow(i + 1);
                        tr.style.color="#333399";
                        tr.style.borderBottom="2px solid #fff" ;

                        // number
                        var td = iw.create("td");
                        td.style.color="#024f99";
                        td.style.paddingLeft="10px";
                        td.style.width="35px";
                        td.appendChild(document.createTextNode((i+1)+"."));
                        iw.append(tr,td);

                        // direction image
                        var td = iw.create("td");
                        td.style.color="#024f99";
                        td.style.width="60px";
                        var img = iw.create("img");
                        img.src = appPath+"images/route/"+getGetDirectionImage(segment.getDirection());
                        td.appendChild(img);
                        iw.append(tr,td);

                        // time
                        td = iw.create("td");
                        td.style.color="#024f99";
                        td.style.paddingRight ="40px";
                        td.style.paddingLeft="5px";
                        td.appendChild(document.createTextNode( formatRoutingTime(segment.getEntryTime())) );
                        
                        iw.append(tr,td);

                        // description
                        td = iw.create("td");
                        td.style.color="#024f99";
                        td.style.width="570px";
                        td.style.paddingRight="10px";
                        td.innerHTML = formatter.createDescriptionAsHTML(i);
                        iw.append(tr,td);

                        // section length
                        td = iw.create("td");
                        td.style.color="#024f99";
                        td.style.paddingLeft="10px";
                        td.appendChild(document.createTextNode( formatDistence( segment.getEntryDistance() )) );
                        iw.append(tr,td);

                        // total time
                        td = iw.create("td");
                        td.style.color="#024f99";
                        td.style.paddingLeft="10px";
                        td.appendChild(document.createTextNode( formatRoutingTime(segment.getTotalTime())) );
                        iw.append(tr,td);
                                                
                        totalTime += segment.getEntryTime();
                		totalDistance += segment.getEntryDistance();
                    }


                }
               
                 var sRouteTable = "";
                sRouteTable += '<table id=' + routeTable.id
                        + ' style="'
                        + ' border: ' + routeTable.style.border + ';'
                        + '"'
                        + '>'
                        + routeTable.innerHTML
                        + '</table>';
            	
                var infoDiv = 
                	'<div style="border:1px solid #CCCCCC;padding:10px;">' +
                		'Gesamtfahrzeit: <strong>' +formatRoutingTimeInfo(totalTime)+ '</strong> Gesamtkilometer: <strong>' +formatDistence(totalDistance)+ '</strong>' +
                	'</div><br>';
                
                divContentArea.innerHTML = infoDiv + sRouteTable ;
            }
            else
            {
                if (divSpecialContent)
                {
                    divContentArea.innerHTML = divSpecialContent.innerHTML;
                }
            }

        }
        else
        {
            var oThis = this;
            window.setTimeout(function() {
                //oThis.PrintInit(PrintWindow, nPrintableWidth, nPrintableHeight, showRoute);
                oThis.PrintInit(PrintWindow, nPrintableWidth, nPrintableHeight, showRoute, ratio, keepScale, adressTabelle,routingBounds,routeSegments);
            }, 500);
        }
    };
    this.setMarkerCoordArray = function(markerCoordArray) {
        _markerCoordArray = markerCoordArray;
    };
}
var iwPrintMap = null;
var tooltipTimeout = null;
var applicationCopyright = '';

var coordCenter = new IWCoordinate(560513, 80731);
var sliderControl = null;
var windowResized = false;
var marker = null;
var tooltip = null;
var navigationControl = null;
var mapMode = 0;

function countNavigationEvent() {

	if (map.getCurrentMapType().getName() == 'hybrid') {
		wipeCounter.logAction('KShybrid');
	} else if (map.getCurrentMapType().getName() == 'roadmap') {
		wipeCounter.logAction('KSkarte');
	} else if (map.getCurrentMapType().getName() == 'birdsview' || map.getCurrentMapType().getName() == 'birdsviewarea') {
		wipeCounter.logAction('KSbird');
	}
}

function onAftermaptypechangedEvent(mapTypeChangeEvent) {

	if (currentMapType == 3)
	{
		copyright = map.getOptions().getApplicationCopyright();
		if (tmcLayer.isVisible()) {
			updateCopyrightWhithTMC(false);
		}
		scalarControl.getContainer().style.visibility = "hidden";
		hideOverlays();
		updateSliderView("birdsview");
	} 
	else 
	{
		copyright = map.getOptions().getApplicationCopyright();
		scalarControl.getContainer().style.visibility = "visible";
		if (tmcLayer.isVisible()) {
			updateCopyrightWhithTMC(true);
		}
		map.getLayoutManager().getLayer(0).removeControl(sliderControl);
		sliderControl = new IWSliderControl(map);
		map.getLayoutManager().getLayer(0).addControl(sliderControl, IWAlignment.LEFT, IWAlignment.TOP, 0, 0);
		showOverlays();
		updateSliderView(mapTypeChangeEvent.newMapType.getName());
	}
}

function getPoiData(e) 
{
	if (e.requestedEvent == 'onclick') {
		var content = document.createElement('div');

		content.style.position = 'relative';
		content.style.height = '100px';
		content.style.overflow = 'auto';

		// fetch all records
		for (layer in e.json)
		{
			var records = e.json[layer].recordset.record;
			for ( var i = 0; i < records.length; i++) {
				if (records[i].NAME) {
					// Formats the POIs content
					content.appendChild(formatContent(records[i]));
				} else if (records[i].ID) {
					// Format content for TMCPro Traffic Info
					content.appendChild(formatTMCPro(records[i]));
				}
			}
		}

		// we create the infoballoon and put it on the map
		if (parseInt(content.style.height) > 100) {
			content.style.width = parseInt(content.style.width) + 50 + px;
		}

		// we create the infoballoon and put it on the map
		if (e.records > 0) {
			map.openInfoBalloon(e.mouseCoordinate, content);
		}
	} 
	else if (e.requestedEvent == 'onmousestop') 
	{
		var content = "";
		for (layer in e.json) {
			content = e.json[layer].recordset.record[0].NAME;
			break;
		}

		// close old tooltip (if present)
		closeTooltip();

		// create a new tooltip with the 'tooltip text' from the first record.
		map.openTooltip(e.mouseCoordinate, content);

		// close the tooltip after 5 seconds automatically
		tooltipTimeout = window.setTimeout( function() {
			closeTooltip();
		}, 5000);
	}
}

function setMapTypeNormal()
{
	wipeCounter.logAction('KSkarte');
	wipeLogZoom = false;
	
	var newZoomLevel = checkZoomLevel(mapMode);
	mapMode = 0;
	MaptypeUtils.updateTilesAliases(map, mapMode, newZoomLevel, true);
}

function setMapHybrid() {
	wipeCounter.logAction('KShybrid');

	mapModus = 1;
	currentMapType = 1;
	var newZoomLevel = checkZoomLevel(mapMode);
	mapMode = 2;
	MaptypeUtils.updateTilesAliases(map, mapMode, newZoomLevel, true);
}

var savedZoomLevel = 0;
function checkZoomLevel(oldMapMode)
{
	var newZoomLevel = map.getZoom();
	if (mapMode == 3) //was in birdsview mode
	{
		newZoomLevel = savedZoomLevel;
	}	
	return newZoomLevel;
}

function setMapBirdsView() {
	if (!birdsviewActive)
	{
		return false;
	}
	
	zoomLevelMap = map.getZoom();
	
	wipeCounter.logAction('KSbird');
	wipeLogZoom = false;
	mapModus = 3;
	mapMode = 3;
	
	scalarControl.setVisible(false);
	savedZoomLevel = map.getZoom();
	MaptypeUtils.updateTilesAliases(map, mapMode, map.getZoom(), true);
}

function initSavedZoomLevel()
{
	zoomLevelMap = map.getZoom();
	zoomLevelHybrid = map.getZoom();
}

function showOverlays() {
	if (markerModus != 0) 
	{
		setAllMarkerVisible();
	} 
	else 
	{
		setOneMarkerVisible(selectedMarker);
	}
}

function hideOverlays() {
	setAllMarkerHidden();
}
function mouseZoom() {
	map.getOptions().setLeftMouseAction(IWMapOptions.CONTROL_ZOOM);
}

function mouseMove() {
	map.getOptions().setLeftMouseAction(IWMapOptions.CONTROL_MOVE);
}

//FOR POIs
function formatContent(record) {
	var div = document.createElement('div');
	div.style.position = 'relative';
	div.style.textAlign = 'left';

	var name = record.NAME;
	var boldName = createTextParagraph(name.replace(/\u0020/g, '&nbsp;'));
	boldName.style.fontWeight = 'bold';
	div.appendChild(boldName);
	div.appendChild(createTextParagraph(record.STRASSE.replace(/\u0020/g, '&nbsp;') + '&nbsp;' + record.HNR.replace(/\u0020/g, '&nbsp;')));
	div.appendChild(createTextParagraph(record.PLZ.replace(/\u0020/g, '&nbsp;') + '&nbsp;' + record.ORT.replace(/\u0020/g, '&nbsp;')));
	if (record.Www) {
		var internet = createTextParagraph('Internet:&nbsp;<a href="' + record.Www + '" target="_blank">' + record.Www + '</a>');
		div.appendChild(internet);
	}
	div.appendChild(createTextParagraph('<br>'));
	return div;
}

function makeLayer(layerTitle, layerName) {
	var layer = new IWLayer(map, layerTitle, layerName);
	var requestLayer = new IWRequestLayer(layer);

	requestLayer.registerEvent('onmousestop');
	requestLayer.registerEvent('onclick');

	map.getLayerInfoManager().addRequestLayer(requestLayer);
	var removeListener = IWEventManager.addListener(layer, 'onremove', function(e) {
		map.getLayerInfoManager().removeRequestLayer(requestLayer);
		IWEventManager.removeListener(removeListener);
	});

	return layer;
}
/**
 * Creates a new slider control.
 *
 * @class A control element which allows the user to zoom in and out the map
 *
 * @constructor
 * @extends IWControl
 *
 * @param {IWMap} map the map
 *
 * @author KUN
 */
function MarSliderControl(map)
{
	IWControl.call(this, map, 'MarSliderControl');

	//********************************************************************
	//* Private attributes
	//********************************************************************

	// TODO: Slider springt noch beim Zoomen
	// TODO: Reihenfolge beim Klick auf den Zoom Panel falsch. Erst Button, dann Zoomen
	// TODO: Mausrad und Slider synchronisieren. Button mit Mausrad verschieben.

	var _map				= map;
	var _self				= this;
	var _tilesizeArray 		= iwconst.A_TILESIZE_METER;
  	var _lowValue 			= _map.getCurrentMapType().getMaxLevel();
  	var _highValue 			= _map.getCurrentMapType().getMinLevel();
	var _offsetX 			= 23;
	var _offsetY 			= 21;
	var _maxSlide 			= 161 - _offsetY;
	var _currentPos 		= _map.getZoom();
	var _mouseAdapter 		= new IWMouseAdapter();
	var _container 			= this.getContainer();

	// GUI elements
	var _divSliderButton	= iw.create('div');
	var _areaPlus 			= iw.create('area');
	var _areaMinus 			= iw.create('area');
    var imgSlider           = iw.create('img');
	//********************************************************************
	//* Public methods
	//********************************************************************

	/**
	 * Returns the current value of the slider
	 *
	 * @return {int} the current value of the slider
	 */
	this.getValue = function(round)
	{
		// TODO: Hier nicht runden...
		if (typeof(round) == "undefined")
		{
			round = true;
		}
	  var value =  _lowValue + (_highValue-_lowValue) * (parseInt(_divSliderButton.style.top)-_offsetY) / _maxSlide;
	  if (round)
	  {
	  	return Math.round(value);
	  }
	  else
	  {
	  	return value;
	  }
	};

	/**
	 * Sets the position of the slider
	 *
	 * @param {int} value The value the slider shall represent
	 * @param {boolean} ignore If ignore is true, the map will not be zoomed (optional, default is false)
	 * @return {void}
	 */
	this.setValue = function (value, ignore)
	{
		if (typeof(ignore) == "undefined")
			ignore = false;

	  if (typeof(value) == "string")
			value = parseInt(value);

	  // set within min/max bounds
	  var rangeValue = Math.min(Math.max(value,_lowValue),_highValue) - _lowValue;

	  // move button to calculated position
	  _divSliderButton.style.top = _maxSlide * rangeValue / (_highValue-_lowValue) + _offsetY + 'px';

	  _currentPos = value;

	  if (!ignore)
	  {
	  	_map.setZoom(value);
	  }
	};

	/**
	 * Sets the language ISO code which should be used for displaying the text.
	 *
	 * @param {String} language the iso-code of the language.
	 * @return {void}
	 */
	this.setLanguage = function(language)
	{
		var lng = language.toLowerCase();

		if (lng.toLowerCase() == 'de')
		{
			_areaPlus.title		= 'Vergr\u00F6\u00DFern';
			_areaMinus.title 	= 'Verkleinern';
		}
		else
		{
			_areaPlus.title		= 'zoom in';
			_areaMinus.title	= 'zoom out';
		}
	};

	/**
	 * @return {void}
	 */
	this.afterAppend = function()
	{
		buildGUI();
		this.setValue(_map.getZoom(), true);
	};

	/**
	 * Returns a string representation of this slider control.
	 *
	 * @return {String}
	 */
	this.toString = function()
	{
		return '[IWSliderControl]';
	};

	//********************************************************************
	//* Private methods
	//********************************************************************

	/**
	 * Returns for a given slider value the Y-Position in pixel
	 *
	 * @private
	 * @param {int} step A arbitrary slider value
	 * @return{int} The corresponding Y-coordinate
	 */
	function _fromSteptoPixel(step)
	{
		return parseInt(_maxSlide / _highValue) * step + _offsetY;
	}

	/**
	 * Creates the GUI for the slider control.
	 *
	 * @private
	 * @return void
	 */
	function buildGUI()
	{

		// create image map for slider background
		// Workaround for an IE bug: IE does not recognize changes of the name property of dynamically created
		// elements, so the slider has to be created with the special MS syntax of createElement().

		var mapSlider = null;
		try
		{
			mapSlider = iw.create('<map name="mapSlider">');
		}
		catch (e)
		{
			mapSlider = iw.create('map');
			mapSlider.name = 'mapSlider';
		}
		iw.append(_container, mapSlider);

		// create the zoom in area
		iw.append(mapSlider, _areaPlus);

		_areaPlus.shape		= 'rect';
		_areaPlus.coords	= '8,1,45,20';
		_areaPlus.style.cursor = 'pointer';

		IWEventManager.addDomListener(_areaPlus, 'onmousedown',
			function(event)
			{
				_currentPos = _map.getZoom();
				if (!map.isZooming() && (_map.getCurrentMapType().getMaxLevel() < _currentPos))
				{
					_currentPos--;
					this.setValue(_currentPos, true);
				  if (!_map.zoomIn())
				  {
						_currentPos++;
						this.setValue(_currentPos, true);
				  }
				}
			}.iwclosure(_self)
		);

		// create the zoomout area
		iw.append(mapSlider, _areaMinus);

		_areaMinus.shape	= 'rect';
		_areaMinus.coords	= '8,193,45,218';
		_areaMinus.style.cursor = 'pointer';

		IWEventManager.addDomListener(_areaMinus, 'onmousedown',
			function(event)
			{
				_currentPos = _map.getZoom();
				if (!map.isZooming() && (_map.getCurrentMapType().getMinLevel() > _currentPos))
				{
					_currentPos++;
					this.setValue(_currentPos, true);

					if (!_map.zoomOut())
					{
						_currentPos--;
						this.setValue(_currentPos, true);
					}
				}
			}.iwclosure(_self)
		);

		// create the zoom area panel

		var areaPanel = iw.create('area'); iw.append(mapSlider, areaPanel);

		areaPanel.shape		= 'rect';
		areaPanel.coords	= '20,21,35,218';

		IWEventManager.addDomListener(areaPanel, 'onmousedown',
			function(event)
			{
				if (map.isZooming())
					return;

				if (!event)
					event = window.event;

				var _mouseAdapter = new IWMouseAdapter();
				var mouseEvent = _mouseAdapter.toMouseEvent(event, _container);
				var y = mouseEvent.position.getY() - 20;


				if (y >= 0 && y <= 170)
				{
					var idx = Math.min(Math.round((y / 161) * _highValue), _highValue);
					_map.setZoom(idx);
				}
			}.iwclosure(_self)
		);

		// create the slider background

		var imgSlider = iw.create('img');
		iw.append(_container, imgSlider);

		imgSlider.useMap	= '#mapSlider';
		imgSlider.onload	= function () { correctPNG(this); }.iwclosure(imgSlider);
		imgSlider.src		= 'images/slider_new.png';
		imgSlider.width		= '58';
		imgSlider.height	= '218';
		imgSlider.border	= '0';

		// append the slider button

	  	iw.append(_container, _divSliderButton);

		_divSliderButton.style.position = 'absolute';
		_divSliderButton.style.left 	= _offsetX + 'px';
		_divSliderButton.style.top  	= _offsetY + 'px';
		_divSliderButton.style.width 	= '13px';
		_divSliderButton.style.height 	= '35px';
		_divSliderButton.style.cursor = 'pointer';

	  	IWEventManager.addDomListener(_divSliderButton, 'onmousedown',
	  		function(event)
	  		{
	  			if(!event)
	  			{
	  				event = window.event;
	  			}

				// TODO: Wird das noch benötigt?

				if (event.cancelable)
				{
					event.preventDefault();
				}
	   			event.cancelBubble = false;
	   			event.returnValue = false;

	  			var mouseEvent = _mouseAdapter.toMouseEvent(event, _container);

	  			//ignore all but leftclicks + if map already zooming +
	  			//map is zoomed by another object
				if ((mouseEvent.button != IWButton.LEFT) || map.isZooming() || !map.startOpticalZoom())
					return;

				IWEventManager.trigger(_map, 'beforezoom', null);

				limitHigh = _offsetY;
				limitLow = _maxSlide+_offsetY;
				var oldPosY  =  mouseEvent.position.getY();

				var onMouseMoveListener = IWEventManager.addListener(document.body, 'onmousemove',
					function(event)
					{
						if (!event)
						{
							event = window.event;
						}

						var mouseEvent = _mouseAdapter.toMouseEvent(event, _container);
						var mouseY = mouseEvent.position.getY();

						if (event.cancelable)
						{
							event.preventDefault();
						}
						event.cancelBubble = false;
						event.returnValue = false;

						var y = parseInt(_divSliderButton.style.top) + mouseY - oldPosY;
						if ((limitHigh < y) && (y < limitLow))
						{
							_divSliderButton.style.top  = y +'px';
							oldPosY = mouseY;

							// we determine the actual size for the map by a convexcombination
							// between current step and neighbour
							var alpha = this.getValue(false) - this.getValue()+1;
							var meter;
							if (this.getValue() == _lowValue)
								meter = alpha*_tilesizeArray[this.getValue()];
							else
								meter = alpha*_tilesizeArray[this.getValue()] + (1-alpha)*_tilesizeArray[this.getValue()-1];

							_map.setOpticalZoomStep(meter);
						}
					}.iwclosure(this)
				);

				var onMouseUpListener = IWEventManager.addListener(document.body, 'onmouseup',
					function(event)
					{
						_currentPos = this.getValue();
						var newLevel = _map.endOpticalZoom(_currentPos);

						if (_currentPos != newLevel)
						{
						  _currentPos = newLevel;
							this.setValue(newLevel, true);
						}
						IWEventManager.removeListener(onMouseMoveListener);
						IWEventManager.removeListener(onMouseUpListener);
					}.iwclosure(this)
				);
  			}.iwclosure(_self)
  		);


		// create the zoom button image

		var imgButton = iw.create('img');
		iw.append(_divSliderButton, imgButton);

		imgButton.src 				= iwconst.GLOBAL_APP_URL + 'img/slider_button.png';
		imgButton.style.width 		= '13px';
		imgButton.style.height 		= '35px';
	}

	//********************************************************************
	//* Constructor implementation
	//********************************************************************

	_container.id 			= 'IWSliderControl';
	_container.style.width 	= '58px';
	_container.style.height = '218px';

	this.setLanguage(_map.getOptions().getLanguage());

	//********************************************************************
	//* Eventhandling
	//********************************************************************

  	IWEventManager.addListener(_map, 'onmousewheel',
	  	function(event)
	  	{
	  		if (map.isZooming() || map.getOptions().getMouseWheelAction() != IWMapOptions.CONTROL_ZOOM)
	  		{
				return;
	  		}

  			_currentPos = Math.min(Math.max(_currentPos - event.delta, _map.getCurrentMapType().getMaxLevel()), _map.getCurrentMapType().getMinLevel());

  			this.setValue(_currentPos, true);
  		}.iwclosure(this)
  	);

  	IWEventManager.addListener(_map, 'onzoom',
  		function(event)
  		{
  			// Nur optimisches Verschieben des Buttons
  			this.setValue(event.newZoomLevel, true);
  		}.iwclosure(this)
  	);

  	IWEventManager.addListener(_map, 'aftercentered',
  		function(event)
  		{
  			this.setValue(_map.getZoom(), true);
  		}.iwclosure(this)
  	);

  	IWEventManager.addListener(_map, 'aftermaptypechanged',
  		function(event)
  		{
	  		_currentPos = _map.getZoom();
	  		_lowValue = _map.getCurrentMapType().getMaxLevel();
	  		_highValue = _map.getCurrentMapType().getMinLevel();
	  		this.setValue(_currentPos, true);
  		}.iwclosure(this)
  	);

  	IWEventManager.addListener(_map, 'afterlanguagechanged',
  		function(e)
  		{
  			_self.setLanguage(e.language);
  		}
  	);
}
function showRouteInput() {

	document.getElementById('berechneRoute').style.cssFloat = 'left';
	document.getElementById('berechneRoute').style.overflowY = 'auto';
	document.getElementById('berechneRoute').style.overflowX = 'hidden';
	document.getElementById('berechneRoute').style.height = document.getElementById("divMap").offsetHeight + "px";
	document.getElementById('berechneRoute').style.width = '254px';

	document.getElementById('berechneRoute').innerHTML =

	'<form onsubmit="startRouting();wipeCounter.logAction(\'KSroute\'); return false;">' + '<fieldset class="start"><legend><span>Start</span></legend>' + '<div class="row">' + '<label><span>Stra&szlig;e</span><input id="STR1" name="STR1" type="text" class="strasse" value="" /></label>'
			+ '<label><span>Nr.</span><input id="HNR1" name="HNR1" type="text" class="nummer" value="" /></label>' + '</div><br class="clear" />' + '<div class="row">' + '<label><span>PLZ</span><input id="PLZ1" name="PLZ1" type="text" class="plz" value="" maxlength="5" /></label>'
			+ '<label><span>Ort</span><input id="ORT1" name="ORT1" type="text" class="ort" value="" /></label>' + '</div>' + '</fieldset>' + '<fieldset><legend><span>Ziel</span></legend>' + '<div id="destination" class="zieladresse"></div>' + '</fieldset>'
			+ '<fieldset class="settings"><legend><span>Einstellungen</span></legend>' + '<div>' + '<span>Route</span>' + '<label for="schnellste_route"><input id="schnellste_route" name="route" type="radio" value="schnellste" checked="true"/>schnellste</label>'
			+ '<label for="kuerzeste_route"><input id="kuerzeste_route" name="route" type="radio" value="kuerzeste" />k&uuml;rzeste</label>' + '</div>' + '<div>' + '<span>Fahrstil</span>'
			+ '<label for="fahrstil_langsam"><input id="fahrstil_langsam" name="fahrstil" type="radio" value="langsam" />langsam</label>' + '<label for="fahrstil_normal"><input id="fahrstil_normal" name="fahrstil" type="radio" value="normal" checked="true"/>normal </label>'
			+ '<label for="fahrstil_schnell"><input id="fahrstil_schnell" name="fahrstil" type="radio" value="schnell" />schnell</label>' + '</div>' + '</fieldset>' + '<input name="Route berechnen" type="submit" id="btn_route_berechnen" value="" />' + '</form>';
}

function showWaitMessage(from, to, name) {
	document.getElementById('berechneRoute').innerHTML = '<div id="zeigeRoute">' + '<div class="ihreroute"><strong>Ihre Route</strong></div>' + '<div>von:<br /><span id="start_str">' + from.getStreet() + '</span>&nbsp;<span id="start_nr">' + from.getHouseNumber()
			+ '</span><br /><span id="start_plz">' + from.getZipCode() + '</span>&nbsp;<span id="start_ort">' + from.getCity() + '</span></div>' + '<div>nach:<br />' + name + '<br />' + to.getStreet() + ' ' + to.getHouseNumber() + '<br />' + to.getZipCode() + ' ' + to.getCity() + '</div>'
			+ '<div>wird berechnet.</div>' + '<div class="hinweis">Je nach Auslastung des Servers kann dies einige Sekunden dauern. Bitte haben Sie etwas Geduld &hellip;</div>' + '</div>';
}

function geocodeRoutingAddresses(from, to, routeOptions, name) {
	var _inputAddresses = new Array();

	var _geocoderClient = new IWSimpleGeocoderClient();
	_geocoderClient.setUrl(geocoderUrl);

	var _addressIndex = 0;
	var _geocodeAddresses = null;
	var _routeAddresses = null;
	var _MAX_ADDRESSES_PER_GEOCODE = 100;

	var _geoResults = new Array();

	_geoResults[0] = null;
	_geoResults[1] = null;
	var oneResult = false;

//TODO:
	var _onGeocodeListener = IWEventManager.addListener(_geocoderClient, 'ongeocode', function(event) {
		var results = event.results;
		if (results.length == 0) {
			var addressStr = formatAddressString(event.inputAddress);
			addressStr.trim().length > 0 ? addressStr = ": " + addressStr : addressStr = " " + addressStr;  
			alert('Die Adresse konnte nicht geocodiert werden' + addressStr);
			return;
		} else {
			if (_addressIndex == 0) {
				var resultsLength = results.length;

				if (resultsLength > 1) {					
					var berechneRoute = document.getElementById("berechneRoute"); // was content

					berechneRoute.innerHTML = '';
					berechneRoute.style.cssFloat = 'left';
					berechneRoute.style.overflow = 'auto';
					berechneRoute.style.width = '100%';
					var content = document.createElement('div');
					content.style.height = '420px';
					berechneRoute.appendChild(content);
		
					var linkTabelle = document.createElement('div');
					linkTabelle.id = "adressList";
					linkTabelle.style.fontSize = "11px";
					linkTabelle.innerHTML = "<strong> <fmt:message key='severalAddressesWereFound'/> </strong><br/><br/>";

					content.appendChild(linkTabelle);

					for ( var i = resultsLength-1; i >= 0; i--) {
						var result = results[i];
						var text = formatAddressString(result.getAddress());
		
						var link = document.createElement('a');
						link.id = "routingStartAddr" + i;
						link.href = "#";
						link.className = "underlink";
						link.result = result;

						link.onclick = function(){
							_geoResults[0] = results[parseInt(this.id.substring(16))].getAddress();
							if (_geoResults[0] != null && _geoResults[1] != null) {
								showWaitMessage(from, to, name);
								routeStart = _geoResults[0];
								routeZiel = _geoResults[1];
								calcRoute(_geoResults[0], _geoResults[1], routeOptions);
							}
						};

						link.innerHTML = text + '</br>';
						linkTabelle.appendChild(link);
						linkTabelle.appendChild(document.createElement('br'));
					}
				} 
				else 
				{
					var result = results.pop();
					oneResult = true;
					_geoResults[0] = result.getAddress();
				}
		} 
		else 
		{
			var result = results.pop();
			_geoResults[1] = result.getAddress();
		}			
	}
	
	if (_addressIndex == 1 && oneResult) {
		showWaitMessage(from, to, name);
		routeStart = _geoResults[0];
		routeZiel = _geoResults[1];
		calcRoute(_geoResults[0], _geoResults[1], routeOptions);
	}

	// geocode the next address
	if (_addressIndex < _inputAddresses.length - 1) {
		_addressIndex++;
		_geocoderClient.geocodeAddress(_inputAddresses[_addressIndex]);
	}
}.iwclosure(this));

	_inputAddresses.push(from);
	_inputAddresses.push(to);

	_addressIndex = 0;
	_geocodeAddresses = new Array();
	_geocoderClient.geocodeAddress(_inputAddresses[_addressIndex], true);
}

function formatAddressString(address) {
	var s = '';

	if (address.getStreet() != null) {
		s = s.concat(address.getStreet());

		if (address.getHouseNumber() != null)
			s = s.concat(' ' + address.getHouseNumber());
	}

	if (address.getZipCode() != null) {
		if (address.getZipCode().replace(/^\s+|\s+$/g, '').length == 0)
			return;
		
		if (s.length > 0)
			s = s.concat(', ');

		s = s.concat(address.getZipCode()).concat(' ');
	}

	if (address.getCity() != null)
	{
		if (address.getCity().replace(/^\s+|\s+$/g, '').length == 0)
			return;

		s = s.concat(address.getCity());
	}

	if (address.getPart() != null)
	{
		if (address.getPart().replace(/^\s+|\s+$/g, '').length == 0)
			return;

		s = s.concat(" / ");
		s = s.concat(address.getPart());
	}
	
	return s;
}

function calcRoute(from, to, routeOptions) {
	var _routingClient = new IWRoutingClient();
	var _routeSegments = null;
	routeBounds = null;
	routeSegments = null;
	
	IWEventManager.addListener(_routingClient, 'onroute', function(event) {
		shapeName = event.shape;
		showRoutingResult(event);
		showRouteOnMap(event);
		routeBounds = event.route.getBounds();
		routeSegments = event.route;

	});

	_routingClient.setRouteOptions(routeOptions);
	_routingClient.route(from, to);
}

function clearRoutingResult() {
	var table = document.getElementById("routeErgebnis");
	var rows = table.rows;
	while (rows.length > 1)
		table.deleteRow(rows.length - 1);

}

function showRoutingResult1(event)
{
	var route = event.route;
	
	//********************************************************************
	//* Formats the driving instructions 
	//********************************************************************
	var formatter = new IWRouteFormatter(route);
	formatter.setLanguage('de');

	var table = document.getElementById('routeErgebnis');								

	for (var i = table.rows.length-1; i > 0; i--)
	{
		table.deleteRow(i);
	}
	
	for(var i = 0; i < route.getSegments(); i++) 
	{					
		var tr = table.insertRow(i+1);
		
		tr.className = (i % 2 ? 'even' : 'odd');
		
		var td = tr.insertCell(0);
		td.innerHTML = i+1;

		var td = tr.insertCell(1);
		td.style.textAlign = 'center';			
		td.innerHTML = formatter.createImageAsHTML(i);											

		tr.insertCell(2).innerHTML = formatter.createDescriptionAsHTML(i);													
		tr.insertCell(3).innerHTML = formatter.createDistanceAsHTML(i);
	}			
	
	//********************************************************************
	//* Puts the routing layer on the map
	//********************************************************************	
	
	// if the routeLayer does not exist we create one.
	if (routeLayer == null)
	{
		routeLayer = new IWLayer(map, 'route', 'ROUTE');
		// the geometrie of a route is stored in a shape file.		
		routeLayer.addShape(new IWShape(route.getShape()));
		// add the route layer to the map.
		map.addLayer(routeLayer);					
	}
	else
	{
		// sets the name of the shapefile for the new route.
		routeLayer.getShapes()[0].setShapeName(route.getShape());
	}
	// set the new center and zooming level to show the whole route on the map.
	map.setCenter(route.getBounds().getCenter(), map.getBoundsZoomlevel(route.getBounds()));
				
	return true;
}

function showRoutingResult(event) {
	clearRoutingResult();
	
	var totalTime = 0;
	var totalDistance = 0;
	var table = document.getElementById("routeErgebnis");
	var route = event.route;
	
	var formatter = new IWRouteFormatter(route);
	formatter.setLanguage('de');

	for(var i = 0; i < route.getSegments(); i++)
	{   			
		var segment = route.getEntry(i); 
		
		var tr = table.insertRow(i + 1);
		tr.style.color = "#024f99";
		tr.style.borderBottom = "2px solid #fff";

		// number
		var td = iw.create("td");
		td.style.color = "#024f99";
		td.style.paddingLeft = "10px";
		td.style.width = "35px";
		td.appendChild(document.createTextNode((i + 1) + "."));
		iw.append(tr, td);

		// direction image
		var td = iw.create("td");
		td.style.color = "#024f99";
		td.style.width = "60px";
		var img = iw.create("img");
		img.src = appPath + "images/route/" + getGetDirectionImage(segment.getDirection());
		td.appendChild(img);
		iw.append(tr, td);

		// time
		td = iw.create("td");
		td.style.color = "#024f99";
		td.style.paddingRight = "40px";
		td.style.paddingLeft = "5px";
		td.appendChild(document.createTextNode( formatRoutingTime(segment.getEntryTime())) );
		iw.append(tr, td);

		// description
		td = iw.create("td");
		td.style.color = "#024f99";
		td.style.width = "570px";
		td.style.paddingRight = "10px";
		var coord = segment.getCoordinate();
		var link = document.createElement('a');
		link.innerHTML = formatter.createDescriptionAsHTML(i);
		link.href = "javascript:showTargetArea(" + coord.getX() + "," + coord.getY() + ");";
		iw.append(td, link);
		iw.append(tr, td);

		// section length
		td = iw.create("td");
		td.style.color = "#024f99";
		td.style.paddingLeft = "10px";
		td.appendChild(document.createTextNode( formatDistence( segment.getEntryDistance() )) );
					
		iw.append(tr, td);

		// total time
		td = iw.create("td");
		td.style.color = "#024f99";
		td.style.paddingLeft = "10px";
		td.appendChild(document.createTextNode( formatRoutingTime(segment.getTotalTime())) );
		iw.append(tr, td);
		
		totalTime += segment.getEntryTime();
		totalDistance += segment.getEntryDistance();
	}

	table.style.display = '';
	
	var divTime = document.getElementById("routetotalTime");
	divTime.innerHTML = formatRoutingTimeInfo(totalTime);
	var divDistance = document.getElementById("routetotalDistance");
	divDistance.innerHTML = formatDistence(totalDistance);
	
	var divDistanceInfo = document.getElementById("totaldistance");
	divDistanceInfo.style.display = '';
}
var routeLayer = null;

function getZoomLevelWithMapType(_mapType, _route)
{
	var currrentMinLevel = map.getCurrentMapType().getMinLevel();
	var minLevelMapType = _mapType.getMinLevel();
	map.getCurrentMapType().setMinLevel(minLevelMapType);
	var newZoomLevel = map.getBoundsZoomlevel(_route.getBounds());
	map.getCurrentMapType().setMinLevel(currrentMinLevel);
	return newZoomLevel;
}

function showRouteOnMap(event) {
	var route = event.route;

	if (routeLayer == null) {
		routeLayer = new IWLayer(map, 'route', 'ROUTE');
		routeLayer.addShape(new IWShape(route.getShape()));
		map.addLayer(routeLayer);
	}
	else
	{
		routeLayer.getShapes()[0].setShapeName(route.getShape());
	}
	
	routeLayer.setVisibility(true);
	routeLayer.setVisible(true);

	var zoomLevel = map.getBoundsZoomlevel(route.getBounds());
	var routingCenter = route.getBounds().getCenter();
	if (map.getCurrentMapType().getName() == 'birdsview')
	{
		zoomLevel = getZoomLevelWithMapType(hybridBing_mapdispatcher, route);
		mapMode = 2; //hybrid
		var mapType = MaptypeUtils.updateTilesAliases(map, mapMode, zoomLevel, false);
		map.setCenter(routingCenter, zoomLevel, mapType);
	}
	else
	{
		map.setCenter(routingCenter, zoomLevel);
	}	
	 
	showRouteInput();
	var destination = document.getElementById('destination');
	destination.innerHTML = '<span class="title">' + routeName + '</span><br/>' + routeTo.getStreet() + ' ' + routeTo.getHouseNumber() + '<br/>' + routeTo.getZipCode() + ' ' + routeTo.getCity();

	if (divSubAdressesHtml.length > 0) {
		destination.innerHTML += '<div id="related" class="related_show"> ' + ' <a href="#" onClick="hideSubDestination(); return false";>Zugeh&ouml;rige Eintr&auml;ge ausblenden</a>' + '</div>';

		destination.innerHTML += '<div id="divSubadresses"> ' + divSubAdressesHtml + ' </div>';

	}

	document.getElementById('STR1').value = routeFrom.getStreet();
	document.getElementById('HNR1').value = routeFrom.getHouseNumber();
	document.getElementById('PLZ1').value = routeFrom.getZipCode();
	document.getElementById('ORT1').value = routeFrom.getCity();

	if (routeOptions.getType() == 'SPEED') {
		document.getElementById('schnellste_route').checked = true;
	} else {
		document.getElementById('kuerzeste_route').checked = true;
	}

	var speed = routeOptions.getCitySpeed();
	switch (speed) {
	case 30:
		document.getElementById('fahrstil_langsam').checked = true;
		break;
	case 40:
		document.getElementById('fahrstil_normal').checked = true;
		break;
	default:
		document.getElementById('fahrstil_schnell').checked = true;
		break;
	}
}

function hideRouteOnMap() {
	if (routeLayer != null) {
		routeLayer.setVisibility(false);
		routeLayer.setVisible(false);
	}

}
function showTargetArea(coordX, coordY) {
	wipeLogCenter = true;
	wipeLogZoom = false;
	
	var newCenter = new IWCoordinate(coordX, coordY);
	var targetZoomLevel = 13;
	
	if (map.getCurrentMapType().getName() == 'birdsview')
	{
		mapMode = 2; //hybrid
		var mapType = MaptypeUtils.updateTilesAliases(map, mapMode, targetZoomLevel, false);
		map.setCenter(newCenter, zoomLevel, mapType);
	}
	else
	{
		//TODO: targetZoomLevel?
		if (map.getZoom() != targetZoomLevel) {
			var _l = IWEventManager.addListener(map, 'onmove', function(e) {
				map.setZoom(targetZoomLevel);
				IWEventManager.removeListener(_l);
			});
		}

		map.panTo(newCenter);
	}
	
}

var routeDirectionImages = new Array();
routeDirectionImages[-3] = "rtlinks_3.gif";
routeDirectionImages[-2] = "rtlinks_2.gif";
routeDirectionImages[-1] = "rtlinks_1.gif";
routeDirectionImages[0] = "rtgeradeaus.gif";
routeDirectionImages[1] = "rtrechts1.gif";
routeDirectionImages[2] = "rtrechts2.gif";
routeDirectionImages[3] = "rtrechts3.gif";
routeDirectionImages[10] = "rtziel.gif";
routeDirectionImages[11] = "rtkreis.gif";

function getGetDirectionImage(direction) {
	return routeDirectionImages[direction];
}

function formatRoutingTime(seconds)
{
	var hours = Math.floor(seconds / 3600);
	hours = hours < 10 ? '0' + hours : hours;
	var minutes = Math.floor( (seconds % 3600) / 60 );
	minutes = minutes < 10 ? '0' + minutes : minutes;
	return hours +":"+ minutes; 
}

function formatDistence(meters)
{
	meters = parseInt(meters);
	var len = meters > 1000? Math.ceil( meters/1000 ) + " km" : meters + " m";
	return len;
}

function formatRoutingTimeInfo(seconds)
{
	var hours = Math.floor(seconds / 3600);
	var minutes = Math.floor( (seconds % 3600) / 60 );
	if (hours == 0){
		return minutes + " Min";
	}
	
	return hours + " Std. " + minutes + " Min"; 
}
function IWWipeCounter(ID, debug) {

	var wwa$ = null;

	if (debug != undefined && debug == true) {
		var wwa$ = _WWA_.getAnalyzer(ID, {
			debugMode : true
		});
	} else {
		wwa$ = _WWA_.getAnalyzer(ID);
	}

	var logKeys = {
		"KSdruck" : "Stadtplan Druckseite",
		"KShybrid" : "Stadtplan Hybrid",
		"KSkarte" : "Stadtplan Karte",
		"KSluft" : "Stadtplan Luftbild",
		"KSbird" : "Stadtplan Birdsview",
		"KSroute" : "Stadtplan Route",
		"KSrouteTab" : "Stadtplan Route Tab",
		"KSTrefferTab" : "Stadtplan Treffer Tab"
	};

	this.logAction = function(id) {

		var value = this.getValue(id);
		if (value != '') {

			wwa$.logAction(value);
		}

	}

	this.logPageVeiw = function(id) {

		var value = this.getValue(id);
		if (value != '') {
			wwa$.setPageAttr( {
				pageName : value
			});
			wwa$.logPageView();
		}

	}

	this.getValue = function(id) {
		var value = '';
		switch (id) {
		case 'KSdruck':
			value = logKeys.KSdruck;
			break;
		case 'KShybrid':
			value = logKeys.KShybrid;
			break;
		case 'KSkarte':
			value = logKeys.KSkarte;
			break;
		case 'KSluft':
			value = logKeys.KSluft;
			break;
		case 'KSbird':
			value = logKeys.KSbird;
			break;
		case 'KSroute':
			value = logKeys.KSroute;
			break;
		case 'KSrouteTab':
			value = logKeys.KSrouteTab;
			break;
		case 'KSTrefferTab':
			value = logKeys.KSTrefferTab;
			break;
		default:

			break;
		}
		return value;
	}
};/**
 * Creates a new geocoder client for the gc_simple application.
 *
 * @class A geocoder client is necessary in order to convert an address into coordinates. 
 *
 * @constructor
 * 
 * @author JAN
 */
//function 11IWSimpleGeocoderClient11()
{
	//********************************************************************
	//* Private attributes
	//********************************************************************
	var _url = 'http://localhost/gc_simple/Simple.jsp';
	
	//********************************************************************
	//* Public methods
	//********************************************************************
	
	/**
	 * Sets the url for gc_simple.
	 * @param {String} url, e.g. <code>http://iwgeo.mapandroute.de/gc_simple/Simple.jsp</code>
	 * @return {void}
	 */
	this.setURL = function(url)
	{
		_url = url;
	};
	
	/**
	 * Returns the url for gc_simple.
	 * @return {void}
	 */
	this.getURL = function()
	{
		return _url;
	};

	/**
	 * Geocodes an address into a coordinate.
	 * 
	 * @param {IWAddress} inputAddress an address
	 * @param {boolean} [multihits]	if this parameter is true, than the geocoder returns a list of geocoded addresses, otherwise it returns only the best one. 
	 * @return {void}
	 */
	this.geocodeAddress = function(inputAddress, multihits)
	{		
		var multi = 0;

		//********************************************************************
		//* Check if the geocoder should return a list of geocoded addresses.
		//********************************************************************
		if (typeof multihits != 'undefined' && multihits == true)
		{
			multi = 1;
		}
		
		var serverUrl = _url + 
					'?VNR=' + IWAccessFilter.getCNR() + 
					'&PNR=' + IWAccessFilter.getPNR() + 
					'&PLZ=' + inputAddress.getZipCode() + 
					'&ORT=' + inputAddress.getCity() + 
					'&STR=' + inputAddress.getStreet() + 
					'&HNR=' + inputAddress.getHouseNumber() + 
					'&LND=' + inputAddress.getCountryCode() + 
					'&MULTI=' + multi;
										
		var xmlHttp = new IWXMLHttpRequest();
		
		var url = iwconst.GLOBAL_PROXY_URL + '?serverURL=' + escape(serverUrl);
		
		xmlHttp.open('GET', url, true);
    	xmlHttp.onreadystatechange = function() { geocodedCallback(this, xmlHttp, inputAddress); }.iwclosure(this);
    	xmlHttp.send(null);														
	};
	
	/**
	 * Returns a string representation of this geocoder client.
	 *
	 * @return {String}
	 */ 
	this.toString = function()
	{
		return '[IWSimpleGeocoderClient]';
	};
	
	//********************************************************************
	//* Event functions
	//********************************************************************	
	
	/**
	 * The <tt>afterGeocodedEvent</tt> is fired when the address is geocoded.
	 * 
	 * <p>Register an event listener with <tt>IWEventManager.addListener(theSimpleGeocoderClient, 'aftergeocoded', yourHandlerMethod(event));</tt> to receive the event.</p> 
	 * 
	 * @event afterGeocoded
	 * @param {IWSimpleGeocodingEvent} event the geocoding event
	 * @return {void}
	 */			
	this.triggerAfterGeocoded = function(event)
	{
		 IWEventManager.trigger(this, 'aftergeocoded', event);			
	};	
	
	//********************************************************************
	//* Private methods
	//********************************************************************

	/**
	 * Callback method for geocoding. Triggers the <tt>aftergeocoded</tt> event.
	 * 
	 * @private
	 * @param {IWSimpleGeocoderClient} self
	 * @param {IWXMLHttpRequest} xmlHttp
	 * @param {IWCoordinate} inputAddress
	 * @return {void}
	 */
	function geocodedCallback(self, xmlHttp, inputAddress)
	{
		var results = new Array();

		if (xmlHttp.readyState == 4)
		{		
			if(xmlHttp.statusText == 'OK')
		 	{
//				var root = xmlHttp.responseXML.documentElement;
				var root = xmlHttp.responseText;
				//var json = eval("(" + xmlHttp.responseText + ")");
				
				if (window.DOMParser)
				  {
				  parser=new DOMParser();
				  xmlDoc=parser.parseFromString(root,"text/xml");
				  }
				else // Internet Explorer
				  {
				  xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
				  xmlDoc.async="false";
				  xmlDoc.loadXML(root);
				  }
				root = xmlDoc;
				   
				
				var errorText = IWXMLHelper.getNodeValue(root.getElementsByTagName('error'));
				
				if (errorText == null || errorText == '')
			  	{
			  		var zipCodes = root.getElementsByTagName('zipcode');
			  		var cities = root.getElementsByTagName('city');
			  		var parts = root.getElementsByTagName('part');			  		
					var streets = root.getElementsByTagName('street');
					var houseNumbers = root.getElementsByTagName('housenumber');
			    	var wgs84 = root.getElementsByTagName('wgs84');
			    	var lccEurope = root.getElementsByTagName('lcc_europe');
			    	var matchcode = root.getElementsByTagName('matchcode');

			    	for (var i = (zipCodes.length-1); i >= 0; i--)
					{
						var houseNumber = IWXMLHelper.getNodeValue(houseNumbers[i]);
						
			    		var address = new IWAddress();
						address.setStreet(IWXMLHelper.getNodeValue(streets[i]));
						address.setHouseNumber((houseNumber != 'X' && houseNumber != '0' ? houseNumber : ''));
						address.setZipCode(IWXMLHelper.getNodeValue(zipCodes[i]));
						
						var city = IWXMLHelper.getNodeValue(cities[i]);	
						var part = IWXMLHelper.getNodeValue(parts[i]); 					
						if (part != null && part != '')
						{
							city += '\u0020/\u0020' + part; 							
						}
						
						address.setCity(city);
						address.setCountryCode(inputAddress.getCountryCode());						
	
						var result = new IWSimpleGeocodingResult();
						result.setAddress(address);
			      		result.setLCC(new IWLCCEurope(IWXMLHelper.getNodeValue(lccEurope[i].childNodes[0]), IWXMLHelper.getNodeValue(lccEurope[i].childNodes[1])));         
						result.setWGS84(new IWWGS84(IWXMLHelper.getNodeValue(wgs84[i].childNodes[0]), IWXMLHelper.getNodeValue(wgs84[i].childNodes[1])));
						result.setMatchCode(IWXMLHelper.getNodeValue(matchcode[i]));
		
						results.push(result);
					}						
				}
			}
			else if (xmlHttp.status == 401)
			{
				alert(xmlHttp.statusText);
			}	
			else
			{
				alert('Geocoding failed: ' + xmlHttp.status + '\n' + xmlHttp.statusText);
			}		
		}
		
		var event = new IWSimpleGeocodingEvent();
		event.inputAddress = inputAddress;
		event.status = xmlHttp.statusText;
		event.results = results;		
		
		self.triggerAfterGeocoded(event);
	}
	
	//********************************************************************
	//* Constructor implementation
	//********************************************************************
}/**
 * Creates a new simple geocoding event.
 *
 * @class
 *
 * @constructor
 * 
 * @author JAN
 */
function IWSimpleGeocodingEvent()
{
	//********************************************************************
	//* Public attributes
	//********************************************************************	

	/**
	 * The status code from the geocoder service.
	 * @type {String}
	 */
	this.status = null;
	
	/**
	 * The input address.
	 * @type {IWAddress}
	 */
	this.inputAddress = null;

	/**
	 * An array of geocoded address results.
	 * @type {IWSimpleGeocodingResult[]}
	 */	
	this.results = null;
	
	/**
	 * Returns a string representation of this geocoding event.
	 *
	 * @return {String}	
	 */	
	this.toString = function()
	{
		return '[IWSimpleGeocodingEvent] ' +
			'InputAddress: ' + (this.inputAddress == null ? 'null' : this.inputAddress) + ', ' +
			'Status: ' + (this.status == null ? 'null' : this.status) + ', ' + 
			'Results: ' + (this.results == null ? 'null' : this.results.length);
	};
}	
/**
 * Creates a new geocoding result.
 *
 * @class A geocoded address result.
 *
 * @constructor
 * 
 * @author JAN
 */
function IWSimpleGeocodingResult()
{
	//********************************************************************
	//* Private attributes
	//********************************************************************	
	
	var _address = null;
	var _lcc = null;
	var _wgs84 = null;
	var _matchcode = null;
	
	//********************************************************************
	//* Public methods
	//********************************************************************		
	
	/**
	 * Sets the address for this geocoding result.
	 * 
	 * @param {IWAddress} address the geocoded address
	 * 
	 * @return {void}
	 */	
	this.setAddress = function(address)
	{
		_address = address;
	};
	
	/**
	 * Returns the geocoded address. 
	 * 
	 * @return {IWAddress} address 
	 */	
	this.getAddress = function()
	{
		return _address;
	};
	
	/**
	 * Sets the LCC coordinate on which the address has been located.
	 *  
	 * @param {IWLCCEurope} lcc the lcc coordinate
	 * @return {void}
	 */
	this.setLCC = function(lcc)
	{
		_lcc = lcc;
	}
	
	/**
	 * Returns the lcc coordinate of the geocoded address.
	 * 
	 * @return {IWLCCEurope} the lcc coordinate
	 */
	this.getLCC = function()
	{
		return _lcc;
	};
	
	/**
	 * Sets the WGS84 coordinate on which the address has been located.
	 * 
	 * @param {IWWGS84} wgs84
	 * @return {void}
	 */
	this.setWGS84 = function(wgs84)
	{
		_wgs84 = wgs84;		
	};
	
	/**
	 * Returns the WGS84 coordinate of the geocoded address.
	 * 
	 * @return {IWWGS84}
	 */
	this.getWGS84 = function()
	{
		return _wgs84;
	};
	
	/**
	 * Sets the matchcode of the geocoded address.
	 * 
	 * @param {int} matchcode
	 * 
	 * @return {void}
	 */	
	this.setMatchCode = function(matchcode)
	{
		_matchcode = matchcode;
	};
	
	/**
	 * Returns the matchcode of the geocoded address.
	 * 
	 * <p>The following matchcodes are definied:</p> 
	 * 
	 * <UL>
     * <LI><code>-1</code>: indicates an error</LI>
     * <LI><code>&nbsp;1</code>: house exactly</LI>
     * <LI><code>&nbsp;2</code>: street exactly</LI>
     * <LI><code>&nbsp;3</code>: city exactly</LI>
     * <LI><code>&nbsp;4</code>: zip code exactly</LI>
     * </UL>
	 
	 * @return {int}
	 */
	this.getMatchCode = function()
	{
		return _matchcode;
	};
	
	/**
	 * Returns a string representation of this geocoding result.
	 * 
	 * @return {String}
	 */
	this.toString = function()
	{
		return '[IWSimpleGeocodingResult] ' +
			'address: ' + _address.toString() + ', ' +
			'lcc cooordinate: ' + _lcc.toString() + ', ' +
			'wgs84 coordinate: ' + _wgs84.toString() + ', ' +
			'matchcode: ' + _matchcode;			
	};
}

