// Build the webgisApp namespace 
(function(){
    if (typeof window.webgisApp === 'undefined') {
        window.webgisApp = {};
        OpenLayers.ImgPath = '/static/map_app/js/OpenLayers-2.9-rc1/img/';
    } else {
        throw 'Konnte globale Variable "webgisApp" nicht "window" zuweisen. Namenskollision?';
    }
})();

// Blocking the UI until the map is ready...
jQuery( window ).load( function () {
    webgisApp.getDataAndBuildOpenLayersClient();
    webgisApp.addLogo();
    webgisApp.addLegend();
    webgisApp.addBuiltByTerrestrisNote();
});
// log global for development
function log(){
/*    if (typeof window.console === 'object' && typeof window.console.log !== 'undefined') {
        try {
            console.log.apply(this, arguments);    
        } catch(e) {
            for(var i=0, l=arguments.length; i<l; l++) {
                console.log(arguments[i]);
            }
        }
        
    } */
}
// error global for development
function error(m){
    log(m);
    //throw m;
}



var marginHotelContainer = 25;
var widthHotelContainer = 625;
var heightHotelContainer = 465; // 475;

// Current Client
webgisApp.clientid = 'DSAR';
// holds the OpemLayers.Map instance
webgisApp.map = null;
// Farben für die Veltorlayer
webgisApp.vectorcolors = {
    hotel: {
        primary: '#ff3300',
        secondary: '#33ff00'
    },
    poi: {
        primary: '#0033ff',
        secondary: '#33ff00'
    },
    route: {
        primary: '#ac001f',// oder C90017?
        secondary: '#ac001f'
    },
    highlight: {
        primary: '#ffd700',
        secondary: '#ffd700'
    }
};

webgisApp.readDataURL = function() {
    var dataurl = 'http://tourplaner.dsar.de/reiseverlauf/bcc5966d-bf57-4837-8494-d0756fef07e3/data.json';
    var urlobj = new URL( location.href );
    if ( urlobj.get('dataurl') !== null) {
        dataurl = urlobj.get('dataurl');
    } 
    return dataurl;
};
webgisApp.parseDataURL = function(){
    var my_url = location.href.split("?")[0];
    if(my_url.toLowerCase().indexOf('http://tourplaner.dsar.de') !== -1) {
        return my_url.replace('karte', 'reiseverlauf') + 'data.json'
    }else{
        return my_url.replace('karte', 'extern') + 'data.json'
    }
}
// der Highlightlayer
webgisApp.highlightVectorLayer = null;
// Hotellayer
webgisApp.hotelVectorLayer = null;
// Start und Zielfahne
webgisApp.startAndFinishVectorLayer = null;
// Das Popup (vom Hovern)
webgisApp.hoverPopup = null;
// Der Timeout, der Das Popup autpomatisch nach drei sekunden ausblendet
webgisApp.hoverPopupAutoDestroyTO = null;
// URL auf das JSON-Objekt
webgisApp.dataURL = webgisApp.parseDataURL(); 
// unser lokaler Proxy !! Ggf. einrichten & anpassen
//webgisApp.proxy = '/cgi-bin/proxy.cgi';
webgisApp.proxy = '';
// die "Lightbox" (jQuery-Objekt)
webgisApp.moreDetailsDialog = undefined;
// Der Dialog mit den Hotels (jQuery-Objekt)
webgisApp.hotelContainer = null;
// Die eigentliche Liste der Hotels (jQuery-Objekt)
webgisApp.hotelList = null;
webgisApp.reiseroutenData = null;
webgisApp.proj = {};
webgisApp.proj.google = new OpenLayers.Projection('EPSG:900913'); 
webgisApp.proj.lonlat = new OpenLayers.Projection('EPSG:4326');
webgisApp.proj.lonlat2google = function( olObj ) {
    return (olObj.clone()).transform(webgisApp.proj.lonlat, webgisApp.proj.google); 
};
webgisApp.proj.google2lonlat = function( olObj ) {
    return (olObj.clone()).transform(webgisApp.proj.google, webgisApp.proj.lonlat); 
};
webgisApp.addBuiltByTerrestrisNote = function(){
  var html_fragment_bg =  jQuery('<div id="built-by-terrestris-bg">...built by <a href="http://www.terrestris.de/">terrestris</a></div>');
  var html_fragment_front =  jQuery('<div id="built-by-terrestris">...built by <a href="http://www.terrestris.de/">terrestris</a></div>');
  jQuery( document.body ).append(html_fragment_bg).append(html_fragment_front);
};

webgisApp.addLegend = function(){
  var legend_div =  jQuery('<div id="clickable-legend" class="closed" title="Anklicken zum Ein- oder Ausblenden der Legende"></div>');
  legend_div.bind('click', function() {
      $this = jQuery(this);
      if ($this.hasClass('closed')) {
          $this.removeClass('closed').addClass('open');
          $this.animate({
              height:144
          }, 400, 'linear');
      } else {
          $this.animate({
              height:21
          }, 400, 'linear', function() {
              jQuery(this).removeClass('open').addClass('closed');
          });
      }
  });
  jQuery( document.body ).append(legend_div);
};

