/**
 * @author Peter Goulborn
 * @modifiedby David Cordner
 *
 * Date: 03/05/2009
 *  
 * Class: Astun.iSharemaps.OLInteractCtrl
 * Provides iSharemaps map interface controls for handling pop-ups
 * <Astun.iSharemaps.OLInteractCtrl> constructor.  
 */

if (!Astun) var Astun = {};
if (!Astun.iSharemaps) Astun.iSharemaps = {};
Astun.iSharemaps.OLInteractCtrl = Class.create({

    initialize: function(olmap) {
        /**
        * Function: initialize, creates the object 
        *
        * Parameters:
        * olmap - {object} olmap object
        *
        * Returns:
        * l
        */
        this.clickedInfo = '';
        this.mapWrapper = olmap;

    },

    showMapToolTip: function(evt) { //onMapToolTip
        /**
        * Function: showMapToolTip
        * Draws a popup containing feature properties info on feature hover
        *
        * {this} is assumed to be an <Astun.iSharemaps.OLMap> object, 
        * should be passed through from calling function
        *
        * Parameters:
        * evt - {object} Open layer evt object 
        *
        * Returns:
        * 
        */

        var evtElement = evt.memo.mapEvent.originalTarget || evt.memo.mapEvent.srcElement;
        if (!evtElement.map &&
			  !(evtElement.id === evtElement.parentNode.id + '_GroupDiv') &&
			  !(evtElement.id === evtElement.parentNode.id + '_FrameDecorationImg_4')
			) {
            // Test to see if hover is actually over the map. If not then return.
            return;
        }
        var mapWrapper = this;
        var pauseDelay = (mapWrapper.infoPopup) ? 1000 : 600; // if a map tip popup already exists then take longer
        var en = this.map.getLonLatFromPixel(evt.memo.mapEvent.xy);
        function clearPopup() {

            mapWrapper.map.removePopup(mapWrapper.infoPopup);
            mapWrapper.infoPopup = null;
        }
        var oMap = this.map;

        var queryType = 'info';
        clearTimeout(mapWrapper.timers.hover);
        mapWrapper.timers.hover = setTimeout(function() {
            mapWrapper.getMapMultiInfo(
				en,
				12,
				queryType,
				function(response, mapWrapper) {
				    if (mapWrapper.infoPopup) { clearPopup(); }
				    var htmlFormat = '';
				    if (response.unexpectedResponse) {
				        var displayname = '';
				        var htmlFormat = '' + response.unexpectedResponse;
				    }
				    else {
				        var featureCollectionArray = response;
				        while (featureCollectionArray.length > 0) {
				            var featureCol = featureCollectionArray.shift();
				            for (i = 0; i < featureCol.features.length; i++) {
				                htmlFormat += featureCol.features[i].properties.html;
				            }
				        }
				    }
				    var htmlDiv = '<div style="height: 250px; overflow: auto; padding: 0 0.5em;">' + htmlFormat + '</div>';
				    var anchorIcon = OpenLayers.Marker.defaultIcon();
				    var featurePopup = new OpenLayers.Popup.FramedCloud
						(
							null,
							en,
							new OpenLayers.Size(200, 300),
							htmlDiv,
							{ size: new OpenLayers.Size(1, 1), pixel: new OpenLayers.Pixel(0, 0) },
							true,  // close box
							function(evt) {
							    this.hide();
							    clearPopup();
							    OpenLayers.Event.stop(evt);
							}
						);
				    featurePopup.maxSize = new OpenLayers.Size(600, 300);
				    featurePopup.autoSize = true;
				    featurePopup.panMapIfOutOfView = true;
				    mapWrapper.map.addPopup(featurePopup);
				    mapWrapper.infoPopup = featurePopup;
				}
			)
        },
		pauseDelay);
    }, //onMapToolTip


    onInfoClick: function(evt) { //onInfoClick
        /**
        * Function: onInfoClick
        * Draws a popup containing feature properties on clicking on a map feature
        *
        * {this} is assumed to be a <Astun.iSharemaps.OLMap> object
        *
        * Parameters:
        * evt - {object} Open layer evt object 
        *
        * Returns:
        * 
        * Revision History:
        * 08/01/2009 -  Prak -   Corrected error when dragging map
        * 07/01/2009 -  Prak -   First Investigations
        *
        */

        clearTimeout(this.timers.hover);
        var en = this.map.getLonLatFromPixel(evt.memo.mapEvent.xy);
        var queryType = 'info';

        var triggerEvent = function(response, OLMap) {
            var htmlFormat = '';
            if (response.unexpectedResponse) {
                var displayname = '';
                var htmlFormat = '' + response.unexpectedResponse;
            }
            else {
                var featureCollectionArray = response;
                while (featureCollectionArray.length > 0) {
                    var featureCol = featureCollectionArray.shift();
                    htmlFormat += featureCol.properties.htmlHeader;
                    for (i = 0; i < featureCol.features.length; i++) {
                        htmlFormat += featureCol.features[i].properties.html;
                    }
                    htmlFormat += featureCol.properties.htmlFooter;
                }
            }
            this.clickedInfo = htmlFormat;
            OLMap.mapElement.fire("astun:resultsReceived", { 'type': 'infoClick', 'html': htmlFormat });
        };
        this.getMapMultiInfo
				(
						en,
						12,
						queryType,
						triggerEvent
				)

    }, //onInfoClick

    findNearest: function(evt) { //findNearest
        /**
        * Function: findNearest
        * Displays a set of features of interest within a distance range as makers
        *
        * {this} is assumed to be a <Astun.iSharemaps.OLMap> object
        *
        * Parameters:
        * evt - {object} Open layer evt object 
        *
        * Returns:
        * 
        */

        var layer = evt.memo.layer;
        var en = this.currentPosition || this.map.getCenter();
        if (this.query.popups.length > 0) {
            while (this.query.popups.length) {
                this.map.removePopup(this.query.popups.pop());
            }
        }
        this.deleteMarker(this.currentLocation.marker);
        this.currentLocation.marker = null;

        var showMyNearest = function(response, OLMap) {//ShowFeatures
            if (response.unexpectedResponse) {
                var displayname = '';
                var htmlResponse = '' + response.unexpectedResponse;
            }
            else {
                var featureCollectionArray = response;
                var featureCol = featureCollectionArray[0];
                var html = '';
                var popupBounds = new OpenLayers.Bounds();
                popupBounds.extend(OLMap.currentPosition);
                OLMap.query.layer = featureCol.properties.layer;
                OpenLayers.Popup.FramedCloud.prototype.fixedRelativePosition = true;
                OpenLayers.Popup.FramedCloud.prototype.relativePosition = "tr";
                html += featureCol.properties.htmlHeader;
                while (featureCol.features.length) {
                    var feature = featureCol.features.shift(); // 
                    var htmlFormat = feature.id;

                    var lonLat = new OpenLayers.LonLat(feature.geometry.coordinates[0][0], feature.geometry.coordinates[0][1]);

                    popupBounds.extend(lonLat);
                    // if third coordinate different then dealing with bounding box, extend to that too, put marker in centre
                    if ((feature.geometry.coordinates[0][0] !== feature.geometry.coordinates[2][0]) || (feature.geometry.coordinates[0][1] !== feature.geometry.coordinates[2][1])) {
                        var topRight = new OpenLayers.LonLat(feature.geometry.coordinates[2][0], feature.geometry.coordinates[2][1]);
                        popupBounds.extend(topRight);
                        var featureBounds = new OpenLayers.Bounds();
                        featureBounds.extend(lonLat);
                        featureBounds.extend(topRight);
                        lonLat = featureBounds.getCenterLonLat();
                    }

                    var featurePopup = new OpenLayers.Popup.FramedMarker
							(
								null,
								lonLat,
								new OpenLayers.Size(20, 18),
								htmlFormat,
								{ size: new OpenLayers.Size(1, 1), pixel: new OpenLayers.Pixel(0, 0) },
								false  // no close box
							);
                    OLMap.query.popups.push(featurePopup);
                    html += feature.properties.html; //We want results HTML to be in ascending order of distance
                }
                html += featureCol.properties.htmlFooter;

                OLMap.map.zoomToExtent(popupBounds.scale(1.4), true); //Add some padding and find zoom level as we will probably be using cached tiles


                var icon = new OpenLayers.Icon('images/zoomToIcon.gif', new OpenLayers.Size(34, 34), null, function(size) {
                    return new OpenLayers.Pixel(-12, 2 - size.h);
                });
                OLMap.currentLocation.marker = OLMap.createMarker(OLMap.currentPosition, icon);


                var numPopups = OLMap.query.popups.length;
                for (var i = numPopups - 1; i > -1; --i) {
                    OLMap.map.addPopup(OLMap.query.popups[i]); // Reverse order to give nearest resutls highest z-index.
                }
                var displayName = OLMap.query.layer;
                var htmlResponse = html;
            }

            OLMap.mapElement.fire("astun:resultsReceived", { 'type': 'findNearest', 'displayName': displayName, 'html': htmlResponse });

        } //showMyNearest

        if (evt.memo.reset) {
            this.mapElement.fire("astun:resultsCleared", { 'type': 'findNearest', 'displayName': this.query.layer });
            this.query.layer = null;
        }
        else {
            if (layer.query.findNearest) {
                this.findMyNearest(
								en,
								layer.layerName,
								layer.query.findNearest.maxResults,
								layer.query.findNearest.distance,
								showMyNearest
						);
            }
            else if (layer.query.showMy) {
                this.findMy(
								en,
								layer.layerName,
								showMyNearest
						);
            }
        }
    }, //findNearest

    buildImgTag: function(arWard, graphType, width, height, noBorder, simplify, axisFontSize, yField, dateRange, ds, sIncidentField) {
        /**
        * Function: buildImgTag
        * builds an image html tag from parameters for graph display on popup, 
        *
        * Parameters:
        * arWard - {Array} Contains info for polygon feature for popup, 0-feaureName,1-ward,2-District
        * graphType - {String}, can be 'Line', 'Bar', 'Line-Symbol', 'Pie'
        * width - {number} width of image in pixel
        * height - {number} height of image in pixel
        * noBorder - {bool} true-no border, false-with border
        * simplify - {bool} paramer sent to produce graph
        * axisFontSize - {number} font size of text charaters on graph
        * yField - {String} field whose values to be plotted on Y-axis
        * dateRange - {String} string for date rane e.g. "between '2008-11-01' and '2008-11-30'"
        * ds - {String} name of the datasource name configured on iShareMaps studio
        *
        * Returns:
        * {string} - an iamge html tag e.g. '<img, src=.... />
        */
        var myURL = location.href.substring(0, location.href.lastIndexOf("/") + 1);
        var sImgHtml = '<img class="atThematicGraph"';
        sImgHtml += ' src="';
        sImgHtml += myURL + "getdata.aspx?RequestType=Chart&DataSource=";
        sImgHtml += ds;
        sImgHtml += "&Type=" + graphType + "&NoBorder=" + noBorder + "&Simplify=" + simplify;
        sImgHtml += "&Size=" + width + "|" + height + "&AxisFontSize=" + axisFontSize + "&chosen=^neighbourhood^'";
        //sImgHtml +=  this.escapeSpecialChars(arWard[1]) ;
        sImgHtml += this.escapeSpecialChars(arWard[0]);
        sImgHtml += "'^&Xfield=datetime&Title=Sample&Selected=";
        sImgHtml += sIncidentField;
        sImgHtml += "&filter=^datetime^ ";
        sImgHtml += dateRange;
        sImgHtml += " and district = '"
        sImgHtml += this.escapeSpecialChars(arWard[2]) + "'";
        sImgHtml += "^";
        sImgHtml += '" width="' + width + '"';
        sImgHtml += ' height="' + height + '"';
        sImgHtml += ' />';
        return sImgHtml;
    },

    getDistrictWard: function(featureName) {
        /**
        * Function: getDistrictWard
        * retuns an array object conbtaining ward, district name from a polygon feature name
        *
        * Parameters:
        * featureName - {String} name of a polygon feature on thematic layer
        *
        * Returns:
        * {Array} - 0-featureName, 1-Ward name, 2-District Name
        */

        var retAr = [];
        var iIndex = featureName.indexOf('@');
        var sWard = featureName.substring(0, (iIndex));
        var sDistrict = featureName.substring((iIndex + 1));
        retAr[0] = featureName;
        retAr[1] = sWard;
        retAr[2] = sDistrict;
        return retAr;
    },

    showThematicPopUp: function(evt) {

        /**
        * Function: showThematicPopUp
        * Throws a popup on hovering over a polygon feaure on the thematic layer
        *
        * Parameters:
        * evt - {object} Open layer evt object 
        *
        * Returns:
        * 
        */


        // QUESTION: Why not use the feature selector control referenced elsewhere?


        var evtElement = evt.originalTarget || evt.srcElement;

        var notOverVector = (
			evtElement.id.split('_')[0] !== 'OpenLayers.Layer.Vector' &&
			evtElement.parentNode.id.split('_')[0] !== 'OpenLayers.Layer.Vector' &&
			evtElement.id !== evtElement.parentNode.id + '_GroupDiv' &&
			evtElement.id !== evtElement.parentNode.id + '_FrameDecorationImg_4'
		);


        if (notOverVector) {
            // Test to see if hover is actually over the vector layer or empty parts of the popup. If not then return.
            return;
        }

        // FT JSON
        var getPopUpJsonDefine = function(sfeature, sfeatureCode, gs, ms, pd) {
            var onSuccessFunc = function(transport) {
                try {
                    var oJson = transport.responseText.evalJSON();

                    var myURL = location.href.substring(0, location.href.lastIndexOf("/") + 1);
                    var arHoverWard = this.interactions.getDistrictWard(sfeature);
                    var sWard = arHoverWard[1];
                    var sDistrict = arHoverWard[2];

                    var arHomeWard = null;
                    if (!!this.map.thematic.homeFeature) {
                        arHomeWard = this.interactions.getDistrictWard(this.map.thematic.homeFeature.current.attributes.name);
                    }
                    var sIncidentField = this.map.thematic.columnName;
                    var ds = this.map.thematic.dataSourceName;
                    var oFeature = this.map.thematic.feature;
                    //var periodDiff = ( oFeature.attributes.currentValue - oFeature.attributes.previousValue );
                    var aRules = this.map.thematic.feature.layer.styleMap.styles['default'].rules;
                    var rangeColour = '';
                    var rangeName = '';
                    for (var i = 0; i < aRules.length; i++) {
                        var oRule = aRules[i];
                        var applies = oRule.evaluate(oFeature);
                        if (applies) {
                            rangeColour = oRule.symbolizer.Polygon.fillColor;
                            rangeName = oRule.name;
                        }
                    }
                    var en = this.map.getLonLatFromPixel(evt.xy);
                    /*
                    //show arrow if diferrence > 5
                    var arrowImg = '';
                    arrowImg = '<img width="16" height="16" src="';
                    arrowImg += "images/" ;

					//oFeature.attributes.previousValue now hold the change flag indicator 0=no change, -1=decrease,1=increase
                    if ( oFeature.attributes.previousValue == 1)
                    arrowImg += 'arrow-up_16.gif" alt="up" title="Increase of more than 5% since previous month"/>' ;
                    else if ( oFeature.attributes.previousValue == -1)
                    arrowImg += 'arrow-down_16.gif" alt="down" title="Decrease of more than 5% since previous month" />' ;
                    else				
                    arrowImg += 'arrow-forward_16.gif" "little change" title="Less than 5% change since previous month"/>' ;
                    */

                    var contentHTML = '<h4>' + arHoverWard[1] + '</h4>';
                    contentHTML += '<h5>in ' + arHoverWard[2] + '</h5>';
                    contentHTML += '<div id="atThemeInformation"><p class="atLayerText"><span class="atLayerLegend" style="border-color:' + rangeColour + ';"><img src="includes/olmaps/_assets/images/spacer.gif" style="background-color: ' + rangeColour + ';"/></span>' + this.map.thematic.title + ' ' + this.map.thematic.themeField + ': ' + rangeName + '</p>';
                    //contentHTML += '	<p class="atChangeText">Compared to this time last year: ' + arrowImg + '</p>';
                    contentHTML += '</div>\n';
                    contentHTML += '<ul id="atPopupTabSwitcher"><li><a href="#atThemePopupOne">Summary</a></li><li><a href="#atThemePopupTwo">Compare</a></li><li><a href="#atThemePopupThree">Trend</a></li></ul>';
                    contentHTML += '<div id="atPopupTabs">\n';
                    contentHTML += '<div class="atPopupTab" id="atThemePopupOne">';
                    contentHTML += oJson.data.summary;
                    contentHTML += '</div><div class="atPopupTab" id="atThemePopupTwo">';
                    contentHTML += oJson.data.comparison;
                    contentHTML += '</div><div class="atPopupTab" id="atThemePopupThree">';
                    contentHTML += oJson.data.trend;
                    contentHTML += '</div></div>\n';
                    if (oJson.data.url.length > 0) {
                        contentHTML += '<p style="float:left;margin-top:5px;margin-top:10px"><img src="images/skin/ppInfo.gif" />&nbsp;<a href="' + oJson.data.url + '">Go to a detailed profile of ' + arHoverWard[1] + '</a></p>\n';
                    }
                    //contentHTML += '<p style="float:left;"><img src="images/skin/ppQuestion.gif" />&nbsp;<a href="viewpage.aspx?c=page&page=ppHelp">What do these numbers mean?</a></p>\n';
                    var popupInitDefine = function() {
                        var switcher = $("atPopupTabSwitcher");
                        //return;
                        var selectors = switcher.select("a");
                        switcher.current = selectors[this.map.thematic.lastThemePopupTab || 0];
                        setLastTabDefine = function(tabIndex) {
                            this.lastThemePopupTab = tabIndex;
                        }
                        setLastTab = setLastTabDefine.bind(this.map.thematic);
                        selectors.each(function(selector, index) {
                            $(selector.parentNode);
                            selector.tabId = selector.href.split("#").pop();
                            selector.id = index;
                            if (selector === switcher.current) {
                                $(selector.tabId).addClassName("atPopupTabSelected");
                                selector.parentNode.addClassName("atPopupTabSelected");
                            }
                            var clickFunc = function(evt, lastThemePopupTab) {
                                try {
                                    if (!(this === switcher.current)) {
                                        $(switcher.current.tabId).removeClassName("atPopupTabSelected");
                                        switcher.current.parentNode.removeClassName("atPopupTabSelected");
                                        $(this.tabId).addClassName("atPopupTabSelected");
                                        this.parentNode.addClassName("atPopupTabSelected");
                                        switcher.current = this;
                                        setLastTab(this.id);
                                    };
                                }
                                finally {
                                    Event.stop(evt); return false;
                                }
                            };
                            Event.observe(selector, "click", clickFunc.bindAsEventListener(selector));
                        });
                    }
                    var popupInit = popupInitDefine.bind(this);

                    var featurePopup = new OpenLayers.Popup.FramedCompact
					(
						null,
						en,
                    //new OpenLayers.Size(300, 275),
						new OpenLayers.Size(256, 380),
						contentHTML,
						null,
						true,  // close box

						function(evt) {
						    this.hide();
						    this.map.thematic.lastThemePopup = '';
						    this.map.removePopup(this);
						    this.destroy;
						    OpenLayers.Event.stop(evt);
						    $('atGeomPanel').show();
						},

						'white'
					);

                    featurePopup.autoSize = false;
                    this.map.addPopup(featurePopup);
                    popupInit();
                    //add to theme Popup array
                    $('atGeomPanel').hide();
                    this.arThemePopup.push(featurePopup);
                    //store the feature property for future comparison
                    this.map.thematic.lastThemePopup = sfeature;
                }
                catch (er) {
                    alert('Error: Failed to get pop-up.');
                }
            }

            var options =
			{
			    method: 'get',
			    parameters: null,
			    onFailure: function(transport) {
			        if (transport.status != 0) { // i.e. if not fail because interrupted
			            alert('Error: Failed to get data for popup');
			        }
			    },
			    onSuccess: onSuccessFunc.bindAsEventListener(this)
			};

            var myURL = this.dataurl;
            myURL += '?requesttype=json&type=mappopup&gs=' + gs + '&ms=' + this.mapsource + '&pd=' + pd + '&rc=' + sfeatureCode;
            new Ajax.Request
					(myURL,
						options
					);

        }

        var getPopUpJson = getPopUpJsonDefine.bind(this);

        var sfeature = this.map.thematic.featureName;
        var sfeatureCode = this.map.thematic.featureCode;
        var sDataSourceName = this.map.thematic.dataSourceName;
        var gs = sDataSourceName.split('@')[1];
        var ms = sDataSourceName.split('@')[0].split('.')[0];
        var pd = sDataSourceName.split('@')[0].split('.')[1];

        if (sfeature === '' || sfeature === undefined) {
            this.clearThemePopups();
            return;
        }


        //create property to keep ref to last themePopup
        if (!this.map.thematic.lastThemePopup) {
            this.map.thematic.lastThemePopup = '';
        }
        //if same feature then do nothing						
        if ((sfeature == this.map.thematic.lastThemePopup) && (this.arThemePopup.length)) {
            //( this.map.popups.length ))
            return;
        }
        this.clearThemePopups();

        getPopUpJson(sfeature, sfeatureCode, gs, ms, pd);



        /*
        var insertTrendExplanation = function(transport) {
        var explanation = transport.responseText;
        if (explanation.length > 0) {
        $('atThemeInformation').insert('<h6>Trend explanation</h6>'+explanation);
        }
        }
        var options = 
        {
        method: 'get',
        parameters: {
        'RequestType': 'xsl',
        'Type': 'DataFunc',
        'ds': 'RSSProcessor',
        'params': '"pubDate","description","title","link","ward"~"RSSCrimeTrendExplanationFeed"~'+this.interactions.escapeSpecialChars(arHoverWard[0]),
        'xsl': 'xml/ClevelandPanelsDescription.xsl'
        },
        onSuccess : insertTrendExplanation.bindAsEventListener(this)					
        };		
        var myURL = location.href.substring(0,location.href.lastIndexOf("/")+1);
        //add to theme Popup array
        this.arThemePopup.push(featurePopup);
        //store the feature property for future comparison
        this.map.thematic.lastThemePopup = sfeature;
        if ( !arHomeWard )
        {
        return ;
        }
        else
        {		
        $('hoverWard').innerHTML = '<h4>' + arHoverWard[1] + '</h4>' ;
        $('hoverWard').innerHTML += '<h5>' + arHoverWard[2] + '</h5>' ;
        $('hoverWard').innerHTML += this.interactions.buildImgTag(arHoverWard,"Line-Symbol-Fill",300,128,true,true,30,sIncidentField,this.map.thematic.dateCriteria2,ds,sIncidentField);
        if (this.mapElement) {
        this.mapElement.fire("astun:resultsReceived", {
        'type': 'wardComparison'
        });
        }
        }
        */
    }, //showThematicPopUp


    showHomeWardGraph: function(thematicInfo) {
        /**
        * Function: showHomeWardGraph
        * Displays the home graph when set
        *
        * Parameters:
        * thematicInfo - {object} contains info about the home ward vector feature
        *
        * Returns:
        * 
        */
        var arHomeWard = this.getDistrictWard(thematicInfo.homeFeature.current.attributes.name);
        var sIncidentField = thematicInfo.oThematicLayer.map.thematic.columnName;
        var dateCriteria2 = thematicInfo.oThematicLayer.map.thematic.dateCriteria2;
        var ds = thematicInfo.oThematicLayer.map.thematic.dataSourceName;
        var title = $('atGraphTitle');
        if (title) {
            title.update(thematicInfo.title);
        }
        else {
            $('atGraphs').insert({ 'top': '<h3 id="atGraphTitle">' + thematicInfo.title + '</h3>' });
        }
        $
        $('homeWard').innerHTML = '<h4>' + arHomeWard[1] + '</h4>';
        $('homeWard').innerHTML += '<h5>' + arHomeWard[2] + '</h5>';
        $('homeWard').innerHTML += this.buildImgTag(arHomeWard, "Line-Symbol-Fill", 300, 128, true, true, 30, sIncidentField, dateCriteria2, ds, sIncidentField);

    },


    escapeSpecialChars: function(strInput) {
        /**
        * Function: escapeSpecialChars
        * retuns a string escaped for characters in set "[\^$.|?*+()]'"
        *
        * Parameters:
        * strInput - {String} the input string
        *
        * Returns:
        * {string} - output string
        */
        var specChars = "[\^$.|?*+()]'";
        for (var i = 0; i < specChars.length; i++) {
            strInput = strInput.replace(new RegExp("\\" + specChars.substr(i, 1), "g"), "\\" + specChars.substr(i, 1));
        }
        return strInput;
    }



});  //oLInteractCtrl
