﻿/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is VisKort.
*
* The Initial Developer of the Original Code is
* IT- og Telestyrelsen / Danish National IT and Telecom Agency.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):

* Lars Klindt Mogensen
* Morten Bødtkjer
* Niels Kinnerup
* Thomas Bergstedt
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */

/// <reference path="OpenLayers.js"/>

var infoPopup = null;

OpenLayers.Control.InfoBox = OpenLayers.Class(OpenLayers.Control, {
    HEADERTEXT_LOADING: "Henter information...",
    HEADERTEXT_LOADED: "<b>Info om:</b>",
    HEADERTEXT_INFO_ABOUT: "Info om: ",
    HEADERTEXT_BACKLINK: "Gå tilbage",
    HEADERTEXT_ROUTEPLANNING1: "Nærmeste adresse til udpegede sted er:",
    HEADERTEXT_ROUTEPLANNING2: "",

    TEXT_NO_DATA: " (ingen data)",
    TEXT_NO_DATA_LONGTEXT: "Ingen information på udpegede sted",

    defaultHandlerOptions: {
        'single': true,
        'double': false,
        'pixelTolerance': 0,
        'stopSingle': false,
        'stopDouble': false
    },

    infoContainerDiv: null,

    ignoreMapClickOnce: false,

    selectList: null,

    selectListHeader: null,

    linkContainer: null,

    layerInfoBody: null,

    layerInfoHeader: null,

    info: null,

    info: null,

    key: null,

    qs: null,

    regex: null,

    getFcount: null,

    UseAdvInfobox: null,

    infoCount: 0,

    infoLoadedCount: 0,

    linkGenerators: null,

    infoBoxArea: null,

    infoBoxSettings: null,

    infoBoxThemeMode: null,

    initialize: function (options, infoBoxArea, linkGenerators, infoBoxSettings) {
        this.infoBoxArea = infoBoxArea;
        this.linkGenerators = linkGenerators;
        this.infoBoxSettings = infoBoxSettings;
        OpenLayers.Control.prototype.initialize.apply(this, arguments);
    },

    getQuerystring: function(key, default_) {

        if (default_ == null) default_ = "";
        key = key.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
        var regex = new RegExp("[\\?&]" + key + "=([^&#]*)");
        var qs = regex.exec(window.location.href);
        if (qs == null)
            return default_;
        else
            return qs[1];
    },

    activate: function () {
        this.UseAdvInfobox = this.getQuerystring('UseAdvInfobox');
        this.handlerOptions = OpenLayers.Util.extend(
                            {}, this.defaultHandlerOptions
                        );

        if (this.UseAdvInfobox != "") {
            if (this.UseAdvInfobox == "true") {
                this.handler = new OpenLayers.Handler.Click(
                            this, {
                                'click': this.advancedTrigger
                            }, this.handlerOptions
                        );
            }
            else {
                this.handler = new OpenLayers.Handler.Click(
                            this, {
                                'click': this.trigger
                            }, this.handlerOptions
                        );
            }

        }

        else {
            if (this.infoBoxSettings && this.infoBoxSettings.InfoBox.Advanced) {
                this.handler = new OpenLayers.Handler.Click(
                            this, {
                                'click': this.advancedTrigger
                            }, this.handlerOptions
                        );
            }
            else {
                this.handler = new OpenLayers.Handler.Click(
                            this, {
                                'click': this.trigger
                            }, this.handlerOptions
                        );
            }
        }
        OpenLayers.Control.prototype.activate.apply(this, arguments);
    },

    /* Event: trigger
    * Event that's triggeret when the map is clicked
    * Creates a default infobox with info for the activelayers
    * and an address and routelink from this point.
    */
    trigger: function(e) {

        /*TO GET THE QUERYSTRING PARAMETER*/
        getFcount = this.getQuerystring('GetFeatureCount');
        UseAdvInfobox = this.getQuerystring('UseAdvInfobox');

        /* Close infoPopup if created */
        if (infoPopup != null)
            this.onPopupClose();

        /* Get clicked lonlat */
        var xy = e.xy;
        var lonlat = this.map.getLonLatFromViewPortPx(xy);
        var reverseGeocodedLonLat = lonlat;

        if (viskort.applicationModeGlobal) {
            reverseGeocodedLonLat = viskort.convertLonLat(lonlat, 'EPSG:102113', 'EPSG:25832');
        }

        // Used for info marker on print page
        var info_icon = document.getElementById("print_info_icon");
        if (info_icon) {
            info_icon.innerHTML = lonlat.lon + ":" + lonlat.lat;
        }

        /* Check for point inside clickable area*/
        var lonlatPoint = new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat);
        if (this.infoBoxArea && (!this.infoBoxArea.intersects(lonlatPoint)))
            return;

        var layers = this.map.layers;

        this.info = new Array(layers.length);
        this.infoCount = 0;
        this.infoLoadedCount = 0;

        this.infoContainerDiv = document.createElement("div");
        this.infoContainerDiv.className = this.displayClass + "_container";

        this.selectListHeader = document.createElement("div");
        this.selectListHeader.className = this.displayClass + "_header";
        this.selectListHeader.innerHTML = this.HEADERTEXT_LOADING;

        this.selectList = document.createElement("div");
        this.selectList.className = this.displayClass + "_list";

        this.layerInfoHeader = document.createElement("div");
        this.layerInfoHeader.className = this.displayClass + "_header";

        this.layerInfoBody = document.createElement("div");
        this.layerInfoBody.className = this.displayClass + "_detail";

        this.linkContainer = document.createElement("div");
        this.linkContainer.className = this.displayClass + "_linkContainer";

        this.infoContainerDiv.appendChild(this.linkContainer);

        this.infoContainerDiv.appendChild(this.layerInfoHeader);
        this.infoContainerDiv.appendChild(this.layerInfoBody);

        // Init adresse and travelplan
        if (this.infoBoxSettings.InfoBox.Address) {
            if (this.linkGenerators) {
                var services = new VisKort.Utils.Services();
                services.reverseGeocodeLonlat(reverseGeocodedLonLat, this.addRouteplanningLinks.bind(this));
            }
        }

        this.layerInfoHeader.style.display = "none";
        this.layerInfoBody.style.display = "none";

        this.infoBoxThemeMode = viskort.infoBoxThemeMode;

        var featureCount = 1;
        if (this.infoBoxSettings.InfoBox.GetFeaturesCount) {
            featureCount = this.infoBoxSettings.InfoBox.GetFeaturesCount;
        }

        for (var i = 0; i < layers.length; i++) {

            // Check for specific layer getFeatureCount
            var getfeaturesLayer = 0;
            if (layers[i].options.extra != null) {
                if (layers[i].options.extra.getfeature) {
                    getfeaturesLayer = layers[i].options.extra.getfeature;
                }
            }
            else {
                if (getFcount == "") {
                    getfeaturesLayer = this.infoBoxSettings.InfoBox.GetFeaturesCount;
                }
                else {
                    getfeaturesLayer = getFcount;
                }
            }

            if (layers[i].visibility && ((layers[i].CLASS_NAME == "OpenLayers.Layer.WMS") || (layers[i].CLASS_NAME == "OpenLayers.Layer.WMS.Untiled")) &&
                    layers[i].options.extra != null && layers[i].options.extra.infoBoxLayout != null) {

                var infoformat = (layers[i].params.INFO_FORMAT != null ? layers[i].params.INFO_FORMAT : 'text/xml');
                // set max tolerance if specified inside layers properties
                var tol = 0.1;
                if (layers[i].options.extra.maxTolerance != null)
                    tol = layers[i].options.extra.maxTolerance;
                var tolerance = tol * (this.map.getNumZoomLevels() - this.map.getZoom());
                // set max tolerance to default 5
                if (tolerance > 100)
                    tolerance = 100;
                var url = layers[i].getFullRequestString({
                    REQUEST: "GetFeatureInfo",
                    BBOX: (this.infoBoxThemeMode == 'atkmode') ? (this.map.getExtent().toBBOX()) : (new OpenLayers.Bounds(lonlatPoint.x - tolerance, lonlatPoint.y - tolerance, lonlatPoint.x + tolerance, lonlatPoint.y + tolerance).toBBOX()),
                    X: (this.infoBoxThemeMode == 'atkmode') ? Math.round(xy.x) : 1,
                    Y: (this.infoBoxThemeMode == 'atkmode') ? Math.round(xy.y) : 1,
                    QUERY_LAYERS: layers[i].params.LAYERS,
                    INFO_FORMAT: (this.infoBoxThemeMode == 'atkmode') ? 'text/plain' : infoformat,
                    FEATURE_COUNT: getfeaturesLayer != "" ? getfeaturesLayer : featureCount,
                    EXCEPTIONS: 'application/vnd.ogc.se_xml',
                    WIDTH: (this.infoBoxThemeMode == 'atkmode') ? this.map.size.w : 3,
                    HEIGHT: (this.infoBoxThemeMode == 'atkmode') ? this.map.size.h : 3
                });

                var layerInfoLink = document.createElement("div");
                layerInfoLink.className = this.displayClass + "_listElement";
                layerInfoLink.innerHTML = layers[i].name;

                this.info[this.infoCount] = { layer: layers[i], infoUrl: url, infoHtml: 'Loading...', parentLink: layerInfoLink };
                this.infoCount++;

                this.selectList.appendChild(layerInfoLink);
            } else if (layers[i].visibility && (layers[i].CLASS_NAME == "OpenLayers.Layer.ArcGIS93Rest") &&
                    layers[i].options.extra != null && layers[i].options.extra.infoBoxLayout != null &&
                    layers[i].params.LAYERS != null) {

                var baseUrl = layers[i].url.substring(0, layers[i].url.indexOf("/MapServer/export"));
                var tolerance = this.map.getNumZoomLevels() - this.map.getZoom();
                // set max tolerance to default 5
                if (tolerance > 5)
                    tolerance = 5;

                // set max tolerance if specified inside layers properties
                if (layers[i].options.extra.maxTolerance != null &&
			        tolerance > layers[i].options.extra.maxTolerance)
                    tolerance = layers[i].options.extra.maxTolerance;

                var url = baseUrl + "/MapServer/identify?f=json&" +
                	"geometry={x:" + lonlatPoint.x + ",y:" + lonlatPoint.y + ",spatialReference:{wkid:102113}}&" +
                	"spatialReference=102113&tolerance=" + tolerance + "&returnGeometry=false&" +
                	"mapExtent={xmin:" + this.map.getExtent().left + ",ymin:" + this.map.getExtent().bottom + ",xmax:" + this.map.getExtent().right + ",ymax:" + this.map.getExtent().top + ",spatialReference:{wkid:102113}}&" +
                	"imageDisplay=400,400,96&geometryType=esriGeometryPoint&sr=102113&layers=" + layers[i].params.LAYERS.replace("show:", "all:") +
                	"&callback=viskort._jsonpCallback";

                var layerInfoLink = document.createElement("div");
                layerInfoLink.className = this.displayClass + "_listElement";
                layerInfoLink.innerHTML = layers[i].name;

                this.info[this.infoCount] = { layer: layers[i], infoUrl: url, infoHtml: 'Loading...', parentLink: layerInfoLink };
                this.infoCount++;

                this.selectList.appendChild(layerInfoLink);
            } else if (layers[i].visibility && (layers[i].CLASS_NAME == "OpenLayers.Layer.TMS") &&
                    layers[i].lyr != null && layers[i].lyr == "com.panoramio.all") {
                // google panoramio (picture) layer
                var deltaX = Math.abs(this.map.getExtent().left - this.map.getExtent().right) / 200;
                var deltaY = Math.abs(this.map.getExtent().top - this.map.getExtent().bottom) / 200;
                var newExtent = new OpenLayers.Bounds(lonlatPoint.x + deltaX, lonlatPoint.y + deltaY,
                                                        lonlatPoint.x - deltaX, lonlatPoint.y - deltaY);
                viskort.kmlReverseTransformGeometry(newExtent);
                var url = "http://www.panoramio.com/map/get_panoramas.php?order=popularity&set=public&" +
                              "from=0&to=1" +
                              "&minx=" + newExtent.right +
                              "&miny=" + newExtent.top +
                              "&maxx=" + newExtent.left +
                              "&maxy=" + newExtent.bottom +
                              "&size=thumbnail" +
                              "&callback=viskort._jsonpCallback";
                var layerInfoLink = document.createElement("div");
                layerInfoLink.className = this.displayClass + "_listElement";
                layerInfoLink.innerHTML = layers[i].name;

                this.info[this.infoCount] = { layer: layers[i], infoUrl: url, infoHtml: 'Loading...', parentLink: layerInfoLink };
                this.infoCount++;

                this.selectList.appendChild(layerInfoLink);
            }
            else if (layers[i].visibility && (layers[i].CLASS_NAME == "OpenLayers.Layer.TMS") &&
                    layers[i].lyr != null && layers[i].lyr == "com.google.webcams") {
                // google webcam layer
                viskort.kmlReverseTransformGeometry(lonlatPoint);
                var url = "http://api.webcams.travel/rest?method=wct.webcams.list_nearby" +
                            "&unit=deg&format=json&radius=0.1" +
                            "&lat=" + lonlatPoint.y +
                            "&lng=" + lonlatPoint.x +
                            "&devid=997af535c03874f2c1a32e46fccf492b" +
                            "&callback=viskort._jsonpCallback";
                var layerInfoLink = document.createElement("div");
                layerInfoLink.className = this.displayClass + "_listElement";
                layerInfoLink.innerHTML = layers[i].name;

                this.info[this.infoCount] = { layer: layers[i], infoUrl: url, infoHtml: 'Loading...', parentLink: layerInfoLink };
                this.infoCount++;

                this.selectList.appendChild(layerInfoLink);
            }
            else if (layers[i].visibility && (layers[i].CLASS_NAME == "OpenLayers.Layer.TMS") &&
                    layers[i].url != null && layers[i].url.indexOf("cbk0.google.com/cbk") > -1) {
                // google streetview layer
                viskort.kmlReverseTransformGeometry(lonlatPoint);
                var url = "http://maps.google.dk/cbk?output=xml" +
                            "&ll=" + lonlatPoint.y + "," + lonlatPoint.x +
                            "&cb_client=maps_sv";
                var layerInfoLink = document.createElement("div");
                layerInfoLink.className = this.displayClass + "_listElement";
                layerInfoLink.innerHTML = layers[i].name;

                this.info[this.infoCount] = { layer: layers[i], infoUrl: url, infoHtml: 'Loading...', parentLink: layerInfoLink };
                this.infoCount++;

                this.selectList.appendChild(layerInfoLink);
            }
            else if (layers[i].visibility && (layers[i].CLASS_NAME == "OpenLayers.Layer.KML")) {
                // google streetview layer
                viskort.kmlReverseTransformGeometry(lonlatPoint);
                var url = "http://maps.google.dk/cbk?output=xml" +
                            "&ll=" + lonlatPoint.y + "," + lonlatPoint.x +
                            "&cb_client=maps_sv";
            }
        }

        var containerHeight = 90;
        if (this.infoCount > 0) {
            this.infoContainerDiv.appendChild(this.selectListHeader);
            this.infoContainerDiv.appendChild(this.selectList);

            containerHeight += 16;
            containerHeight += Math.min(this.infoCount, 3) * 20;
        }

        this.infoContainerDiv.style.height = containerHeight + "px";

        var tempContainer = document.createElement("div");
        tempContainer.appendChild(this.infoContainerDiv);
        infoPopup = new OpenLayers.Popup.FramedCloud("Info",
                           lonlat,
                           new OpenLayers.Size(200, 200),
                           tempContainer.innerHTML,
                           null, true, this.onPopupClose.bind(this));
        infoPopup.imageSrc = OpenLayers.Util.getImagesLocation() + 'cloud-popup-relative.gif';

        this.adjustInfoPopupBounds(infoPopup);

        this.map.addPopup(infoPopup);

        infoPopup.contentDiv.replaceChild(tempContainer, infoPopup.contentDiv.firstChild);

        if (this.infoBoxThemeMode == 'atkmode') {
            if (this.infoCount > 0) {
                for (var i = 0; i < this.infoCount; i++) {
                    var request = new OpenLayers.Ajax.Request(this.info[i].infoUrl,
		                      { method: 'get', parameters: { InfoIdx: i },
		                          onComplete: this.onInfoResponse.bind(this), onFailure: OpenLayers.nullHandler
		                      });
                }
            }
            else
                this.selectListHeader.innerHTML = "";
        }
        else {
            if (this.infoCount > 0) {
                for (var i = 0; i < this.infoCount; i++) {
                    var url = this.info[i].infoUrl;
                    var u = "viskort.onInfoCallBack('" + url + "', '" + i + "');";
                    setTimeout(u, 0);

                }
                this.idCount = 0;
            }
            else
                this.selectListHeader.innerHTML = "";
        }
    },

    /**
    * Event: advancedTrigger 
    *
    */
    advancedTrigger: function(e) {

        /*To get URL parameters*/
        getFcount = this.getQuerystring('GetFeatureCount');
        UseAdvInfobox = this.getQuerystring('UseAdvInfobox');
    
        /* Close infoPopup if created */
        if (infoPopup != null)
            this.onPopupClose();

        /* Get clicked lonlat */
        var xy = e.xy;
        var lonlat = this.map.getLonLatFromViewPortPx(xy);

        // Used for info marker on print page
        var info_icon = document.getElementById("print_info_icon");
        if (info_icon) {
            info_icon.innerHTML = lonlat.lon + ":" + lonlat.lat;
        }

        /* Check for point inside clickable area*/
        var lonlatPoint = new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat);
        if (this.infoBoxArea && (!this.infoBoxArea.intersects(lonlatPoint))) {
            return;
        }

        var layers = this.map.layers;
        this.info = new Array(layers.length);
        this.infoCount = 0;
        this.infoLoadedCount = 0;

        this.infoContainerDiv = document.createElement("div");
        this.infoContainerDiv.className = this.displayClass + "_Advancedcontainer";
        this.infoContainerDiv.id = "infoContainerDIVID";
  
        this.layerInfoHeader = document.createElement("div");
        this.layerInfoHeader.id = "advanceHeaderDIVID";

        this.layerInfoBody = document.createElement("div");
        this.layerInfoBody.className = this.displayClass + "_Advanceddetail";
        this.layerInfoBody.id = "addetailDIVID";
   
        this.linkContainer = document.createElement("div");
        this.linkContainer.className = this.displayClass + "_AdvancedlinkContianer";
        this.linkContainer.id = "adlinkConDIVID";

        this.infoContainerDiv.appendChild(this.linkContainer);

        this.infoContainerDiv.appendChild(this.layerInfoHeader);
        this.infoContainerDiv.appendChild(this.layerInfoBody);

        // Init adresse and travelplan
        if (this.infoBoxSettings.InfoBox.Address) {
            if (this.linkGenerators) {
                var services = new VisKort.Utils.Services();
                services.reverseGeocodeLonlat(lonlat, this.addRouteplanningLinks.bind(this));
            }
        }

        // default featureCount 1 
        var featureCount = 1;
        if (this.infoBoxSettings.InfoBox.GetFeaturesCount) {
            featureCount = this.infoBoxSettings.InfoBox.GetFeaturesCount;
        }

        for (var i = 0; i < layers.length; i++) {
            var getfeaturesLayer = 0;
            if (layers[i].options.extra != null && layers[i].options.extra.getfeature) {
                getfeaturesLayer = layers[i].options.extra.getfeature;
            }
            else {
                if (getFcount == "") {
                    getfeaturesLayer = this.infoBoxSettings.InfoBox.GetFeaturesCount;
                }
                else {
                    getfeaturesLayer = getFcount;
                }
            }
            if (layers[i].visibility && ((layers[i].CLASS_NAME == "OpenLayers.Layer.WMS") || (layers[i].CLASS_NAME == "OpenLayers.Layer.WMS.Untiled")) &&
                    layers[i].options.extra != null && layers[i].options.extra.infoBoxLayout != null) {
                var url = layers[i].getFullRequestString({
                    REQUEST: "GetFeatureInfo",
                    BBOX: this.map.getExtent().toBBOX(),
                    X: Math.round(xy.x),
                    Y: Math.round(xy.y),
                    QUERY_LAYERS: layers[i].params.LAYERS,
                    INFO_FORMAT: 'text/plain',
                    FEATURE_COUNT: getfeaturesLayer != "" ? getfeaturesLayer : featureCount,
                    WIDTH: this.map.size.w,
                    HEIGHT: this.map.size.h
                });

                var layerInfoLink = document.createElement("div");
                layerInfoLink.className = this.displayClass + "_AdvancedlistElement";
                layerInfoLink.innerHTML = layers[i].name;

                this.info[this.infoCount] = { layer: layers[i], infoUrl: url, infoHtml: 'Loading...', parentLink: layerInfoLink };
                this.infoCount++;

            }
        }

        var tempContainer = document.createElement("div");
        tempContainer.appendChild(this.infoContainerDiv);
        infoPopup = new OpenLayers.Popup.FramedCloud("Info",
                           lonlat,
                           new OpenLayers.Size(200, 200),
                           tempContainer.innerHTML,
                           null, true, this.onPopupClose.bind(this));
        infoPopup.imageSrc = OpenLayers.Util.getImagesLocation() + 'cloud-popup-relative.gif';

        this.adjustInfoPopupBounds(infoPopup);
        this.map.addPopup(infoPopup);

        infoPopup.contentDiv.replaceChild(tempContainer, infoPopup.contentDiv.firstChild);

        if (this.infoCount > 0) {
            for (var i = 0; i < this.infoCount; i++) {
                var request = new OpenLayers.Ajax.Request(this.info[i].infoUrl,
                                    { method: 'get', parameters: { InfoIdx: i },
                                        onComplete: this.onAdvancedInfoResponse.bind(this), onFailure: OpenLayers.nullHandler
                                    });
            }
        }
        else {
            this.onPopupClose(infoPopup);
        }
    },

    onAdvancedInfoResponse: function (response) {
        var idx = response.request.options.parameters.InfoIdx;
        var parentLink = this.info[idx].parentLink;

        var infoHtml;
        var listdata = "";
        if (response.responseText.indexOf('no features were found') != 0 && response.responseText != "" &&
            response.responseText.indexOf('Search returned no results') == -1) {
            var infoBoxLayout = this.info[idx].layer.options.extra.infoBoxLayout;
            if (infoBoxLayout["#cdata-section"] != null) {
                infoHtml = infoBoxLayout["#cdata-section"];
                var responseText = response.responseText;
                var lines = responseText.split('\n');
                var count = 0;
                for (lcv = 0; lcv < (lines.length); lcv++) {
                    var vals = lines[lcv].replace(/^\s*/, '').replace(/\s*$/, '').replace(/ = /, "=").replace(/=/, ":").replace(/'/g, '').split(':');
                    if (vals[0] != null && vals[0].length >= 1) {
                        var r = new RegExp("<!--#" + vals[0] + "#-->", 'gi');
                        var vl = vals[1];
                        if (vals.length > 2) {
                            for (var t = 2; t < vals.length; t++)
                                vl += ":" + vals[t];
                        }
                        infoHtml = infoHtml.replace(null, "");
                        infoHtml = infoHtml.replace(r, vl);

                        if (vals[0].indexOf("--------") != -1 && lcv != 1 && count == 0) {
                            listdata += infoHtml + "<br />";
                            infoHtml = infoBoxLayout["#cdata-section"];
                            count = 1;
                        } else {
                            count = 0;
                        }
                    }
                }
            }
            else {
                infoHtml = response.responseText;
            }
            OpenLayers.Event.observe(parentLink, "click",
                OpenLayers.Function.bindAsEventListener(this.onShowLayerInfo,
                                                        { infoBox: this, infoIdx: idx }));

            parentLink.className = this.displayClass + "_listElement_loaded";
        }
        else {
            // No data for this clicked location
            infoHtml = this.TEXT_NO_DATA_LONGTEXT;
            parentLink.className = this.displayClass + "_listElement_nodata";
            parentLink.innerHTML += this.TEXT_NO_DATA;
        }

        this.info[idx].infoHtml = listdata;

        // Set print info
        if (infoHtml != this.TEXT_NO_DATA_LONGTEXT) {
            var printinfo = "<br />" + infoHtml + "<br />";
            var util_instance = new VisKort.Utils();
            util_instance.AddToPrintdetail_infobox(printinfo);
        }

        this.infoLoadedCount++;

        if (this.infoLoadedCount == this.infoCount) {
            var headerLoad = document.getElementById("advanceHeaderDIVID");
            if (headerLoad) {
                headerLoad.innerHTML = "";
            }
            // Firefox fix
            var infoDiv = document.getElementById("Info_contentDiv");
            if (infoDiv) {
                infoDiv.style.overflowY = 'auto';
            }

            for (var i = 0; i < this.infoCount; i++) {
                if (this.info[i].infoHtml != "") {
                    this.layerInfoBody.innerHTML += "<div style='font-size:larger;'><b>" + this.info[i].layer.name + ":</b></div><br />";
                    this.layerInfoBody.innerHTML += this.info[i].infoHtml;
                }
                this.layerInfoBody.innerHTML += "<br />";
            }

            if (this.layerInfoBody.innerHTML == "") {
                if (infoDiv) {
                    infoDiv.style.overflowY = 'hidden';
                }
                this.layerInfoBody.innerHTML += this.TEXT_NO_DATA_LONGTEXT;
            }
            this.layerInfoHeader.scrollTop = "0px";

            if (navigator.appName.toLowerCase().match("microsoft internet explorer") && navigator.appVersion.toLowerCase().match("msie 7.0")) {
                this.infoContainerDiv.style.pixelHeight = "110px";
            }
        }
    },

    onInfoResponse: function (i, response) {
        // Test for atkins mode or geodata danmark
        if (this.infoBoxThemeMode == 'atkmode') {
            response = i;
            var idx = response.request.options.parameters.InfoIdx;
            var parentLink = this.info[idx].parentLink;
            //Search returned no results
            var infoHtml;
            if (response.responseText.indexOf('no features were found') != 0 && response.responseText != "" &&
	        response.responseText.indexOf('Search returned no results') == -1) {
                var infoBoxLayout = this.info[idx].layer.options.extra.infoBoxLayout;
                if (infoBoxLayout["#cdata-section"] != null) {
                    infoHtml = infoBoxLayout["#cdata-section"];
                    var responseText = response.responseText;
                    var lines = responseText.split('\n');
                    for (lcv = 0; lcv < (lines.length); lcv++) {
                        var vals = lines[lcv].replace(/^\s*/, '').replace(/\s*$/, '').replace(/ = /, "=").replace(/=/, ":").replace(/'/g, '').split(':');
                        if (vals[0] != null && vals[0].length >= 1) {
                            var r = new RegExp("<!--#" + vals[0] + "#-->", 'gi');
                            var vl = vals[1];
                            if (vals.length > 2) {
                                for (var t = 2; t < vals.length; t++)
                                    vl += ":" + vals[t];
                            }
                            infoHtml = infoHtml.replace(r, vl);
                        }
                    }
                }
                else
                    infoHtml = response.responseText;

                OpenLayers.Event.observe(parentLink, "click",
	            OpenLayers.Function.bindAsEventListener(this.onShowLayerInfo,
	            { infoBox: this, infoIdx: idx })
	            );
                parentLink.className = this.displayClass + "_listElement_loaded";
            }
            else {
                infoHtml = this.TEXT_NO_DATA_LONGTEXT;
                parentLink.className = this.displayClass + "_listElement_nodata";
                parentLink.innerHTML += this.TEXT_NO_DATA;
            }

            this.info[idx].infoHtml = infoHtml;

            // Set print info
            if (infoHtml != this.TEXT_NO_DATA_LONGTEXT) {
                var printinfo = "<br />" + infoHtml + "<br />";
                var util_instance = new VisKort.Utils();
                util_instance.AddToPrintdetail_infobox(printinfo);

            }

            this.infoLoadedCount++;

            if (this.infoLoadedCount == this.infoCount) {
                this.selectListHeader.innerHTML = this.HEADERTEXT_LOADED;
                //            if (this.infoCount == 1)
                //                this.showLayerInfo(0, false);
            }
        }
        else 
        {
            var parentLink = this.info[i].parentLink;
            //Search returned no results
            var infoHtml;
            if (response.getAllResponseHeaders().indexOf('Content-Type: text/plain') > 0 ||
             response.getAllResponseHeaders().indexOf('Content-Type: application/json') > 0) {
                var dataFound = false;
                var startStr = "viskort._jsonpCallback(";
                var jsonStartIndex = response.responseText.indexOf(startStr);

                var endStr = ");";
                var jsonEndIndex = response.responseText.indexOf(endStr);
                if (jsonEndIndex == -1) {
                    // special case for panoramio json response
                    endStr = "})";
                    jsonEndIndex = response.responseText.indexOf(endStr) + 1;
                }
                if (jsonStartIndex != -1) {
                    var infoBoxLayout = this.info[i].layer.options.extra.infoBoxLayout;
                    var linkLayer = this.info[i].layer.options.linkLayer;
                    // if one layers has been set with property linkLayer=true
                    // remove popup, and search attribute data for links,
                    // which is popped up in a new window
                    if (linkLayer != null && linkLayer == true) {
                        this.map.removePopup(infoPopup);
                    }
                    var linkLayer = this.info[i].layer.options.linkLayer;
                    if (infoBoxLayout["#cdata-section"] != null) {
                        var jsonStr = response.responseText.substring(jsonStartIndex + startStr.length, jsonEndIndex);
                        infoHtml = viskort.JSONparseAGSRestInfo(infoBoxLayout["#cdata-section"], jsonStr, linkLayer);
                        if (infoHtml.trim().length > 0 && infoHtml.indexOf("<!--#") == -1) {
                            // all replacement performed
                            dataFound = true;
                        }

                    }
                    else
                        infoHtml = response.responseText;

                    if (!dataFound) {
                        infoHtml = this.TEXT_NO_DATA_LONGTEXT;
                        parentLink.className = this.displayClass + "_listElement_nodata";
                        parentLink.innerHTML += this.TEXT_NO_DATA;
                    } else {
                        OpenLayers.Event.observe(parentLink, "click",
				OpenLayers.Function.bindAsEventListener(this.onShowLayerInfo,
					    { infoBox: this, infoIdx: i })
				);
                        parentLink.className = this.displayClass + "_listElement_loaded";
                    }


                }
                else if (response.responseText.indexOf('no features were found') != 0 && response.responseText != "" &&
			response.responseText.indexOf('Search returned no results') == -1) {
                    var infoBoxLayout = this.info[i].layer.options.extra.infoBoxLayout;
                    if (infoBoxLayout["#cdata-section"] != null) {
                        var infoHtmlTmp = infoBoxLayout["#cdata-section"];
                        infoHtml = "";
                        var responseText = response.responseText;
                        var lines = responseText.split('\n');
                        for (lcv = 0; lcv < (lines.length); lcv++) {
                            var vals = lines[lcv].replace(/^\s*/, '').replace(/\s*$/, '').replace(/ = /, "=").replace(/=/, ":").replace(/'/g, '').split(':');
                            if (vals[0] != null && vals[0].length >= 1) {
                                if (vals[0].toLowerCase() == 'the_geom') {
                                    // we started on a new feature
                                    infoHtml += infoHtmlTmp;
                                }
                                var r = new RegExp("<!--#" + vals[0] + "#-->", 'gi');
                                var vl = vals[1];
                                if (vals.length > 2) {
                                    for (var t = 2; t < vals.length; t++)
                                        vl += ":" + vals[t];
                                }
                                infoHtml = infoHtml.replace(r, vl);
                            }
                        }
                    }
                    else
                        infoHtml = response.responseText;

                    OpenLayers.Event.observe(parentLink, "click",
				    OpenLayers.Function.bindAsEventListener(this.onShowLayerInfo,
									    { infoBox: this, infoIdx: i })
				);
                    parentLink.className = this.displayClass + "_listElement_loaded";
                    //}
                } else {
                    infoHtml = this.TEXT_NO_DATA_LONGTEXT;
                    parentLink.className = this.displayClass + "_listElement_nodata";
                    parentLink.innerHTML += this.TEXT_NO_DATA;
                }
            }
            else if (response.getAllResponseHeaders().indexOf('Content-Type: text/xml') > 0) {
                var infoBoxLayout = this.info[i].layer.options.extra.infoBoxLayout;
                var dataFound = false;
                if (infoBoxLayout["#cdata-section"] != null) {
                    infoHtml = infoBoxLayout["#cdata-section"];
                    infoHtml = this.traverseXML(response.responseXML, infoHtml);
                    if (infoHtml.indexOf("<!--#") == -1) {
                        // replacement performed
                        dataFound = true;
                    }

                }
                else
                    infoHtml = response.responseText;

                if (!dataFound) {
                    infoHtml = this.TEXT_NO_DATA_LONGTEXT;
                    parentLink.className = this.displayClass + "_listElement_nodata";
                    parentLink.innerHTML += this.TEXT_NO_DATA;
                } else {
                    OpenLayers.Event.observe(parentLink, "click",
			OpenLayers.Function.bindAsEventListener(this.onShowLayerInfo,
							    { infoBox: this, infoIdx: i })
			);
                    parentLink.className = this.displayClass + "_listElement_loaded";
                }

            }
            else {
                infoHtml = this.TEXT_NO_DATA_LONGTEXT;
                parentLink.className = this.displayClass + "_listElement_nodata";
                parentLink.innerHTML += this.TEXT_NO_DATA;
            }

            this.info[i].infoHtml = infoHtml;

            // Set print info
            if (infoHtml != this.TEXT_NO_DATA_LONGTEXT) {
                var printinfo = "<br />" + infoHtml + "<br />";
                var util_instance = new VisKort.Utils();
                util_instance.AddToPrintdetail_infobox(printinfo);

            }

            this.infoLoadedCount++;

            if (this.infoLoadedCount == this.infoCount) {
                this.selectListHeader.innerHTML = this.HEADERTEXT_LOADED;
                //            if (this.infoCount == 1)
                //                this.showLayerInfo(0, false);
            }
        }
    },

    traverseXML: function (node, infoHtml) {
        var str = infoHtml;
        //alert("node.nodeName: " + node.nodeName);
        if (node.attributes != null) {
            //alert("node.attributes: " + node.attributes);
            //alert("node.attributes.length: " + node.attributes.length);
            for (var i = 0; i < node.attributes.length; ++i) {
                //alert("test: " + node.attributes[i].nodeName);
                if (infoHtml.indexOf("<!--#" + node.attributes[i].nodeName + "#-->") > 0) {
                    var r = new RegExp("<!--#" + node.attributes[i].nodeName + "#-->", 'gi');
                    str = str.replace(r, node.attributes[i].nodeValue);
                }
                else if (node.attributes[i].nodeName.toLowerCase() == 'name' &&
				        infoHtml.indexOf("<!--#" + node.attributes[i].nodeValue + "#-->") > 0) {
                    var r = new RegExp("<!--#" + node.attributes[i].nodeValue + "#-->", 'gi');
                    str = infoHtml.replace(r, node.attributes[i + 1].nodeValue);
                }
            }
            if (infoHtml.indexOf("<!--#" + node.nodeName + "#-->") > 0) {
                var r = new RegExp("<!--#" + node.nodeName + "#-->", 'gi');
                str = infoHtml.replace(r, node.text);
            }
        }
        if (node.hasChildNodes()) {
            var children = node.childNodes;
            for (var i = 0; i < children.length; ++i) {
                // break out, if no more replacements
                var r = new RegExp("<!--#.#-->", 'gi');
                if (str.indexOf("<!--#") < 0) {
                    return str;
                }
                str = this.traverseXML(children[i], str);
            }
        }


        return str;
    },

    traverseXML: function (node, infoHtml) {
        var str = infoHtml;
        //alert("node.nodeName: " + node.nodeName);
        if (node.attributes != null) {
            //alert("node.attributes: " + node.attributes);
            //alert("node.attributes.length: " + node.attributes.length);
            for (var i = 0; i < node.attributes.length; ++i) {
                //alert("test: " + node.attributes[i].nodeName);
                if (infoHtml.indexOf("<!--#" + node.attributes[i].nodeName + "#-->") > 0) {
                    var r = new RegExp("<!--#" + node.attributes[i].nodeName + "#-->", 'gi');
                    str = str.replace(r, node.attributes[i].nodeValue);
                }
                else if (node.attributes[i].nodeName.toLowerCase() == 'name' &&
				        infoHtml.indexOf("<!--#" + node.attributes[i].nodeValue + "#-->") > 0) {
                    var r = new RegExp("<!--#" + node.attributes[i].nodeValue + "#-->", 'gi');
                    str = infoHtml.replace(r, node.attributes[i + 1].nodeValue);
                }
            }
            if (infoHtml.indexOf("<!--#" + node.nodeName + "#-->") > 0) {
                var r = new RegExp("<!--#" + node.nodeName + "#-->", 'gi');
                str = infoHtml.replace(r, node.text);
            }
        }
        if (node.hasChildNodes()) {
            var children = node.childNodes;
            for (var i = 0; i < children.length; ++i) {
                // break out, if no more replacements
                var r = new RegExp("<!--#.#-->", 'gi');
                if (str.indexOf("<!--#") < 0) {
                    return str;
                }
                str = this.traverseXML(children[i], str);
            }
        }


        return str;
    },

    addRouteplanningLinks: function (address) {
        var addressTextDiv = document.createElement("div");
        addressTextDiv.className = this.displayClass + "_address";
        addressTextDiv.innerHTML = this.HEADERTEXT_ROUTEPLANNING1 + "<br/><b>" + address + "</b>"; // "<br/>" + this.HEADERTEXT_ROUTEPLANNING2 + "<br/>";
        this.linkContainer.appendChild(addressTextDiv);

        var styleClass;
        for (var i = 0; i < this.linkGenerators.length; i++) {
            styleClass = this.displayClass + "_linkGeneratorsStd";
            var linkGenerator = this.linkGenerators[i].getDivElement({ address: address }, styleClass);
            this.linkContainer.appendChild(linkGenerator);
        }
    },

    addRouteplanningLinksNoText: function (address) {
        var styleClass;
        for (var i = 0; i < this.linkGenerators.length; i++) {
            styleClass = this.displayClass + "_linkGeneratorsStd";
            var linkGenerator = this.linkGenerators[i].getDivElement({ address: address }, styleClass);
            this.linkContainer.appendChild(linkGenerator);
        }
    },

    showLayerInfo: function (infoIdx, includeBackLink) {
        this.selectList.style.display = "none";
        this.selectListHeader.style.display = "none";
        this.linkContainer.style.display = "none";

        this.layerInfoHeader.innerHTML = "";
        if (includeBackLink) {
            var backToListLink = document.createElement("a");
            backToListLink.setAttribute("title", "Tilbage");
            //backToListLink.innerHTML = this.HEADERTEXT_BACKLINK;
            OpenLayers.Event.observe(backToListLink, "click",
                        OpenLayers.Function.bindAsEventListener(this.onShowList,
                                                                { infoBox: this })
                    );
            this.layerInfoHeader.appendChild(backToListLink);
        }

        var layerInfoHeadline = document.createElement("b");
        layerInfoHeadline.innerHTML = this.info[infoIdx].layer.name;
        this.layerInfoHeader.appendChild(layerInfoHeadline);

        this.layerInfoBody.innerHTML = this.info[infoIdx].infoHtml;
        this.layerInfoBody.scrollTop = "0px";

        this.layerInfoHeader.style.display = "";
        this.layerInfoBody.style.display = "";
    },

    showList: function () {
        this.layerInfoHeader.style.display = "none";
        this.layerInfoBody.style.display = "none";

        this.selectListHeader.style.display = "";
        this.selectList.style.display = "";
        this.linkContainer.style.display = "";
    },

    onShowLayerInfo: function (e) {
        this.infoBox.showLayerInfo(this.infoIdx, true);
    },

    onShowList: function (e) {
        this.infoBox.showList();
    },

    showCustomInfo: function (lonlat, infoHtml) {
        if (infoPopup != null)
            this.onPopupClose();

        var customInfoDiv = document.createElement("div");
        customInfoDiv.className = this.displayClass + "_customInfo";
        customInfoDiv.innerHTML = infoHtml;

        var tempContainer = document.createElement("div");
        tempContainer.appendChild(customInfoDiv);

        infoPopup = new OpenLayers.Popup.FramedCloud("Info",
                       lonlat,
                       new OpenLayers.Size(200, 200),
                       tempContainer.innerHTML,
                       null, true, this.onPopupClose.bind(this));
        infoPopup.imageSrc = OpenLayers.Util.getImagesLocation() + 'cloud-popup-relative.gif';

        this.adjustInfoPopupBounds(infoPopup);

        this.map.addPopup(infoPopup);
    },

    onPopupClosePlacename: function () {
        if (infoPopup) {
            this.map.removePopup(infoPopup);
            infoPopup.destroy();
            infoPopup = null;

            // Reset print detailinfo div
            var util_instance = new VisKort.Utils();
            util_instance.ResetPrintDetailInfobox();
        }
        // ensure a new popup does not appear immidiately after/on popup close
        // - not necessary in IE
        /*if (OpenLayers.Util.getBrowserName() != "msie")
        this.ignoreMapClickOnce = true;*/
    },

    onPopupClose: function (feature) {
        if (infoPopup) {
            this.map.removePopup(infoPopup);
            infoPopup.destroy();
            infoPopup = null;

            // Reset print detailinfo div
            var util_instance = new VisKort.Utils();
            util_instance.ResetPrintDetailInfobox();
        }
        try {
            OpenLayers.Event.stop(feature);
        }
        catch (e) {
        }
        // ensure a new popup does not appear immidiately after/on popup close
        // - not necessary in IE
        /*if (OpenLayers.Util.getBrowserName() != "msie")
        this.ignoreMapClickOnce = true;*/
    },

    showCombinedInfo: function (evtInfo) {

        /* Close infoPopup if created */
        if (infoPopup != null)
            this.onPopupClose();

        var lonlat = evtInfo.lonlat;
        var features = evtInfo.features;
        var tempContainer = document.createElement("div");
        this.linkContainer = document.createElement("div");
        this.linkContainer.className = this.displayClass + "_combinedContainer";
        tempContainer.appendChild(this.linkContainer);

        for (var i = 0; i < features.length; i++) {
            var html = "<hr /><p class='" + this.CLASS_NAME.replace(/\./g, "") + "Item" + "'><b>" + features[i].layer.extra.infoBoxTitle + "</b><br /><br />" + features[i].data.name + "<br />" + features[i].data.description + "</p>";
            var customInfoDiv = document.createElement("div");
            customInfoDiv.className = this.displayClass + "_combinedInfo";
            //if (i != features.length - 1) html += "<hr />";
            customInfoDiv.innerHTML = html;
            tempContainer.appendChild(customInfoDiv);
        }

        // Route info
        var lonlatPoint = new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat);
        if (this.infoBoxArea && (!this.infoBoxArea.intersects(lonlatPoint)))
            return;

        if (this.linkGenerators) {
            var services = new VisKort.Utils.Services();
            services.reverseGeocodeLonlat(lonlat, this.addRouteplanningLinks.bind(this));
        }

        infoPopup = new OpenLayers.Popup.FramedCloud("Info",
                           lonlat,
                           new OpenLayers.Size(200, 200),
                           tempContainer.innerHTML,
                           null, true, this.onPopupClose.bind(this));
        infoPopup.imageSrc = OpenLayers.Util.getImagesLocation() + 'cloud-popup-relative.gif';

        this.adjustInfoPopupBounds(infoPopup);

        this.map.addPopup(infoPopup);

        // Empty childNodes
        for (var i = 0; i < infoPopup.contentDiv.childNodes.length; i++)
            infoPopup.contentDiv.childNodes[i].innerHTML = "";

        infoPopup.contentDiv.replaceChild(tempContainer, infoPopup.contentDiv.firstChild);
    },

    CLASS_NAME: "OpenLayers.Control.InfoBox",

    adjustInfoPopupBounds: function (infoPopupControl) {
        infoPopupControl.imageSize = new OpenLayers.Size(676, 736);
        infoPopupControl.positionBlocks.tl.blocks[1].position = new OpenLayers.Pixel(-638, 0);
        infoPopupControl.positionBlocks.tl.blocks[3].position = new OpenLayers.Pixel(-638, -632);
        infoPopupControl.positionBlocks.tr.blocks[1].position = new OpenLayers.Pixel(-638, 0);
        infoPopupControl.positionBlocks.tr.blocks[3].position = new OpenLayers.Pixel(-638, -631);
        infoPopupControl.positionBlocks.bl.blocks[1].position = new OpenLayers.Pixel(-638, 0);
        infoPopupControl.positionBlocks.bl.blocks[3].position = new OpenLayers.Pixel(-638, -629);
        infoPopupControl.positionBlocks.br.blocks[1].position = new OpenLayers.Pixel(-638, 0);
        infoPopupControl.positionBlocks.br.blocks[3].position = new OpenLayers.Pixel(-638, -627);

        infoPopupControl.contentDiv.style.overflowX = 'hidden';
        infoPopupControl.contentDiv.style.overflowY = 'auto';
    }
});