webgisApp.addLogo = function(){
  var logo_div =  jQuery('<div id="customer-logo"></div>');
  jQuery( document.body ).append( logo_div );
};

webgisApp.toggleAdditionalInformationAccordion = function(img) {
  if (/plus\.gif$/.test(img.src) ) {
      img.src = '/static/map_app/img/minus.gif';
  } else {
      img.src = '/static/map_app/img/plus.gif';
  }
  jQuery(img).parents('li:first').find('div.terrestris-hideable-content').toggleClass('terrestris-hidden-content');
};

webgisApp.getHotelListItem = function(day, coordsObj){
    var d = Date.parseExact(webgisApp.reiseroutenData.date, "yyyy-MM-dd");
    d.add({
        days: (day.day-1)
    });
    var formattedDate = d.toString('dd.MM.yyyy');
    var weekday = d.toString('ddd');
    var hotel_li_parts = [];
    hotel_li_parts.push('<li class="ui-corner-all terrestris-accordion-header">');
    hotel_li_parts.push('<div class="terrestris-clickable-header">');
    hotel_li_parts.push('<table class="information-table">');
    hotel_li_parts.push('<tr class="general-information">');
    hotel_li_parts.push('<td class="day-in-row">Tag ' + str_pad(day.day, 2, '0', 'STR_PAD_LEFT') + '</td>');
    hotel_li_parts.push('<td class="weekday">' + weekday + '</td>');
    hotel_li_parts.push('<td class="date">' + formattedDate + '</td>');
    hotel_li_parts.push('<td class="title">' + (day.title || '') + '</td>');
    //if (coordsObj.prev_lon && coordsObj.prev_lat) {
        hotel_li_parts.push('<td class="show-in-map"><a href="#" title="Klicken, um zum gew&auml;hlten Kartenabschnitt zoomen" onclick="return (function(){webgisApp.zoomToRoutePart(' + coordsObj.prev_lon + ', ' + coordsObj.prev_lat + ', ' + coordsObj.this_lon + ', ' + coordsObj.this_lat + ', ' + coordsObj.next_lon + ', ' + coordsObj.next_lat + ');return false})();">Anzeige in Karte</a></td>');
    //} else {
    //    hotel_li_parts.push('<td class="show-in-map">&nbsp;</td>');
    //}
    
    hotel_li_parts.push('<td class="toggle-additional-information"><img title="Klicken, um mehr Informationen zum Tag ein- bzw. ausblenden" src="/static/map_app/img/plus.gif" width="16" height="14" onclick="webgisApp.toggleAdditionalInformationAccordion(this);"></td>');
    hotel_li_parts.push('</tr>');
    hotel_li_parts.push('<tr class="additional-information">');
    hotel_li_parts.push('<td class="route" colspan="4">' + (day.route || '') + '</td>');
    if (day.distance && day.distance !== '') {
        hotel_li_parts.push('<td class="distance">(ca. ' + day.distance  + ' km)</td>');
    } else {
        hotel_li_parts.push('<td class="distance"></td>');
    }
    
    hotel_li_parts.push('<td>&nbsp;</td>');
    hotel_li_parts.push('</tr>');
    hotel_li_parts.push('</table>');
    hotel_li_parts.push('</div>');
    hotel_li_parts.push('<div class="terrestris-hideable-content terrestris-hidden-content">');
    hotel_li_parts.push('<p>' + (day.program || '') + '</p>');
    hotel_li_parts.push('<table class="information-table">');
    if (day.pois && day.pois.length > 0) {
        var pois_html = [];
        hotel_li_parts.push('<tr>');
        hotel_li_parts.push('<td class="data-header-cell"><strong>Sehenswert:</strong></td>');
        hotel_li_parts.push('<td>');
        jQuery.each(day.pois, function (i, n) {
            pois_html.push('<a href="' + n.url + '" onclick="webgisApp.openMoreInformationPopup(this.href);return (function(){return false;})()">' + n.name + '</a>');
        });
        hotel_li_parts.push(pois_html.join(', '));
        hotel_li_parts.push('</td>');
        hotel_li_parts.push('</tr>');
    }
    if (day.hotel && day.hotel.name) {
        hotel_li_parts.push('<tr>');
        hotel_li_parts.push('<td class="data-header-cell"><strong>Unterkunft:</strong></td>');
        hotel_li_parts.push('<td><a href="' + day.hotel.url + '" onclick="webgisApp.openMoreInformationPopup(this.href);return (function(){return false;})();">' + day.hotel.name + '</a>');
        if (day.hotel.leistungsbasis && day.hotel.leistungsbasis !== '') {
            hotel_li_parts.push(', (' + day.hotel.leistungsbasis + ')</td>');
        }
        hotel_li_parts.push('</tr>');
    }
    
    hotel_li_parts.push('</table>');
    hotel_li_parts.push('</div>');
    hotel_li_parts.push('</li>');
    var $hotel_li = jQuery(hotel_li_parts.join(''));
    return $hotel_li;
};


