/// <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,

    infoCount: 0,

    infoLoadedCount: 0,

    linkGenerators: null,

    infoBoxArea: null,

    idCount: 0,

    initialize: function(options, infoBoxArea, linkGenerators) {
        this.infoBoxArea = infoBoxArea;
        this.linkGenerators = linkGenerators;
        OpenLayers.Control.prototype.initialize.apply(this, arguments);
    },

    activate: function() {
        /*        this.map.addClickListener(this.trigger.bind(this)); */

        /**/
        this.handlerOptions = OpenLayers.Util.extend(
                        {}, this.defaultHandlerOptions
                    );
        this.handler = new OpenLayers.Handler.Click(
                        this, {
                            'click': this.trigger
                        }, this.handlerOptions
                    );


        OpenLayers.Control.prototype.activate.apply(this, arguments);
        /**/


    },

    /*
    trigger: function(geoEvent) {
    
    */

    /**/
    trigger: function(e) {
        /**/
        /*        if (this.ignoreMapClickOnce) {
        this.ignoreMapClickOnce = false;
        return;
        }*/

        if (infoPopup != null)
            this.onPopupClose();

        /**/
        var xy = e.xy;
        //alert("x: " + xy.x + ", y:"  + xy.y);
        var lonlat = this.map.getLonLatFromViewPortPx(xy);
        var pConverted = viskort.reverseConvertPoint(new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat));
        var lonlatConverted = new OpenLayers.LonLat(pConverted.x, pConverted.y);

        // 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;
        }

        /**/
        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);

        if (this.linkGenerators) {
            var services = new VisKort.Utils.Services();
            services.reverseGeocodeLonlat(lonlatConverted, this.addRouteplanningLinks.bind(this));
        }

        this.layerInfoHeader.style.display = "none";
        this.layerInfoBody.style.display = "none";

        for (var i = 0; i < layers.length; i++) {
            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');
		var tolerance = 0.1 * (this.map.getNumZoomLevels() - this.map.getZoom());
                var url = layers[i].getFullRequestString({
                    REQUEST: "GetFeatureInfo",
                    BBOX: new OpenLayers.Bounds(lonlatPoint.x - tolerance, lonlatPoint.y - tolerance, lonlatPoint.x + tolerance, lonlatPoint.y + tolerance).toBBOX(),
                    X: 1,
                    Y: 1,
                    QUERY_LAYERS: layers[i].params.LAYERS,
                    INFO_FORMAT: infoformat,
                    FEATURE_COUNT: 1,
                    EXCEPTIONS: 'application/vnd.ogc.se_xml',
                    WIDTH: 3,
                    HEIGHT: 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();
                if (tolerance > 5)
                	tolerance = 5;
                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 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);
            }
        }
        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.map.addPopup(infoPopup);

        infoPopup.contentDiv.replaceChild(tempContainer, infoPopup.contentDiv.firstChild);

        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;
            //this.dosomething();
        }
        else
            this.selectListHeader.innerHTML = "";

    },


    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";
            /*            if (i % 2 == 0)
            styleClass = this.displayClass + "_linkGeneratorsLeft";
            else
            styleClass = this.displayClass + "_linkGeneratorsRight"*/
            var linkGenerator = this.linkGenerators[i].getDivElement({ address: address }, styleClass);
            this.linkContainer.appendChild(linkGenerator);
        }
    },

    onInfoResponse: function(i, response) {
        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;
                if (infoBoxLayout["#cdata-section"] != null) {
                    var jsonStr = response.responseText.substring(jsonStartIndex + startStr.length, jsonEndIndex);
                    infoHtml = viskort.JSONparseAGSRestInfo(infoBoxLayout["#cdata-section"], jsonStr);
                    if (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) {
                    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: 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;
    },

    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.map.addPopup(infoPopup);
    },

    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;*/
    },

    CLASS_NAME: "OpenLayers.Control.InfoBox"
});