/**
 * erzeugt den Openlayers-Client und holt die Daten von JSON. Ausgewertet wird das JSON in 
 * @see webgisApp.processReiseroutenData
 */
webgisApp.getDataAndBuildOpenLayersClient = function (){
    jQuery(document.body).ajaxError(function(event, request, settings){
        alert("URL-Parameter 'dataurl' scheint invalides JSON zurückzugeben.\n\nVerwendete URL: " + settings.url);
        return;
    });
    jQuery.getJSON(/*webgisApp.proxy + '?url=' + */webgisApp.dataURL, function(reiserouten_data, message, xhrObj){
        if(message !== 'success' || xhrObj.statusText !== "OK") {
          return;   
        }
        jQuery('#map').html(""); // clear content, #A.B.
        webgisApp.map = new OpenLayers.Map('map', {
            projection : webgisApp.proj.google,
            displayProjection: webgisApp.proj.google,
            units: "m",
            maxResolution: 156543.0339,
            maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34, 20037508.34, 20037508.34),
            controls: []
        });
        webgisApp.map.addControl(new OpenLayers.Control.Attribution());
        webgisApp.map.addControl(new OpenLayers.Control.LayerSwitcher({activeColor: '#ac001f', roundedCornerColor: '#ac001f'}));
        webgisApp.map.addControl(new OpenLayers.Control.PanZoomBar({position: new OpenLayers.Pixel(5, 65)}));
        webgisApp.map.addControl(new OpenLayers.Control.Navigation());
        
        //Google Layer (Normal, Satellite, Hybrid, Physical) erzeugen und hinzufuegen
        var gphy = new OpenLayers.Layer.Google("Google Physical", {
            type: G_PHYSICAL_MAP,
            sphericalMercator: true,
            transitionEffect: 'resize',
            buffer: 0
        });

        var gmap = new OpenLayers.Layer.Google("Google Streets", {
            numZoomLevels: 20,
            sphericalMercator: true,
            transitionEffect: 'resize',
            buffer: 0
        });
        
        var ghyb = new OpenLayers.Layer.Google("Google Hybrid", {
            type: G_HYBRID_MAP,
            numZoomLevels: 20,
            sphericalMercator: true,
            transitionEffect: 'resize',
            buffer: 0
        });
        
        var gsat = new OpenLayers.Layer.Google("Google Satellite", {
            type: G_SATELLITE_MAP,
            numZoomLevels: 20,
            sphericalMercator: true,
            transitionEffect: 'resize',
            buffer: 0
        });
        
        var osm_mapnik = new OpenLayers.Layer.OSM.Mapnik("OpenStreetMap (Mapnik)");
        var osm_osmarender = new OpenLayers.Layer.OSM.Osmarender("OpenStreetMap (Osmarender)");
        
        webgisApp.map.addLayers([gphy, gmap, ghyb, gsat, osm_mapnik, osm_osmarender]);
      
        var routeStyleMap = new OpenLayers.StyleMap({
            "default": new OpenLayers.Style(OpenLayers.Util.applyDefaults({
                strokeColor: webgisApp.vectorcolors.route.primary,
                strokeWidth: 3,
                strokeDashstyle: 'dash',
                strokeLinecap: 'square',
                strokeOpacity: 1,
                fillColor: webgisApp.vectorcolors.route.primary,
                fillOpacity: 0.7,
                pointRadius: 5
            }, OpenLayers.Feature.Vector.style["default"]))
        });
        var route_lyr = new OpenLayers.Layer.Vector('Reiseroute', {
            styleMap: routeStyleMap,
            transitionEffect: 'resize'
        });
        webgisApp.map.addLayer(route_lyr);
        
        var routeDirectionsStyleMap = new OpenLayers.StyleMap({
            "default": new OpenLayers.Style(OpenLayers.Util.applyDefaults({
                strokeColor: webgisApp.vectorcolors.route.primary,
                strokeWidth: 1,
                strokeOpacity: 1,
                fillColor: webgisApp.vectorcolors.route.primary,
                fillOpacity: 1,
                externalGraphic: "/static/map_app/img/arrow_up.png",
                graphicWidth: 24,
                graphicHeight: 24,
                rotation: "${angle}"
            }, OpenLayers.Feature.Vector.style["default"]))
        });
        var routeDirections_lyr = new OpenLayers.Layer.Vector('Reiserichtung', {
            styleMap: routeDirectionsStyleMap,
            transitionEffect: 'resize'
        });
        webgisApp.map.addLayer(routeDirections_lyr);
        
        
        // start and ednpoint layer
        var startAndFinishStyleMap = new OpenLayers.StyleMap({
            "default": new OpenLayers.Style(OpenLayers.Util.applyDefaults({
                strokeColor: webgisApp.vectorcolors.route.primary,
                strokeWidth: 1,
                strokeOpacity: 1,
                fillColor: webgisApp.vectorcolors.route.primary,
                fillOpacity: 1,
                externalGraphic: '${image}',
                graphicWidth: 46,
                graphicHeight: 42,
                graphicOpacity: 1,
                graphicXOffset: '${xoffset}',
                graphicYOffset: '${yoffset}'
            }, OpenLayers.Feature.Vector.style["default"]))
        });
        webgisApp.startAndFinishVectorLayer = new OpenLayers.Layer.Vector("Start- und Zielpunkt", {
           styleMap: startAndFinishStyleMap,
           displayInLayerSwitcher: true 
        });
        webgisApp.map.addLayer(webgisApp.startAndFinishVectorLayer );
        
        
        var highlightVectorLayerStyleMap = new OpenLayers.StyleMap({
            "default": new OpenLayers.Style(OpenLayers.Util.applyDefaults({
                strokeColor: webgisApp.vectorcolors.highlight.primary,
                strokeWidth: 2,
                strokeOpacity: 1,
                graphicName: 'star',
                fillColor: webgisApp.vectorcolors.highlight.primary,
                fillOpacity: 1,
                pointRadius: 10
            }, OpenLayers.Feature.Vector.style["default"]))
        });
        
        // Highlight-Vektorlayer
        webgisApp.highlightVectorLayer = new OpenLayers.Layer.Vector("Highlight-Vektorlayer", 
            {
                styleMap: highlightVectorLayerStyleMap,
                displayInLayerSwitcher: false,
                transitionEffect: 'resize'
            }
        );
        
        webgisApp.map.addLayer(webgisApp.highlightVectorLayer);
        
        //Vektorlayer
        
        var hotelStyleMap = new OpenLayers.StyleMap({
            "default": new OpenLayers.Style(OpenLayers.Util.applyDefaults({
                strokeColor: '${primaryColor}',
                strokeOpacity: 1,
                fillColor: '${primaryColor}',
                fillOpacity: 0.7,
                pointRadius: 5,
                externalGraphic: '${thumb}',
                graphicWidth: 66,
                graphicHeight: 49,
                graphicOpacity: 1,
                graphicXOffset: 0,
                graphicYOffset: 0,
                graphicTitle: '${title}',
                backgroundGraphic: '/static/map_app/img/etappenziel.png',
                backgroundWidth: 19,
                backgroundHeight: 18,
                cursor: 'pointer'
            }, OpenLayers.Feature.Vector.style["default"]))
        });
        
        var hotels_lyr = new OpenLayers.Layer.Vector('Hotels der Reiseroute', {
            styleMap: hotelStyleMap,
            transitionEffect: 'resize'
        });
        webgisApp.map.addLayer(hotels_lyr);
        
        
        var poiStyleMap = new OpenLayers.StyleMap({
            "default": new OpenLayers.Style(OpenLayers.Util.applyDefaults({
                strokeColor: '${primaryColor}',
                strokeOpacity: 1,
                fillColor: '${primaryColor}',
                fillOpacity: 0.7,
                pointRadius: 5,
                externalGraphic: '${thumb}',
                graphicWidth: 66,
                graphicHeight: 49,
                graphicOpacity: 1,
                graphicXOffset: 0,
                graphicYOffset: -49,
                graphicTitle: '${title}',
                backgroundGraphic: '/static/map_app/img/poi.png',
                backgroundWidth: 13,
                backgroundHeight: 13,
                cursor: 'pointer'
            }, OpenLayers.Feature.Vector.style["default"]))
        });
        var pois_lyr = new OpenLayers.Layer.Vector('POIs der Reiseroute', {
            styleMap: poiStyleMap,
            transitionEffect: 'resize'
        });
        webgisApp.map.addLayer(pois_lyr);
        
        webgisApp.processReiseroutenData(hotels_lyr, pois_lyr, route_lyr, routeDirections_lyr, reiserouten_data);
        
        /*
        var ctrl_hoverSelect = new OpenLayers.Control.Hover({
            onPause: function(evt){
                var feature = this.featureLayer.getFeatureFromEvent(evt);
                if (feature !== null) {
                    webgisApp.selectFeatureByHoverHandler(feature, evt);
                }     
            },
            featureLayer : hotels_and_pois_lyr
        });
        // ... der Karte hinzufgen ...
        webgisApp.map.addControl(ctrl_hoverSelect);
        // ... und aktivieren.
        ctrl_hoverSelect.activate(); 
        */
        
        var ctrl_clickSelect = new OpenLayers.Control.SelectFeature(
            [
                hotels_lyr, // der layer mit den Hotel-Geometrien
                pois_lyr // der layer mit den Poi-Geometrien
            ],
            {
                onSelect: webgisApp.selectFeatureByClickHandler, // die aufzurufende Funktion
                hover: false,
                multiple: false
            }
        );
        // ... der Karte hinzufgen ...
        webgisApp.map.addControl(ctrl_clickSelect);
        // ... und aktivieren.
        ctrl_clickSelect.activate();  
        
        //Namibia in linker Bildschirmhaelfte
        var originalDataBounds = hotels_lyr.getDataExtent();
        originalDataBounds.extend(pois_lyr.getDataExtent());
        var decenteredDataBounds = webgisApp.decenterBounds(originalDataBounds);
        //map.zoomToExtent( decenteredDataBounds.transform(proj_disply, proj_google) );
        webgisApp.map.zoomToExtent( decenteredDataBounds, false );
    });
};
/**
 * TODO ggf. am ende des Prozessierens mit fixen wertrten aufrufen 
 * (keine erneute iteration)
 * 
 * @param {Object} daydata
 */
webgisApp.addFirstLastMarkers = function(daydata){
    var firstIdx;
    var lastIdx;
    
    jQuery.each(daydata, function (i, n) {
        if (typeof firstIdx === 'undefined' && !empty(n.hotel) && !empty(n.hotel.lon) && !empty(n.hotel.lat)) {
            firstIdx = i;
        } else if (typeof firstIdx === 'number' && !empty(n.hotel) && !empty(n.hotel.lon) && !empty(n.hotel.lat)) {
            lastIdx = i;
        }
    });
    
    /* added by AB 2011-01: fix for RVs with only one Hotel */
    if (typeof lastIdx === 'undefined' && typeof firstIdx === 'number') {
        lastIdx = firstIdx;
    }
       
    var start_g = new OpenLayers.Geometry.Point(
        daydata[firstIdx].hotel.lon,
        daydata[firstIdx].hotel.lat
    );
    var start_f = new OpenLayers.Feature.Vector(
        start_g.transform(webgisApp.proj.lonlat, webgisApp.proj.google),
        {
            image: '/static/map_app/img/startfahne.png',
            xoffset: '-46',
            yoffset: '-42'
        }
    );
    var end_g = new OpenLayers.Geometry.Point(
        daydata[lastIdx].hotel.lon,
        daydata[lastIdx].hotel.lat
    );
    var end_f = new OpenLayers.Feature.Vector(
        end_g.transform(webgisApp.proj.lonlat, webgisApp.proj.google),
        {
            image: '/static/map_app/img/zielfahne.png',
            xoffset: '0',
            yoffset: '-42'
        }
    );
    webgisApp.startAndFinishVectorLayer.addFeatures([start_f, end_f]);
    
};

/**
 * Prozessiert das JSON, fügt features denm Layern hunzu, füllt den
 * Dialog mit den Hotels und bindet die Click / Hover Funktionalität 
 * @param {OpenLayers.Layer.Vector} hotels_lyr
 * @param {OpenLayers.Layer.Vector} pois_lyr
 * @param {OpenLayers.Layer.Vector} route_lyr
 * @param {OpenLayers.Layer.Vector} routeDirections_lyr
 * @param {Object} reiserouten_data (Die JSON Antwort)
 */
webgisApp.processReiseroutenData = function(hotels_lyr, pois_lyr, route_lyr, routeDirections_lyr, reiserouten_data){
    webgisApp.reiseroutenData = reiserouten_data;
    var hotelFeatures = [];
    var routePoints = [];
    var poiFeatures = [];
    
    // accessing hotel list container:
    webgisApp.hotelContainer = jQuery('#list-of-hotels div.main');
    // generating hotel list
    webgisApp.hotelContainer.append('<ul>');
    webgisApp.hotelList = webgisApp.hotelContainer.find('ul');
    
    var prev_lon = null;
    var prev_lat = null;
    var this_lon = null;
    var this_lat = null;
    var next_lon = null;
    var next_lat = null;
    
    webgisApp.addFirstLastMarkers(reiserouten_data.days);
    
    jQuery.each(reiserouten_data.days, function(i, day){
        if (!empty(day.hotel) && !empty(day.hotel.lon) && !empty(day.hotel.lat)) {
            this_lon = day.hotel.lon;
            this_lat = day.hotel.lat;
        } else {
            this_lon = null;
            this_lat = null;
        }
        
        var nextRoutePoint = reiserouten_data.days[ i+1 ];
        if (!empty(nextRoutePoint) && !empty(nextRoutePoint.hotel) && !empty(nextRoutePoint.hotel.lon) && !empty(nextRoutePoint.hotel.lat)) {
            next_lon = nextRoutePoint.hotel.lon;
            next_lat = nextRoutePoint.hotel.lat;
        } else {
            next_lon = null;
            next_lon = null;
        }
        
        if (!empty(day.hotel) && !empty(day.hotel.name)) {
            // adding hotel list-item
            // var $hotel_li = jQuery('<li class="ui-state-default ui-corner-all" onclick="webgisApp.zoomToRoutePart(' + prev_lon + ', ' + prev_lat + ', ' + this_lon + ', ' + this_lat + ', ' + next_lon + ', ' + next_lat + ');" onmouseover="webgisApp.addHighlightPoint(' + day.hotel.lon + ', ' + day.hotel.lat + ');" onmouseout="webgisApp.removeHighlightPoints();">Tag ' + day.day + ': ' + day.hotel.name + '</li>');
            
            var $hotel_li = webgisApp.getHotelListItem(day, {prev_lon: prev_lon, prev_lat: prev_lat, this_lon: this_lon, this_lat: this_lat, next_lon: next_lon, next_lat: next_lat});
            webgisApp.hotelList.append($hotel_li);
        }
        
        if (!empty(day.hotel) && !empty(day.hotel.lon) && !empty(day.hotel.lat) && !empty(day.hotel.name)) {
            // adding hotel feature
            var hotelGeometry = new OpenLayers.Geometry.Point(day.hotel.lon, day.hotel.lat);
            hotelGeometry = webgisApp.proj.lonlat2google(hotelGeometry);
            var hotelData = {
                'name': day.hotel.name,
                'title': (day.day && day.hotel.name) ? 'Tag ' + day.day + ': ' + day.hotel.name : (day.hotel.name) ? day.hotel.name : '',
                'url': day.hotel.url || '',
                'thumb': day.hotel.thumb || '',
                'day': day.day || '',
                'type' : 'hotel',
                'primaryColor' : webgisApp.vectorcolors.hotel.primary,
                'secondaryColor' : webgisApp.vectorcolors.hotel.secondary,
                'lon': day.hotel.lon,
                'lat': day.hotel.lat
            };
            var hotelFeature = new OpenLayers.Feature.Vector(hotelGeometry, hotelData);
            hotelFeatures.push(hotelFeature);
            routePoints.push(hotelGeometry.clone());
            // adding poi features
            if (!empty(day.pois)){
                jQuery.each(day.pois, function(ii, poi){
                    if (!empty(poi.lon) && !empty(poi.lat) && !empty(poi.name)) {
                        var poiGeometry = new OpenLayers.Geometry.Point(poi.lon, poi.lat);
                        poiGeometry = webgisApp.proj.lonlat2google(poiGeometry);
                        var poiData = {
                            'name': poi.name,
                            'url': poi.url || '',
                            'title': (day.day && poi.name) ? 'Tag ' + day.day + ': ' + poi.name : (poi.name) ? poi.name : '',
                            'thumb': poi.thumb || '',
                            'belongsToDay' : day.day,
                            'belongsToHotel' : day.hotel.name,
                            'type' : 'poi',
                            'primaryColor' : webgisApp.vectorcolors.poi.primary,
                            'secondaryColor' : webgisApp.vectorcolors.poi.secondary,
                            'lon': poi.lon,
                            'lat': poi.lat
                        };
                        var poiFeature = new OpenLayers.Feature.Vector(poiGeometry, poiData);
                        poiFeatures.push(poiFeature);
                    }
                });
            }
        }
        
        // Wenn mehrtägiger Aufenthalt, dann
        // stay gesetzt:
        if (!empty(day.hotel) && !empty(day.hotel.name) && !empty(day.stay) && day.stay.length && day.stay.length > 0) {
            jQuery.each(day.stay, function (iii, stayDay) {
                // adding hotel list-item
                // var $hotel_li = jQuery('<li class="ui-state-default ui-corner-all" onclick="webgisApp.zoomToRoutePart(' + prev_lon + ', ' + prev_lat + ', ' + this_lon + ', ' + this_lat + ', ' + next_lon + ', ' + next_lat + ');" onmouseover="webgisApp.addHighlightPoint(' + day.hotel.lon + ', ' + day.hotel.lat + ');" onmouseout="webgisApp.removeHighlightPoints();">Tag ' + stayDay.day + ': ' + day.hotel.name + '</li>');
                
                var $hotel_li = webgisApp.getHotelListItem(stayDay, {prev_lon: prev_lon, prev_lat: prev_lat, this_lon: this_lon, this_lat: this_lat, next_lon: next_lon, next_lat: next_lat});
                webgisApp.hotelList.append($hotel_li);
            
                // adding poi features
                if (!empty(stayDay.pois)){
                    jQuery.each(stayDay.pois, function(iiii, stayDayPoi){
                        if (!empty(stayDayPoi.lon) && !empty(stayDayPoi.lat) && !empty(stayDayPoi.name)) {
                            var stayDayPoiGeometry = new OpenLayers.Geometry.Point(stayDayPoi.lon, stayDayPoi.lat);
                            stayDayPoiGeometry = webgisApp.proj.lonlat2google(stayDayPoiGeometry);
                            var stayDayPoiData = {
                                'name': stayDayPoi.name,
                                'title': (stayDay.day && stayDayPoi.name) ? 'Tag ' + stayDay.day + ': ' + stayDayPoi.name : (stayDayPoi.name) ? stayDayPoi.name : '',
                                'url': stayDayPoi.url || '',
                                'thumb': stayDayPoi.thumb || '',
                                'belongsToDay' : stayDay.day,
                                'belongsToHotel' : day.hotel.name,
                                'type' : 'poi',
                                'primaryColor' : webgisApp.vectorcolors.poi.primary,
                                'secondaryColor' : webgisApp.vectorcolors.poi.secondary,
                                'lon': stayDayPoi.lon,
                                'lat': stayDayPoi.lat
                            };
                            var stayDayPoiFeature = new OpenLayers.Feature.Vector(stayDayPoiGeometry, stayDayPoiData);
                            poiFeatures.push(stayDayPoiFeature);
                        }
                    });
                }
            });
        }
        
        if (!empty(this_lon) && !empty(this_lat)) {
            prev_lon = this_lon;
            prev_lat = this_lat;
        } else {
            prev_lon = null;
            prev_lat = null;
        }
        
    });
    hotels_lyr.addFeatures(hotelFeatures);
    var uniquePoiFeatures = webgisApp.filterUniqueFeatures(poiFeatures, ['lon', 'lat']);
    pois_lyr.addFeatures( uniquePoiFeatures );
    // add route
    if (routePoints.length > 2) {
        var routeFeature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString( routePoints ), {name: 'Route'});
        route_lyr.addFeatures([routeFeature]);
    }
    
    webgisApp.drawArrows(routeDirections_lyr, hotelFeatures);
    
    // webgisApp.hotelList.after('<div class="vertical-placeholder">&nbsp;</div>')
               
    // webgisApp.hotelContainer.find('li:odd').addClass('terrestris-item-odd');
    // hotel list shall be in a floating window
    // alert(jQuery(document.body).height()-heightHotelContainer - marginHotelContainer);
    var x_pos = (jQuery(document.body).width()-widthHotelContainer-marginHotelContainer);
    var y_pos = (jQuery.browser.msie && jQuery.browser.version == '6.0') ? marginHotelContainer : (jQuery(document.body).height()-heightHotelContainer-marginHotelContainer);
    
    webgisApp.hotelContainer.parent().dialogr({
        width: widthHotelContainer,
        height: heightHotelContainer,
        title: 'Ihre Reiseroute:',
        position: [x_pos, y_pos],
        closeOnEscape: false,
        resizable: false,
	maximized: false
    });
    webgisApp.hotelContainer.parent().parent().find('.ui-dialog-titlebar-close').remove();
    // jQuery.unblockUI();
};
/**
 * Filter Feature Objekte und gibt nur unique Features als array zurück.
 * Eindeutigkeit wird durch das data attribut und der übergebenen Schlüssel festgelegt
 * @param {Array[OpenLayers.Feature.Vector]} features
 * @param {Object} uniquenessDefinedBy
 */
webgisApp.filterUniqueFeatures = function(features, uniquenessDefinedBy) {
    var compareStrings = [];
    var uniqueFeatures = [];
    var glue = '_';
    jQuery.each( features, function(i, feature){
        var compareString = '';
        var compareParts = [];
        jQuery.each(uniquenessDefinedBy, function(ii, uniquenessDefiner) {
            //feature.data[ uniquenessDefiner ]
            compareParts.push( feature.data[ uniquenessDefiner ] );
        });
        compareString = compareParts.join(glue);
        if (jQuery.inArray(compareString, compareStrings) === -1) {
            compareStrings.push(compareString);
            uniqueFeatures.push(feature.clone());   
        } 
    });
    return uniqueFeatures;
};
/**
 * Der click (onclick) handler 
 * @param {OpenLayers.Feature.Vector} feature
 */           
webgisApp.selectFeatureByClickHandler = function(feature){
    // wir müssen hier alle features wieder deselktieren,
    // da sonst der Click handler nur einmalig aufgerufen wird
    var ctrls = webgisApp.map.getControlsByClass('OpenLayers.Control.SelectFeature');
    if (ctrls && ctrls.length === 1) {
        var ctrl = ctrls[0];
    }
    ctrl.unselectAll();
    webgisApp.openMoreInformationPopup(feature.data.url);
};

/**
 * Der hover (mouseover) handler
 * @param {OpenLayers.Feature.Vector} feature
 * @param {OpenLayers.Event} evt
 */
webgisApp.selectFeatureByHoverHandler = function(feature, evt){
    if (webgisApp.hoverPopup && webgisApp.map && webgisApp.map.popups && webgisApp.map.popups.length > 0) {
        window.clearTimeout(webgisApp.hoverPopupAutoDestroyTO);
        webgisApp.hoverPopup.destroy();
        webgisApp.hoverPopup = null;
    }
    // Positionierung wie folgt:
    //  1) Popuop an linke obere ecke der Karte hängen,
    //  2) PixelOffset aus Event lesen
    //  3) Popup um den Betrag in X / Y verschieben
    var mapExtent = webgisApp.map.getExtent();
    var window_position = new OpenLayers.LonLat(mapExtent.left, mapExtent.top);
    var anchor = {
        size: new OpenLayers.Size(0, 0),
        offset:  evt.xy
    };
    webgisApp.hoverPopup = new OpenLayers.Popup.FramedCloud("ol-hoverinfo-popup", window_position, null, '<div class="map-kurzinfo-popup"><strong>' + feature.data.name + '</strong><br><span class="poi-more-information" onclick="webgisApp.openMoreInformationPopup(\'' + feature.data.url + '\')">weitere Informationen</span></div>',anchor, false);
    webgisApp.hoverPopup.autoSize = true;
    webgisApp.map.addPopup(webgisApp.hoverPopup, true);
    webgisApp.hoverPopupAutoDestroyTO = window.setTimeout(function(){
        if (webgisApp.map && webgisApp.map.popups && webgisApp.map.popups.length > 0) {
            var len = webgisApp.map.popups.length;
            for (var i = 0; i < len; i++) {
                if (webgisApp.map.popups[i] && webgisApp.map.popups[i].destroy) {
                    webgisApp.map.popups[i].destroy();
                }
            }
        }
    }, 3000);
};

/**
 * Zeichnet ein Highlight-Feature
 * @param {Number} lon
 * @param {Number} lat
 */
webgisApp.addHighlightPoint = function(lon, lat){
    var geometry = new OpenLayers.Geometry.Point(lon, lat);
    geometry = webgisApp.proj.lonlat2google(geometry);
    var data = {};
    var feature = new OpenLayers.Feature.Vector(geometry, data);
    webgisApp.highlightVectorLayer.addFeatures([feature]);
};
/**
 * entfernt alle temporären Highlight Features
 */
webgisApp.removeHighlightPoints = function() {
    jQuery.each(webgisApp.highlightVectorLayer.features, function(i, feature) {
        webgisApp.highlightVectorLayer.removeFeatures(feature);
    });
};


/**
 * dezentriert übergebene Bounds, so dass der 
 * östlichste Punkt im Zentrum der neuen Bounds ist
 * @param {OpenLayers.Bounds} bounds
 */
webgisApp.decenterBounds = function(bounds) {
    //log('original bounds: ' + bounds.toString());
    var width = bounds.getWidth();
    //log('width: ' + width);
    var delta = (width/3);
    //log('delta: ' + delta);
    var decentered_bounds = new OpenLayers.Bounds(bounds.left - delta, bounds.bottom, bounds.right + (delta*8), bounds.top);
    //xlog('decentered bounds: ' + decentered_bounds.toString());
    return decentered_bounds;
};            
/**
 * Offnet den Dialog mit der weitere Info URL im Iframe 
 * @param {String} url
 */
webgisApp.openMoreInformationPopup = function(url) {
    if (typeof webgisApp.moreDetailsDialog === 'undefined') {
        webgisApp.moreDetailsDialog = jQuery('<div></div>');
        var $body = jQuery( document.body );
        var margin = 100;
        webgisApp.moreDetailsDialog.append('<iframe name="details" src="' + url + '" width="808" height="97%" style="border: none; margin: 0px auto;">');
        webgisApp.moreDetailsDialog.dialog({
    		bgiframe: true,
            width: 810,
            height: $body.height() - margin,
    		modal: true,
            resizable: false
    	});
        webgisApp.moreDetailsDialog.parent().attr('id', 'more-details-window');
    } else {
        webgisApp.moreDetailsDialog.find('iframe').attr('src', url).end().end();
        webgisApp.moreDetailsDialog.dialog('open');
    }
};
/**
 * Zoomt je nach angeglicktem Punkt auf einen Teil der Route (vorheriger / nächster Punkt)
 * @param {Number} lon1 (vorheriger Punkt)
 * @param {Number} lat1 (vorheriger Punkt)
 * @param {Number} lon2 (aktueller Punkt)
 * @param {Number} lat2 (aktueller Punkt)
 * @param {Number} lon3 (nächster Punkt)
 * @param {Number} lat3 (nächster Punkt)
 */
webgisApp.zoomToRoutePart = function(lon1, lat1, lon2, lat2, lon3, lat3) {
    var bounds = new OpenLayers.Bounds();
    if (!empty(lon1) && !empty(lat1)) {
        bounds.extend(new OpenLayers.LonLat(lon1, lat1));
    }
    if (!empty(lon2) && !empty(lat2)) {
        bounds.extend(new OpenLayers.LonLat(lon2, lat2));
    }
    if (!empty(lon3) && !empty(lat3)) {
        bounds.extend(new OpenLayers.LonLat(lon3, lat3));
    }
    if (bounds.getWidth() > 0 && bounds.getHeight() > 0) {
        bounds = webgisApp.proj.lonlat2google(bounds);
        bounds = webgisApp.decenterBounds(bounds);
        webgisApp.map.zoomToExtent(bounds);
    } else {
        error('Could not zoom to routepart since bounds had illegal dimensions.');
    }
};
/**
 * Zeichnet die Richtungspfeile
 * @param {OpenLayers.Layer.Vector} Ziellayer für Pfeile
 * @param {Array[OpenLayers.Feature.Vector]} hotelFeatures (werden für anfangs-/ endpunkte verwendet)
 */
webgisApp.drawArrows = function(layer, hotelFeatures) {
    var directionFeatures = [];
    jQuery.each(hotelFeatures, function(i, feature) {
        var p1, p2, line, arrow, centerOfArrow, angle;
        p1 = new OpenLayers.Geometry.Point(hotelFeatures[i].geometry.x, hotelFeatures[i].geometry.y);
        if (!empty(hotelFeatures[i + 1])) {
            p2 = new OpenLayers.Geometry.Point(hotelFeatures[i + 1].geometry.x, hotelFeatures[i + 1].geometry.y);
            line = new OpenLayers.Geometry.LineString([p1, p2]);
            angle = line.getRotationAngle();
            directionFeature = new OpenLayers.Feature.Vector(line.getCentroid(), {
                'angle': angle
            });
            directionFeatures.push(directionFeature);
        }
    });
    layer.addFeatures(directionFeatures);
};

