﻿
Type.registerNamespace("ThreeIreland");

ThreeIreland.PublicMap = function(service, mapArgs, tileLayers, accessMode, enableRequestNBS) {
    /// <summary>
    ///   The VE Map.
    ///   Supports load on demand
    /// </summary>
    /// <param name="service">The webservice to call for the map data.</param>
    /// <param name="mapArgs">The map initalisation data.</param>

    this._service = service;
    this._mapArgs = mapArgs;
    this._tileLayers = tileLayers;
    this._accessMode = accessMode;
    this._enableRequestNBS = enableRequestNBS;

    this._map = null;
    this._pinID = 0;
    this._zoomlevel = 0;
    this._layer = null;

    this._buildingsLayer = null;
    this._reclusterLayer = null;
    this._selectedShape = null;

    //popup specific
    this._PopupPrefix = "POPUP";
    this._currentpin = null;
    this._currentindex = 0;

    this.GetSitePinDataDelegate = null;
    this.PinHoverDelegate = null;

    //Holds the list of tile server layers
    this.TileServerLayers = new Array();

    this.TileLayerCurrentlyShown = null;


    //Buy4Now
    this._buy4NowSearchResultLayer = null; //Layer for the search results pins
    this.buy4NowEnteredAddressLine1 = null;
    this.buy4NowEnteredAddressLine2 = null;
    this.buy4NowEnteredAddressLine3 = null;
    this.buy4NowEnteredAddressLine4 = null;
    this.buy4NowEnteredAddressLine5 = null;
    //START - Error in buy4now for "the hills, herbertstown, limerick" (no buildong in DB but 6 deliverypoins in addresslink: We display the BLUE PIN
    this.buy4NowEnteredLat = null;
    this.buy4NowEnteredLon = null;
    this.buy4NowEnteredGeoAddressId = null;
    //END - Error in buy4now for "the hills, herbertstown, limerick" (no buildong in DB but 6 deliverypoins in addresslink.
    this.buy4NowAddressLine1 = null;
    this.buy4NowAddressLine2 = null;
    this.buy4NowAddressLine3 = null;
    this.buy4NowAddressLine4 = null;
    this.buy4NowAddressLine5 = null;
    this.buy4NowAddressLine6 = null;
    this.buy4NowGeoAddressId = null;
    this.buy4NowLatitude = null;
    this.buy4NowLongitude = null;
    this.buy4NowAddressMatched = true;
    // START - Alan (Search buildings around)
    this.buy4NowPinpointUsingBuildingSearch = true;
    this.buy4NowInPinpointMode = false;
    //this.ButtonPinpointOnMap = null;
    this.DivBuy4NowInstructions2 = null;
    // END - Alan
    this.buy4NowMaxPinpointDist = 5; //5 kms

    this._sitesUnavailableLayer = null; //For the "Agents" mode , 28/7/10 MI

    this._init();
}

ThreeIreland.PublicMap.prototype = {

    _init: function() {
        /// <summary>
        ///   Initialises the Map.
        /// </summary>
        //setup map
        var opts = new VEMapOptions();
        opts.EnableBirdseye = false;

        this._map = new VEMap(this._mapArgs.DivID);

        if (token != null && token != "") {
            this._map.SetClientToken(token);
        }

        this._map.LoadMap(this._mapArgs.Center, this._mapArgs.Zoomlevel, this._mapArgs.Style, this._mapArgs.Fixed, this._mapArgs.Mode, false, 0, opts);

        if (token != null && token != "") {
            this.TokenExpireDelegate = Function.createDelegate(this, this._TokenExpire);
            this._map.AttachEvent('ontokenexpire', this.TokenExpireDelegate);
        }

        this._map.ClearInfoBoxStyles();
        this._map.SetScaleBarDistanceUnit(this._mapArgs.Scale);
        // Fix to ensure info boxes appear in front of map
        var mapDivContainer = document.getElementById(this._map.ID);
        if (mapDivContainer != null) {
            mapDivContainer.style.zIndex = 0;
        }
        this._layer = new VEShapeLayer();
        this._map.AddShapeLayer(this._layer);

        this._buildingsLayer = new VEShapeLayer();
        this._map.AddShapeLayer(this._buildingsLayer);

        this._reclusterLayer = new VEShapeLayer();
        this._map.AddShapeLayer(this._reclusterLayer);

        //Add tile layers and show coverage if neccesary
        this._AddTilesAccordingToBrowser();

        if (this._accessMode == "NBS") {
            LoadLegend("ThreeNBSDED");
            this._ShowNBSCoverage();
        }
        else if (this._accessMode == "NBSAgents") {
            LoadLegend("ThreeNBSDED");
            this._ShowNBSCPESCoverage();
        }
        else if (this._accessMode == "Buy4Now") {
            // Do nothing
        }
        else if (this._accessMode == "Agents") { //##
            this._sitesUnavailableLayer = new VEShapeLayer("SitesUnavailable");
            this._map.AddShapeLayer(this._sitesUnavailableLayer);
            //this._sitesUnavailableLayer.Show(); //~~
            //setup the function to get new data whenever the map changes
            this.GetSitePinDataDelegate = Function.createDelegate(this, this._GetSitePinData);
            this._map.AttachEvent("onchangeview", this.GetSitePinDataDelegate);

            this._GetSitePinData();

            // Do nothing
            //LoadLegend("ThreeInOut");
            //this._Show3GCoverageInOut();
        }
        else { } //Do nothing

        if (this._accessMode == "Buy4Now") {
            //layer for the search results pins: functions AddSearchPin & RemoveSearchPin
            this._buy4NowSearchResultLayer = new VEShapeLayer();
            this._map.AddShapeLayer(this._buy4NowSearchResultLayer);
        }
        else {
            //turn off the standard popup and attach our custom handler
            this.PinHoverDelegate = Function.createDelegate(this, this._PinActivate);
            this._map.AttachEvent("onmouseover", this.PinHoverDelegate);
            this._map.AttachEvent("onclick", this.PinHoverDelegate);
        }

        var browserVersion = Utility.DetectBrowser();
        if (browserVersion == "ie6") {
            //On change map style
            this.ChangeMapStyleHandler = Function.createDelegate(this, this._ChangeMapStyleHandler);
            this._map.AttachEvent("onchangemapstyle", this.ChangeMapStyleHandler);
        }

        //setup the function to get new data whenever the map changes
        if (this._accessMode != "Buy4Now") {
            this.GetTileServerLayersDelegate = Function.createDelegate(this, this._UpdateLayerDates);
            this._map.AttachEvent("onchangeview", this.GetTileServerLayersDelegate);
        }



    },
    _TokenExpire: function() {
        alert('expire');
        window.location.reload(true);
    },
    _AddTilesAccordingToBrowser: function() {
        var array = this._tileLayers;
        var browserVersion = Utility.DetectBrowser();
        for (i = 0; i < array.length; i++) {
            this._AddTileServer(array[i][0], array[i][1]);
            if (browserVersion == "ie6") {
                this._AddTileServer(array[i][0] + "r", array[i][1] + "&mapMode=r");
                this._AddTileServer(array[i][0] + "a", array[i][1] + "&mapMode=a");
                this._AddTileServer(array[i][0] + "h", array[i][1] + "&mapMode=h");
            }
        }
    },
    _AddTileServer: function(name, url, opacity, zIndex) {
        var TempTileSource = new VETileSourceSpecification(name, url);
        TempTileSource.MinZoomLevel = 6;
        TempTileSource.MaxZoomLevel = 19;
        TempTileSource.NumServers = 2;
        TempTileSource.Opacity = 0.7;
        if (opacity != null && opacity != undefined) {
            TempTileSource.Opacity = opacity;
        }
        if (zIndex != null && zIndex != undefined) {
            TempTileSource.ZIndex = zIndex;
        }
        //Hack put in to support SSL seamlessly. Load SSL tiles - PF 19/06/09
        if (typeof (useSSL) != "undefined") {
            if (useSSL == "True")
                TempTileSource.TileSource = TempTileSource.TileSource.replace("http", "https");
        }
        this._map.AddTileLayer(TempTileSource, false);
        this._map.HideTileLayer(name);
        this.TileServerLayers.push(name);
    },
    _UpdateTileLayers: function(changedTiles) {
        //IE6: has major problems drawing the layers we use 'R' for road mode, 'A' for aerial mode and 'H' for Hybrid
        var browserVersion = Utility.DetectBrowser();
        //Loop all the tile server layes associated to the map
        var tileNum = changedTiles.length;
        for (x = 0; x < tileNum; x++) {
            var layer = changedTiles[x];
            var TempTileSource = null;
            if (browserVersion == "ie6") {
                var mode = this._map.GetMapStyle();
                //delete if it exists
                if (this._map.GetTileLayerByID(layer[0] + mode) != null)
                    this._map.DeleteTileLayer(layer[0] + mode);
                //create new VETileSourceSpecification obj
                TempTileSource = new VETileSourceSpecification(layer[0] + mode, layer[1] + "&mapMode=" + mode);
            }
            else {
                //delete if it exists
                if (this._map.GetTileLayerByID(layer[0]) != null)
                    this._map.DeleteTileLayer(layer[0]);
                //create new VETileSourceSpecification obj
                TempTileSource = new VETileSourceSpecification(layer[0], layer[1]);
            }
            //set VETileSourceSpecification properties
            TempTileSource.MinZoomLevel = 6;
            TempTileSource.MaxZoomLevel = 19;
            TempTileSource.NumServers = 1;
            TempTileSource.Opacity = 0.7;
            //add VETileSourceSpecification to map
            this._map.AddTileLayer(TempTileSource, false);
        }
    },
    LoadPinsOnMapForGeodirectoryIdLatLon: function(lat, lon, geoAddressId) ////START - END:  Error in buy4now for "the hills, herbertstown, limerick" (no buildong in DB but 6 deliverypoins in addresslink: We display the BLUE PIN
    {
        this.buy4NowEnteredLat = lat;
        this.buy4NowEnteredLon = lon;
        this.buy4NowEnteredGeoAddressId = geoAddressId;
        this._buy4NowSearchResultLayer.DeleteAllShapes();
        this.OnGetBuildingsByIDDelegate = Function.createDelegate(this, this.OnGetBuildingsByIDSuccess);
        this.OnGetBuildingsByIDFailedDelegate = Function.createDelegate(this, this.OnGetBuildingsByIDFailed);
        ThreeIreland.Services.AddressLinkService.GetBuildingsByID(geoAddressId, this.OnGetBuildingsByIDDelegate, this.OnGetBuildingsByIDFailedDelegate);
    },

    LoadPinsOnMapForGeodirectoryId: function(address, addressNormal, geoAddressId) {
        //PF start here
        this._buy4NowSearchResultLayer.DeleteAllShapes();
        this.OnGetBuildingsByIDDelegate = Function.createDelegate(this, this.OnGetBuildingsByIDSuccess);
        this.OnGetBuildingsByIDFailedDelegate = Function.createDelegate(this, this.OnGetBuildingsByIDFailed);
        ThreeIreland.Services.AddressLinkService.GetBuildingsByID(geoAddressId, this.OnGetBuildingsByIDDelegate, this.OnGetBuildingsByIDFailedDelegate);
    },
    LoadPinsOnMapForLatLong: function(latitude, longitude) // START - END Alan (Search buildings around)
    {
        this.DivBuy4NowInstructions2.innerHTML = 'Searching for buildings. Please wait...';
        this._buy4NowSearchResultLayer.DeleteAllShapes();
        this.OnGetBuildingsByLatLongDelegate = Function.createDelegate(this, this.OnGetBuildingsByIDSuccess);
        this.OnGetBuildingsByLatLongFailedDelegate = Function.createDelegate(this, this.OnGetBuildingsByIDFailed);
        ThreeIreland.Services.AddressLinkService.GetBuildingsByLatLong(latitude, longitude, this.OnGetBuildingsByLatLongDelegate, this.OnGetBuildingsByLatLongFailedDelegate);
    },
    LoadPinOnMap: function(lat, lon, address, addressNormal, geoAddressId, deliveryPoints) {
        var loc = new VELatLong(lat, lon);
        //Add the pin
        this.addressPin = new VEShape(VEShapeType.Pushpin, loc);
        this.addressPin.SetCustomIcon("<div class='myPushpin'></div>");
        if ((this._accessMode == "NBS") || (this._accessMode == "NBSAgents")) {
            // "Request NBS notification" is shown according to the weconfig key "EnableRequestNBS"
            if (Utility.ConvertStringToBoolean(this._enableRequestNBS)) {
                this.addressPin.SetDescription("<div class = 'pinDescriptionPublic'><table><tr><td>" + address + "&#160;&#160;</td></tr>" +
                                        "<tr><td align='right'><div class='linkLabel' style='width:250px'  onclick='RemoveAddressPin();'>Delete pin from map</div></td></tr>" +
                                        "<tr><td align='right'><div class='linkLabel' style='width:250px' onclick=\"RequestNBSNotification('" + addressNormal + "');\">Request NBS Notification</div></td></tr></table</div>");
            }
            else {
                this.addressPin.SetDescription("<div class = 'pinDescriptionPublic'><table><tr><td>" + address + "&#160;&#160;</td>" +
                                           "<tr><td align='right'><div class='linkLabel' style='width:250px'  onclick='RemoveAddressPin();'>Delete pin from map</div></td></tr></table></div>");
            }
        }
        else if (this._accessMode == "Buy4Now") {
            this._buy4NowSearchResultLayer.DeleteAllShapes();

            try {
                document.getElementById("myMap").childNodes[0].style.cursor = "";
                this._map.DetachEvent("onmousedown", this.MouseHandlerDelegate);
            }
            catch (o)
            { }

            //Delete shapes of the search result layer
            this._buy4NowSearchResultLayer.DeleteAllShapes();

            var addressSplit = addressNormal.split(',');

            this.buy4NowAddressLine1 = addressSplit.length > 0 ? addressSplit[0] : "";
            this.buy4NowAddressLine2 = addressSplit.length > 1 ? addressSplit[1] : "";
            this.buy4NowAddressLine3 = addressSplit.length > 2 ? addressSplit[2] : "";
            this.buy4NowAddressLine4 = addressSplit.length > 3 ? addressSplit[3] : "";
            this.buy4NowAddressLine5 = addressSplit.length > 4 ? addressSplit[4] : "";
            this.buy4NowAddressLine6 = addressSplit.length > 5 ? addressSplit[5] : "";
            this.buy4NowGeoAddressId = geoAddressId;
            this.buy4NowLatitude = lat;
            this.buy4NowLongitude = lon;

            if (deliveryPoints < 200) {
                this.buy4NowAddressMatched = true;
                var txtPopUp = "<table><tr><td>" + address + "&#160;&#160;</td>" +
                                           "<tr><td align='right'>";
                //txtPopUp += "<div class='linkLabel' style='width:250px' onclick='AcceptBuy4Now();'>Accept</div>";
                txtPopUp += "<input id='ButtonAccept' type='button' value='Accept' onclick='AcceptBuy4Now();' style='font-family:Tahoma' />";
                txtPopUp += "</td></tr></table>";

            }
            else {
                this.buy4NowAddressMatched = false;
                var txtPopUp = "<p><b>We found more than 200 residences at your selected location.</b></p>";
                txtPopUp += "Please refine your Address Search e.g. add a house number or street name <br/>";
                txtPopUp += "If you have already entered your full and complete address, then use the<br/>Pinpoint Address button, click on  the map and select your exact location";
                UpdateInstructions("Choose an address", "More than 200 address"); //Defined in CoveragePublicPage.aspx.js
            }
            this.AddBuy4NowPin(lat, lon, txtPopUp, true);
            return;
        }
        else {
            this.addressPin.SetDescription("<div class = 'pinDescriptionPublic'><table><tr><td>" + address + "&#160;&#160;</td></tr>" +
                                        "<tr><td align='right'><div class='linkLabel' style='width:250px' onclick='RemoveAddressPin();'>Delete pin from map</div></td></tr></table>");
        }
        this._layer.AddShape(this.addressPin);
        //Zoom to the pin
        this._map.SetCenterAndZoom(new VELatLong(lat, lon), 15);
        //Show info box if NBS - CHANGED, NOW SHOW ALWAYS
        //if ((this._accessMode == "NBS") || (this._accessMode == "NBSAgents"))
        this._map.ShowInfoBox(this.addressPin);

    },
    SetBuy4NowAddress: function(addressLine1, addressLine2, addressLine3, addressLine4, addressLine5) {
        this.buy4NowEnteredAddressLine1 = addressLine1.toUpperCase();
        this.buy4NowEnteredAddressLine2 = addressLine2.toUpperCase();
        this.buy4NowEnteredAddressLine3 = addressLine3.toUpperCase();
        this.buy4NowEnteredAddressLine4 = addressLine4.toUpperCase();
        this.buy4NowEnteredAddressLine5 = addressLine5.toUpperCase();
    },
    PinpointAddress: function() {
        // START - Alan (Search buildings around)
        this.buy4NowInPinpointMode = true;
        // END -Alan

        //On mouse right button click
        this.MouseHandlerDelegate = Function.createDelegate(this, this._MouseClickHandler);
        this._map.AttachEvent("onmousedown", this.MouseHandlerDelegate);
        document.getElementById("myMap").childNodes[0].style.cursor = "crosshair";
        this._buy4NowSearchResultLayer.DeleteAllShapes();
    },
    CancelPinpointAddress: function() {
        // START - Alan (Search buildings around)
        this.buy4NowInPinpointMode = false;
        this._buy4NowSearchResultLayer.DeleteAllShapes();
        // END -Alan

        //Detech mouse right button click
        try {
            this._map.DetachEvent("onmousedown", this.MouseHandlerDelegate);
        }
        catch (o) { }
        document.getElementById("myMap").childNodes[0].style.cursor = "";
    },
    _UpdateLayerDates: function() {
        // Retrieves the layers' dates, if any has changed we update the this._tileLayers Object as well as the map's tile layers URLs. This will ensure that the latest tile layer is being correctly loaded
        var currentLayers = this._tileLayers;
        ThreeIreland.Services.MapService.GetUpdatedLayersInformation(currentLayers, Function.createDelegate(this, this.OnGetLatestDatesSucceeded), this.OnGetLayersFailed);
    },
    OnGetLatestDatesSucceeded: function(result) {
        if (result.length > 0) {
            var currentTileChanged = false;

            //STEP 1: Update this._tileLayers object and determine if the current layer has changed
            for (x = 0; x < result.length; x++) {
                var newTile = result[x];
                //STEP 1.1: Check if the current has changed (if true it will be hidden/shown after)
                if (newTile[0] == this.TileLayerCurrentlyShown) {
                    currentTileChanged = true;
                    //Delete the current layer to avoid errors in IE6
                    var browserVersion = Utility.DetectBrowser();
                    if (browserVersion == "ie6")
                        this._map.DeleteTileLayer(this.TileLayerCurrentlyShown + this._map.GetMapStyle());
                    else
                        this._map.DeleteTileLayer(this.TileLayerCurrentlyShown);
                }
                //STEP 1.2: Update this._tileLayers object 
                for (y = 0; y < this._tileLayers.length; y++) {
                    var oldTile = this._tileLayers[y];
                    if (newTile[0] == oldTile[0])
                        this._tileLayers[y] = newTile;
                }
            }

            //STEP 2: Update the map's tile layers that have changed
            this._UpdateTileLayers(result);

            //STEP 3: Show current layer in case the timestamp has been changed
            if (currentTileChanged)
                this._RefreshCurrentTileLayer();
        }
        if (this._selectedShape != null)
            this._map.ShowInfoBox(this._selectedShape);
    },
    OnGetLayersFailed: function() {
        alert("Cannot read layer dates. Please try again.");
    },
    RequestNBSNotification: function() {
        this._map.ClearInfoBoxStyles();
        this.addressPin.SetDescription("<div class='requestNBSInfoBox'><iframe class='iFrameRequestNBS' onload='ReloadNBSNotification()' frameborder='0' scrolling='no' src=\"RequestNBSNotification.aspx?Lat="
                + this.addressPin.Latitude + "&Lon="
                + this.addressPin.Longitude + "\"></iframe></div>");
        //Hide and Show to see the changes
        this._map.HideInfoBox();
        this._map.ShowInfoBox(this.addressPin);
    },
    RemakeNBSNotification: function(name, surname, mail) {
        this._map.ClearInfoBoxStyles();
        this.addressPin.SetDescription("<div class='requestNBSInfoBox'><iframe class='iFrameRequestNBS' onload='ReloadNBSNotification()' frameborder='0' scrolling='no' src=\"RequestNBSNotification.aspx?Lat="
                + this.addressPin.Latitude + "&Lon="
                + this.addressPin.Longitude + "&Name="
                + name + "&Surname="
                + surname + "&Mail="
                + mail + "\"></iframe></div>");
        //Hide and Show to see the changes
        this._map.HideInfoBox();
        this._map.ShowInfoBox(this.addressPin);
    },


    _PinActivate: function(e) {
        if (e.elementID) {
            if (this._map.GetShapeByID(e.elementID).GetType() == VEShapeType.Pushpin) {
                var popupShape = this._map.GetShapeByID(e.elementID)
                if (popupShape) {
                    if (popupShape.Bounds != null && popupShape.Bounds != "") {
                        //set current pin
                        this._currentpin = popupShape;
                        if (this._currentpin.id != "SearchResult")//we don't need to retrieve data from the WS, the description is already filled
                        {
                            this._currentindex = 0;
                            //get the content for the pin.
                            this._getAJAXContent();
                            this._currentpin.SetDescription("<div id='" + this._PopupPrefix + this._currentpin.GetID() + "' class='pinDescription'>Loading...</div>");
                            this._currentpin.SetTitle("");
                        }
                    }
                }
                var box = this._map;
            }
            else if (this._map.GetShapeByID(e.elementID).GetType() == VEShapeType.Polyline) {
                this._map.ShowInfoBox(this._map.GetShapeByID(e.elementID));
            }
        }
    },
    _getAJAXContent: function() {
        this._loadingPin = true;
        /// <summary>
        ///   Request content for popup.
        /// </summary>  

        //call the web service
        this._service.GetPushPin_outages(this._currentpin.Bounds, this._currentindex, Function.createDelegate(this, this._OnContentSucceeded), Utility.OnFailed, this._currentpin.GetID());
    },


    _OnContentSucceeded: function(result, ID) {

        /// <summary>
        ///   Receive content for popup.
        /// </summary>  
        /// <param name="result">The webservice result object - JSON SitePinData</param>  
        /// <param name="ID">The popup ID associated with this call</param>

        //verify this is the data for the current popup.
        if (ID == this._currentpin.GetID()) {
            if (this._map.GetMapMode() == VEMapMode.Mode3D) {
                //3D mode fails to be able to retrieve the div we placed earlier so resort to setting the title and description only
                this._currentpin.SetTitle(result.SiteObject.SiteId);
                this._currentpin.SetDescription("<div class = 'pinDescription'>" + result.SiteObject.SiteName) + "</div>";
            } else {
                //create the content element
                var el = document.createElement("div");
                el.className = "siteOutagePopup";
                var totalRecords = parseInt(result.TotalRecords);
                if (totalRecords > 1) {
                    el.innerHTML = (this._currentindex + 1) + " of " + result.TotalRecords + " sites";
                }
                el.innerHTML += "<div class='pinDescription'><iframe class='' frameborder='0' width=540 height=220 scrolling='no' src=\"SiteOutagesPopup.aspx?nominalid="
                        + result.SiteObject.NominalId + "\"></iframe></div>";
                var popup = $get(this._PopupPrefix + ID);
                if (popup != null) {
                    //Set the position on the screen IF the bottom of the pop up is out of the map
                    var currentTopString = popup.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.style.top;
                    var currentTopNumber = new Number(currentTopString.substring(0, currentTopString.length - 2));
                    var bottomLine = currentTopNumber + 290; /* 290 is the height of the iFrame*/
                    var extraSpace = 50;
                    var browser = Utility.DetectBrowser();
                    if (browser != "ie7")
                        extraSpace = 55;
                    var mapHeight = this._map.GetHeight() - extraSpace;
                    var finalPos = mapHeight - 290;

                    if (bottomLine > mapHeight)
                        popup.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.style.top = finalPos + "px";
                    //clear loading and attach the content
                    popup.innerHTML = "";
                    popup.appendChild(el);


                    //----------------------
                    //Code Block to fix a width issue on certain versions of FF that don't resize automatically the popups #MI,09/08/10
                    // We can't overwrite "customInfoBox-body" in the css as it is shared by at least 2 popup sorts with diffrent widths
                    //I think Alan was doing the same kind of trick with the popup.parentElement.parentElement.parentElement..(etc.), but the way below is safer)
                    var currentEl = popup;
                    for (var i = 0; i < 10; i++) {
                        if (currentEl.parentNode.className.indexOf("customInfoBox-body") != -1) {
                            currentEl.parentNode.style.width = "560px";
                            break;
                        }
                        currentEl = currentEl.parentNode;
                        if (currentEl == null) break;
                    }
                    //----------------------

                }

                if (result.TotalRecords > 1) {
                    //prev / next functionlaity
                    var prevButton = document.createElement("span");
                    prevButton.innerHTML = "<< Previous&nbsp;";
                    el.appendChild(prevButton);
                    Sys.UI.DomElement.addCssClass(prevButton, "ActionButton");
                    if (this._currentindex > 0) {
                        $addHandler(prevButton, "click", Function.createDelegate(this, this._PreviousRecord));
                    } else {
                        Sys.UI.DomElement.addCssClass(prevButton, "ButtonDisabled");
                    }
                    var nextButton = document.createElement("span");
                    nextButton.innerHTML = "Next >>";
                    el.appendChild(nextButton);
                    Sys.UI.DomElement.addCssClass(nextButton, "ActionButton");

                    if (this._currentindex < (result.TotalRecords - 1)) {
                        $addHandler(nextButton, "click", Function.createDelegate(this, this._NextRecord));
                    }
                    else {
                        Sys.UI.DomElement.addCssClass(nextButton, "ButtonDisabled");
                    }
                }
            }
        }

        this._loadingPin = false;
    },



    _MouseClickHandler: function(e) {
        if (e.rightMouseButton) {
            var latLon = this._map.PixelToLatLong(new VEPixel(e.mapX, e.mapY));
            //START - New req 2.3 (16/11/2009): Force ‘postal’ addresses
            /*if ((this.buy4NowLatitude != null) && (this.buy4NowLongitude != null))
            {
            var initialPointlatLon = new VELatLong(this.buy4NowLatitude, this.buy4NowLongitude);
            //Calculate distance
            var dblDistance = Utility.CalcDistance(initialPointlatLon.Latitude, initialPointlatLon.Longitude, latLon.Latitude, latLon.Longitude, Utility.EarthRadiusInKilometers);
            if (dblDistance > this.buy4NowMaxPinpointDist)
            {
            var answer = confirm("You are pinpointing your location " + dblDistance.toFixed(1) + " Km from your initial search")
            if (!answer)
            return;
            }
            }*/
            //END - New req 2.3 (16/11/2009): Force ‘postal’ addresses
            this.buy4NowAddressLine1 = this.buy4NowEnteredAddressLine1;
            this.buy4NowAddressLine2 = this.buy4NowEnteredAddressLine2;
            this.buy4NowAddressLine3 = this.buy4NowEnteredAddressLine3;
            this.buy4NowAddressLine4 = this.buy4NowEnteredAddressLine4;
            this.buy4NowAddressLine5 = this.buy4NowEnteredAddressLine5;
            this.buy4NowAddressLine6 = "";
            this.buy4NowGeoAddressId = "";
            this.buy4NowLatitude = latLon.Latitude;
            this.buy4NowLongitude = latLon.Longitude;
            this.buy4NowAddressMatched = false;
            var addressRep = "<b>" + this.buy4NowEnteredAddressLine1 + "</b><br/>"
                + "<b>" + this.buy4NowEnteredAddressLine2 + "</b><br/>"
                + "<b>" + this.buy4NowEnteredAddressLine3 + "</b><br/>"
                + "<b>" + this.buy4NowEnteredAddressLine4 + "</b><br/>"
                + "<b>" + this.buy4NowEnteredAddressLine5 + "</b>";
            addressRep = addressRep.replace(/%/g, "'");

            // Prev to Alan - var txtPopUp = "You entered:<table><tr><td>" + addressRep + "&#160;&#160;</td>" + "<tr><td align='right'>";
            // START - Alan (Search buildings around)
            if (this.buy4NowPinpointUsingBuildingSearch == true) {
                //this.ButtonPinpointOnMap.style.display = 'none';

                var latLon = this._map.PixelToLatLong(new VEPixel(e.mapX, e.mapY));
                //LOAD PINS
                map.LoadPinsOnMapForLatLong(latLon.Latitude, latLon.Longitude);

                return;
            }
            else {
                //var latLon = this._map.PixelToLatLong(new VEPixel(e.clientX, e.clientY))
                var latLon = this._map.PixelToLatLong(new VEPixel(e.mapX, e.mapY));
                this.buy4NowAddressLine1 = this.buy4NowEnteredAddressLine1;
                this.buy4NowAddressLine2 = this.buy4NowEnteredAddressLine2;
                this.buy4NowAddressLine3 = this.buy4NowEnteredAddressLine3;
                this.buy4NowAddressLine4 = "";
                this.buy4NowAddressLine5 = "";
                this.buy4NowAddressLine6 = "";
                this.buy4NowGeoAddressId = "";
                this.buy4NowLatitude = latLon.Latitude;
                this.buy4NowLongitude = latLon.Longitude;
                this.buy4NowAddressMatched = false;
                var addressRep = "<b>" + this.buy4NowEnteredAddressLine1 + "</b><br/>" + "<b>" + this.buy4NowEnteredAddressLine2 + "</b><br/>" + "<b>" + this.buy4NowEnteredAddressLine3 + "</b>";
                addressRep = addressRep.replace(/%/g, "'");

                var txtPopUp = "You entered:<table><tr><td>" + addressRep + "&#160;&#160;</td>" +
                                           "<tr><td align='right'>";
                //txtPopUp += "<div class='linkLabel' style='width:250px' onclick='AcceptBuy4Now();'>Accept</div></td></tr></table>";
                txtPopUp += "<input id='ButtonAccept' type='button' value='Accept' onclick='AcceptBuy4Now();' style='font-family:Tahoma' />";
                txtPopUp += "</td></tr></table>";
                this.AddBuy4NowPin(latLon.Latitude, latLon.Longitude, txtPopUp, false);
            }
            //END - Alan
            txtPopUp += "<input id='ButtonAccept' type='button' value='Accept' onclick='AcceptBuy4Now();' style='font-family:Tahoma' />";
            txtPopUp += "</td></tr></table>";
            this.AddBuy4NowPin(latLon.Latitude, latLon.Longitude, txtPopUp, false);
        }
    },
    AddBuy4NowPin: function(lat, lon, txtPopUp, centerAndZoom) {
        //Delete shapes of the search result layer
        this._buy4NowSearchResultLayer.DeleteAllShapes();
        //Create the new shape for the search result
        var loc = new VELatLong(lat, lon);
        this.searchShape = new VEShape(VEShapeType.Pushpin, loc);
        this.searchShape.id = "SearchResult";
        this.searchShape.SetCustomIcon("<div class='myPushpin'></div>");
        this.searchShape.SetDescription(txtPopUp);
        //add the new shape to the search result layer
        this._buy4NowSearchResultLayer.AddShape(this.searchShape);
        if (centerAndZoom == true) {
            this._map.SetCenterAndZoom(new VELatLong(lat, lon), 15);
        }
        //Show info box if NBS - CHANGED, NOW SHOW ALWAYS
        //if ((this._accessMode == "NBS") || (this._accessMode == "NBSAgents"))
        this._map.HideInfoBox();
        var pixel = this._map.LatLongToPixel(this._map.GetCenter(), this._map.GetZoomLevel());
        this._map.ShowInfoBox(this.searchShape, new VEPixel(pixel.x - 7, pixel.y));
    },
    RemoveAddBuy4NowPin: function() {
        //HideInfoBox
        this._map.HideInfoBox();
        //Delete shapes of the search result layer
        this._buy4NowSearchResultLayer.DeleteAllShapes();
    },
    CancelRequestNBS: function(address, submitted) {
        if (!submitted) {
            // "Request NBS notification" is shown according to the web config key "EnableRequestNBS"
            if (Utility.ConvertStringToBoolean(this._enableRequestNBS)) {
                this.addressPin.SetDescription("<table><tr><td>" + address + "&#160;&#160;</td></tr>" +
                    "<tr><td align='right'><div class='linkLabel' style='width:250px' onclick='RemoveAddressPin();'>Delete pin from map</div></td></tr>" +
                    "<tr><td align='right'><div class='linkLabel' style='width:250px' onclick=\"RequestNBSNotification('" + address + "');\">Request NBS Notification</div></td></tr></table></div>");
            }
            else {
                this.addressPin.SetDescription("<table><tr><td>" + address + "&#160;&#160;</td>" +
                                           "<tr><td align='right'><div class='linkLabel'  style='width:250px'  onclick='RemoveAddressPin();'>Delete pin from map</div></td></tr></table></div>");
            }
        }
        else
            this.addressPin.SetDescription("<table><tr><td>" + address + "&#160;&#160;</td>" +
                                           "<tr><td align='right'><div class='linkLabel' style='width:250px'  onclick='RemoveAddressPin();'>Delete pin from map</div></td></tr></table></div>");

        //Hide and Show to see the changes
        this._map.HideInfoBox();
        this._map.ShowInfoBox(this.addressPin);
    },
    RequestNBSSubmitted: function(address) {
        this.addressPin.SetDescription("<table><tr><td>" + address + "&#160;&#160;</td>" +
                                        "<tr><td align='right'><div class='linkLabel' style='width:250px' onclick='RemoveAddressPin();'>Delete pin from map</div></td></tr></table></div>");
    },
    RemoveAddressPin: function() {
        //HideInfoBox
        this._map.HideInfoBox();
        //Delete shapes of the search result layer
        this._layer.DeleteAllShapes();
    },
    AcceptBuy4NowFromBuilding: function(addressline1, addressline2, adddressline3, addressline4, addressline5, addressline6, geodirectoryid, latitude, longitude, addressmatched) {
        this.buy4NowAddressLine1 = addressline1;
        this.buy4NowAddressLine2 = addressline2;
        this.buy4NowAddressLine3 = adddressline3;
        this.buy4NowAddressLine4 = addressline4;
        this.buy4NowAddressLine5 = addressline5;
        this.buy4NowAddressLine6 = addressline6;
        this.buy4NowGeoAddressId = geodirectoryid;
        this.buy4NowLatitude = latitude;
        this.buy4NowLongitude = longitude;
        this.buy4NowAddressMatched = addressmatched;
        this.AcceptBuy4Now();
    },
    AcceptBuy4Now: function() {
        this.OnUpdateBuy4NowSuccessDelegate = Function.createDelegate(this, this.OnUpdateBuy4NowSuccess);
        this.OnUpdateBuy4NowFailedDelegate = Function.createDelegate(this, this.OnUpdateBuy4NowFailed);
        ThreeIreland.Services.AddressLinkService.UpdateBuy4NowRetCovEnv(this.buy4NowEnteredAddressLine1, DecodeStringPF(this.buy4NowAddressLine1), DecodeStringPF(this.buy4NowAddressLine2), DecodeStringPF(this.buy4NowAddressLine3), DecodeStringPF(this.buy4NowAddressLine4), DecodeStringPF(this.buy4NowAddressLine5), DecodeStringPF(this.buy4NowAddressLine6), this.buy4NowGeoAddressId, this.buy4NowLatitude, this.buy4NowLongitude, this.buy4NowAddressMatched, this.OnUpdateBuy4NowSuccessDelegate, this.OnUpdateBuy4NowFailedDelegate);
    },
    OnGetBuildingsByIDSuccess: function(myresult) {
        // START - Alan (Search buildings around)         
        if (this.buy4NowInPinpointMode == true && this.buy4NowPinpointUsingBuildingSearch == true) {
            //this.ButtonPinpointOnMap.style.display = 'inline'; // Show cancel button
        }  // END - Alan
        if (myresult.length == 0) {
            // START - Alan (Search buildings around)         
            if (this.buy4NowInPinpointMode == true && this.buy4NowPinpointUsingBuildingSearch == true) {
                this.DivBuy4NowInstructions2.innerHTML = 'No buildings found. Try another location'; // No buildings found
                UpdateInstructions("No buildings found", "Try another location"); //Defined in CoveragePublicPage.aspx.js
            } // END - Alan
            else //START - Error in buy4now for "the hills, herbertstown, limerick" (no buildong in DB but 6 deliverypoins in addresslink: We display the BLUE PIN)
            {
                var addressRep = this.buy4NowEnteredAddressLine1 != "" ? ("<b>" + this.buy4NowEnteredAddressLine1 + "</b><br/>") : "";
                addressRep += this.buy4NowEnteredAddressLine2 != "" ? ("<b>" + this.buy4NowEnteredAddressLine2 + "</b><br/>") : "";
                addressRep += this.buy4NowEnteredAddressLine3 != "" ? ("<b>" + this.buy4NowEnteredAddressLine3 + "</b><br/>") : "";
                addressRep += this.buy4NowEnteredAddressLine4 != "" ? ("<b>" + this.buy4NowEnteredAddressLine4 + "</b><br/>") : "";
                addressRep += this.buy4NowEnteredAddressLine5 != "" ? ("<b>" + this.buy4NowEnteredAddressLine5 + "</b><br/>") : "";
                addressRep = addressRep.replace(/%/g, "'");
                var address = this.buy4NowEnteredAddressLine1 != "" ? (this.buy4NowEnteredAddressLine1 + ", ") : "";
                address += this.buy4NowEnteredAddressLine2 != "" ? (this.buy4NowEnteredAddressLine2 + ", ") : "";
                address += this.buy4NowEnteredAddressLine3 != "" ? (this.buy4NowEnteredAddressLine3 + ", ") : "";
                address += this.buy4NowEnteredAddressLine4 != "" ? (this.buy4NowEnteredAddressLine4 + ", ") : "";
                address += this.buy4NowEnteredAddressLine5 != "" ? (this.buy4NowEnteredAddressLine5 + ", ") : "";
                this.LoadPinOnMap(this.buy4NowEnteredLat, this.buy4NowEnteredLon, addressRep, address, this.buy4NowEnteredGeoAddressId);
            } //END - Error in buy4now
            return;
        }
        else // START - Alan (Search buildings around)         
        {
            // Buildings found
            if (this.buy4NowInPinpointMode == true && this.buy4NowPinpointUsingBuildingSearch == true) {
                this.DivBuy4NowInstructions2.innerHTML = 'Hover over a building to select your exact address or right click somewhere else';
                document.getElementById("pinPointAddressDivTitle").innerHTML = "Choose a building";
                UpdateInstructions("Choose an address", "hover your mouse on a point <img src='../../Images/house-blue-small.gif'></img> and click your address in the pop-up"); //Defined in CoveragePublicPage.aspx.js

            }
        } // END - Alan

        var clusterOptions = new VEClusteringOptions();
        clusterOptions.Icon = new VECustomIconSpecification();
        this.OnClusterDelegate = Function.createDelegate(this, this.OnCluster);
        clusterOptions.Callback = this.OnClusterDelegate;
        this._buy4NowSearchResultLayer.SetClusteringConfiguration(VEClusteringType.Grid, clusterOptions);

        var addressShapeArray = new Array();
        for (i = 0; i < myresult.length; i++) {
            var loc = new VELatLong(myresult[i].Latitude, myresult[i].Longitude);
            addressShapeArray[i] = new VEShape(VEShapeType.Pushpin, loc);
            addressShapeArray[i].id = "SearchResult";
            addressShapeArray[i].SetCustomIcon("<img src='../../Images/house-blue-small.gif'/>");
            addressShapeArray[i].PinDetails = myresult[i];
            var geodirectoryid = myresult[i].BuildingId;
            addressShapeArray[i].SetDescription(this.GetBuildingDescription(myresult[i].Address1, myresult[i].Address2, myresult[i].Address3, myresult[i].Address4, myresult[i].Address5, myresult[i].Address6, geodirectoryid, myresult[i].Latitude, myresult[i].Longitude));
        }

        this._buy4NowSearchResultLayer.AddShape(addressShapeArray);
        this._map.SetMapView(addressShapeArray);
    },
    GetBuildingDescription: function(address1, address2, address3, address4, address5, address6, geodirectoryid, latitude, longitude, clusterdivid) {
        //Change to uppercase
        address1 = address1.toUpperCase();
        address2 = address2.toUpperCase();
        address3 = address3.toUpperCase();
        address4 = address4.toUpperCase();
        address5 = address5.toUpperCase();
        address6 = address6.toUpperCase();

        var description = "<div style='height: 100px' class = 'pinDescriptionPublic'>";
        description += "<b>" + DecodeStringPFDisplay(address1) + "</b><br/>";
        description += "<b>" + DecodeStringPFDisplay(address2) + "</b><br/>";
        description += "<b>" + DecodeStringPFDisplay(address3) + "</b><br/>";
        description += "<b>" + DecodeStringPFDisplay(address4) + "</b><br/>";
        description += "<b>" + DecodeStringPFDisplay(address5) + "</b><br/>";
        description += "<b>" + DecodeStringPFDisplay(address6) + "</b><br/>";
        description += "<input id='ButtonAccept' type='button' value='Accept' onclick='AcceptBuy4NowFromBuilding(\"" + EncodeStringPF(address1) + "\",\"" + EncodeStringPF(address2) + "\",\"" + EncodeStringPF(address3) + "\",\"" + EncodeStringPF(address4) + "\",\"" + EncodeStringPF(address5) + "\",\"" + EncodeStringPF(address6) + "\",\"" + geodirectoryid + "\"," + latitude + "," + longitude + ", true);' style='font-family:Tahoma' />";
        //if (clusterdivid != undefined && clusterdivid != null && clusterdivid != "")
        //description += "<a href='javascript:SetBuildingDescriptionShortPublic(\"" + clusterdivid + "\",\"" + address1 + "\",\"" + address2 + "\",\"" + address3 + "\",\"" + address4 + "\"," + latitude + "," + longitude + ")'>Back</a>";
        description += "</div>";

        return description;
    },
    GetBuildingDescriptionShort: function(divid, address1, address2, address3, address4, address5, address6, geodirectoryid, latitude, longitude) {
        //Change to uppercase
        address1 = address1.toUpperCase();
        address2 = address2.toUpperCase();
        address3 = address3.toUpperCase();
        address4 = address4.toUpperCase();
        address5 = address5.toUpperCase();
        address6 = address6.toUpperCase();

        var description = "<a href='javascript:SetBuildingDescriptionPublic(\"" + divid + "\",\"" + EncodeStringPF(address1) + "\",\"" + EncodeStringPF(address2) + "\",\"" + EncodeStringPF(address3) + "\",\"" + EncodeStringPF(address4) + "\",\"" + EncodeStringPF(address5) + "\",\"" + EncodeStringPF(address6) + "\",\"" + geodirectoryid + "\"," + latitude + "," + longitude + ")'>";
        description += DecodeStringPFDisplay(address1);
        if (address2 != "") description += "," + DecodeStringPFDisplay(address2);
        if (address3 != "") description += "," + DecodeStringPFDisplay(address3);
        if (address4 != "") description += "," + DecodeStringPFDisplay(address4);
        if (address5 != "") description += "," + DecodeStringPFDisplay(address5);
        if (address6 != "") description += "," + DecodeStringPFDisplay(address6);
        description += "</a>";
        return description;
    },
    GetBuildingDescriptionWithBuildingNums: function(divid, address1, address2, address3, address4, address5, address6, buildingsNum, geodirectoryid, latitude, longitude, boundingBox, sameAddressAtMaxZoom) {
        //Change to uppercase
        address1 = address1.toUpperCase();
        address2 = address2.toUpperCase();
        address3 = address3.toUpperCase();
        address4 = address4.toUpperCase();
        address5 = address5.toUpperCase();
        address6 = address6.toUpperCase();

        var descStart = "";
        var descBody = "";
        var descEnd = "";
        var boundingBoxStr = null;
        var acceptBtn = "";


        //dependng on the building Num
        if (buildingsNum > 1) {
            descEnd = " (" + buildingsNum + " buildings)";
            boundingBoxStr = "\"" + boundingBox[0].Latitude + "&" +
                            boundingBox[0].Longitude + "&" +
                            boundingBox[1].Latitude + "&" +
                            boundingBox[1].Longitude + "\"";
        }
        else
            descEnd = " (1 building)";

        if (sameAddressAtMaxZoom) {
            descEnd += "<br/>Building drawn on mouse over.";
            descStart = "<a onmouseover=\"javascript:ShowBuildingAsRedDot(" + latitude + ", " + longitude + ");\"  href='javascript:SetBuildingDescriptionPublic(\"" + divid + "\",\"" + EncodeStringPF(address1) + "\",\"" + EncodeStringPF(address2) + "\",\"" + EncodeStringPF(address3) + "\",\"" + EncodeStringPF(address4) + "\",\"" + EncodeStringPF(address5) + "\",\"" + EncodeStringPF(address6) + "\",\"" + geodirectoryid + "\"," + latitude + "," + longitude + "," + boundingBoxStr + ")'>";
        }
        else
            descStart = "<a href='javascript:SetBuildingDescriptionPublic(\"" + divid + "\",\"" + EncodeStringPF(address1) + "\",\"" + EncodeStringPF(address2) + "\",\"" + EncodeStringPF(address3) + "\",\"" + EncodeStringPF(address4) + "\",\"" + EncodeStringPF(address5) + "\",\"" + EncodeStringPF(address6) + "\",\"" + geodirectoryid + "\"," + latitude + "," + longitude + "," + boundingBoxStr + ")'>";


        //common code
        descBody += DecodeStringPFDisplay(address1);
        if (address2 != "") descBody += "," + DecodeStringPFDisplay(address2);
        if (address3 != "") descBody += "," + DecodeStringPFDisplay(address3);
        if (address4 != "") descBody += "," + DecodeStringPFDisplay(address4);
        if (address5 != "") descBody += "," + DecodeStringPFDisplay(address5);
        if (address6 != "") descBody += "," + DecodeStringPFDisplay(address6);

        return descStart + descBody + descEnd + acceptBtn + "</a>";
    },
    ShowBuilding: function(lat, lon) {
        this._buildingsLayer.DeleteAllShapes();
        var loc = new VELatLong(lat, lon);
        //Add the pin
        var building = new VEShape(VEShapeType.Pushpin, loc);
        if (Sys.Browser.agent == Sys.Browser.InternetExplorer && Sys.Browser.version == 6)
            building.SetCustomIcon("<div class=\"myBuildingPushpinIE6\"></div>");
        else
            building.SetCustomIcon("<div  class=\"myBuildingPushpin\"></div>");

        this._buildingsLayer.AddShape(building);
    },
    ZoomToAddress: function(lat, lon, desc, boundingBox) {
        //Idenfity house
        var selectedShape = null;
        for (var i = 0; i < this._buy4NowSearchResultLayer.GetShapeCount(); i++) {
            var currShape = this._buy4NowSearchResultLayer.GetShapeByIndex(i);
            if ((currShape.Latitude == lat)
                && (currShape.Longitude == lon)) {
                selectedShape = currShape;
                selectedShape.SetDescription(desc);
                this._selectedShape = selectedShape;
                break;
            }
        }
        //Zoom & Show info box 
        if (boundingBox == null) //Show if 1 address with that name
        {
            //Zoom to the pin
            this._map.HideInfoBox();
            this._map.SetCenterAndZoom(new VELatLong(lat, lon), 20);
            setTimeout('ShowInfoBox();', 300);
            //Show if 1 address with that name
            //this._map.ShowInfoBox(selectedShape);
        }
        else {
            //Zoom to the pin
            this._map.SetMapView(boundingBox);
            //Hide info box
            this._map.HideInfoBox();
        }
    },
    GetFinalShapesList: function(cluster) {
        cluster.Shapes.sort(function(a, b) { return StringCompare(a.PinDetails.Latitude, b.PinDetails.Latitude) });

        var toDelete = new Array();
        var pixelsDiff = 20 * (20 - this._map.GetZoomLevel());
        for (var j = 0; j < cluster.Shapes.length; j++) {
            var pixelPinA = this._map.LatLongToPixel(new VELatLong(cluster.Shapes[j].PinDetails.Latitude, cluster.Shapes[j].PinDetails.Longitude));
            for (var l = 0; l < cluster.Shapes.length; l++) {
                //CAN THEY BE UNCLUSTERED??
                try {
                    var pixelPinB = this._map.LatLongToPixel(new VELatLong(cluster.Shapes[l].PinDetails.Latitude, cluster.Shapes[l].PinDetails.Longitude));
                    var horizontalDiff = (pixelPinA.x - pixelPinB.x) * -1;
                    var verticalDiff = (pixelPinA.y - pixelPinB.y) * -1;

                    if ((horizontalDiff > pixelsDiff) || (verticalDiff > pixelsDiff)) {
                        var exists = false;
                        for (var k = 0; k < toDelete.length; k++) {
                            if (toDelete[k] == j)
                                exists = true;
                        }
                        if (!exists)
                            toDelete.push(j);
                    }
                }
                catch (ex) {
                    alert(ex);
                }
            }
        }

        //remove buildings
        for (var z = toDelete.length - 1; z >= 0; z--)
            cluster = this.RemoveFromCluster(cluster, toDelete[z]);

        //remove cluster if only 1 item
        if (cluster.Shapes.length == 1)
            cluster = this.RemoveFromCluster(cluster, 0);

        return cluster;
    },
    RemoveFromCluster: function(cluster, index) {
        //Add building to EXTRA layer
        var loc = new VELatLong(cluster.Shapes[index].Latitude, cluster.Shapes[index].Longitude);
        var buildingShape = new VEShape(VEShapeType.Pushpin, loc);
        buildingShape.SetCustomIcon("<img src='../../Images/house-blue-small.gif'/>");
        buildingShape.id = "SearchResult";
        buildingShape.PinDetails = cluster.Shapes[index].PinDetails;
        var geodirectoryid = cluster.Shapes[index].PinDetails.BuildingId;
        buildingShape.SetDescription(this.GetBuildingDescription(cluster.Shapes[index].PinDetails.Address1,
                                               cluster.Shapes[index].PinDetails.Address2,
                                               cluster.Shapes[index].PinDetails.Address3,
                                               cluster.Shapes[index].PinDetails.Address4,
                                               cluster.Shapes[index].PinDetails.Address5,
                                               cluster.Shapes[index].PinDetails.Address6,
                                               geodirectoryid,
                                               cluster.Shapes[index].PinDetails.Latitude,
                                               cluster.Shapes[index].PinDetails.Longitude));
        this._reclusterLayer.AddShape(buildingShape);
        //Remove from cluster
        cluster.Shapes.splice(index, 1);
        //return list
        return cluster;
    },
    OnCluster: function(clusters) {
        this._reclusterLayer.DeleteAllShapes();
        for (var i = 0; i < clusters.length; ++i) {
            var finalCluster = clusters[i];

            if ((this._map.GetZoomLevel() >= 17) && (clusters[i].Shapes.length > 1))
                finalCluster = this.GetFinalShapesList(clusters[i]);

            if (finalCluster.Shapes.length > 0) {
                //A. SET THE ICON
                var clusterShape = finalCluster.GetClusterShape();
                if (Sys.Browser.agent == Sys.Browser.InternetExplorer && Sys.Browser.version == 6)
                    clusterShape.SetCustomIcon("<div class=\"myAddressClusteredPushpinIE6\"></div><div class=\"numClusterLbl\">" + clusters[i].Shapes.length + "</div>");
                else
                    clusterShape.SetCustomIcon("<div  class=\"myAddressClusteredPushpin\"></div><div class=\"numClusterLbl\">" + clusters[i].Shapes.length + "</div>");
                clusterShape.SetTitle("");

                //B. SET THE DESCRIPTION
                finalCluster.Shapes.sort(function(a, b) { return StringCompare(a.PinDetails.Address1, b.PinDetails.Address1) });
                var desc = this.GetClusteredShapeDesc(finalCluster.Shapes) + "</div>";
                clusterShape.SetDescription(desc);
            }
            else {
                //If NO item in the cluster --> don't show shape
                var clusterShape = finalCluster.GetClusterShape();
                clusterShape.Hide();
            }
        }
    },
    GetClusteredShapeDesc: function(clusteredBuildings) {
        //Init the description
        var description = "<div style='height: 120px; overflow: auto;' id='clusterContent_" + i + "'>";
        description += "Select Address From List:<br/>";

        //1. Get the array of adresses to DISPLAY
        var displayAddresses = new Array(); // adrress description, numItems, shape, bounding box if more than 1 add
        for (var j = 0; j < clusteredBuildings.length; j++) {
            //We need to  avoid duplicated addresses in the popup. See code below:
            var itemDesc = DecodeStringPFDisplay(clusteredBuildings[j].PinDetails.Address1);
            if (clusteredBuildings[j].PinDetails.Address2 != "") itemDesc += "," + DecodeStringPFDisplay(clusteredBuildings[j].PinDetails.Address2);
            if (clusteredBuildings[j].PinDetails.Address3 != "") itemDesc += "," + DecodeStringPFDisplay(clusteredBuildings[j].PinDetails.Address3);
            if (clusteredBuildings[j].PinDetails.Address4 != "") itemDesc += "," + DecodeStringPFDisplay(clusteredBuildings[j].PinDetails.Address4);
            if (clusteredBuildings[j].PinDetails.Address5 != "") itemDesc += "," + DecodeStringPFDisplay(clusteredBuildings[j].PinDetails.Address5);
            if (clusteredBuildings[j].PinDetails.Address6 != "") itemDesc += "," + DecodeStringPFDisplay(clusteredBuildings[j].PinDetails.Address6);

            //Add to display array on increment the address count of the cluster
            var exists = false;
            var sameAddressAtMaxZoom = false;
            for (var l = 0; l < displayAddresses.length; l++) {
                if (itemDesc.toUpperCase() == displayAddresses[l][0]) {
                    //if zoom MAX show accpt btn
                    if (this._map.GetZoomLevel() >= 19) {
                        //Show all the equal address in case zoom is MAX
                        exists = false;
                        //same add at  max zoom (on mouse over --> building is shown)
                        sameAddressAtMaxZoom = true;
                        displayAddresses[l][4] = true;
                    }
                    else {
                        //Increment COUNTER
                        displayAddresses[l][1]++;
                        //EXPAND THE BOUNDING BOX
                        var boundingBox = displayAddresses[l][3];
                        //LAT > NW.LAT
                        if (clusteredBuildings[j].PinDetails.Latitude > boundingBox[0].Latitude)
                            boundingBox[0].Latitude = clusteredBuildings[j].PinDetails.Latitude;
                        //LAT < SE.LAT
                        if (clusteredBuildings[j].PinDetails.Latitude < boundingBox[1].Latitude)
                            boundingBox[1].Latitude = clusteredBuildings[j].PinDetails.Latitude;
                        //LON > NW.LON
                        if (clusteredBuildings[j].PinDetails.Longitude > boundingBox[0].Longitude)
                            boundingBox[0].Longitude = clusteredBuildings[j].PinDetails.Longitude;
                        //LAT < SE.LAT
                        if (clusteredBuildings[j].PinDetails.Longitude < boundingBox[1].Longitude)
                            boundingBox[1].Longitude = clusteredBuildings[j].PinDetails.Longitude;
                        displayAddresses[l][3] = boundingBox;
                        //SET EXISTS TO TRUE
                        exists = true;
                    }
                }

            }
            if (!exists) {
                var displayEltm = new Array();
                displayEltm[0] = itemDesc.toUpperCase();
                displayEltm[1] = 1;
                displayEltm[2] = clusteredBuildings[j];
                var boundingBox = new Array();
                /*NW*/boundingBox[0] = new VELatLong(clusteredBuildings[j].PinDetails.Latitude, clusteredBuildings[j].PinDetails.Longitude);
                /*SE*/boundingBox[1] = new VELatLong(clusteredBuildings[j].PinDetails.Latitude, clusteredBuildings[j].PinDetails.Longitude);
                displayEltm[3] = boundingBox;
                displayEltm[4] = sameAddressAtMaxZoom;
                displayAddresses.push(displayEltm);
            }
        }
        //2. Create descriptions
        for (var m = 0; m < displayAddresses.length; m++) {
            //CODE TO INSERT ADDRESS
            var buildingsNum = displayAddresses[m][1];
            var shape = displayAddresses[m][2];
            var boundingBox = displayAddresses[m][3];
            var sameAddressAtMaxZoom = displayAddresses[m][4];
            var geodirectoryid = shape.PinDetails.BuildingId;
            description += this.GetBuildingDescriptionWithBuildingNums("clusterContent_" + i,
                                    shape.PinDetails.Address1,
                                    shape.PinDetails.Address2,
                                    shape.PinDetails.Address3,
                                    shape.PinDetails.Address4,
                                    shape.PinDetails.Address5,
                                    shape.PinDetails.Address6,
                                    buildingsNum,
                                    geodirectoryid,
                                    shape.PinDetails.Latitude,
                                    shape.PinDetails.Longitude,
                                    boundingBox,
                                    sameAddressAtMaxZoom) + "<br>";
            description += "<hr align='left' width='200' color='#D1D1D1'/>";
        }
        return description;
    },
    OnGetBuildingsByIDFailed: function() {
        //alert("pf failed");
    },
    OnUpdateBuy4NowSuccess: function(coverageTypeAndEnv) {
        if (document.getElementById('ButtonAcceptAddress') != null) {
            document.getElementById('add1').value = this.buy4NowAddressLine1;
            document.getElementById('add2').value = this.buy4NowAddressLine2;
            document.getElementById('add3').value = this.buy4NowAddressLine3;
            document.getElementById('add4').value = this.buy4NowAddressLine4;
            document.getElementById('add5').value = this.buy4NowAddressLine5;
            document.getElementById('add6').value = this.buy4NowAddressLine6;
            document.getElementById('geoAdd').value = this.buy4NowGeoAddressId;
            document.getElementById('lat').value = this.buy4NowLatitude;
            document.getElementById('lon').value = this.buy4NowLongitude;
            document.getElementById('cov').value = coverageTypeAndEnv[0];
            document.getElementById('addMatch').value = this.buy4NowAddressMatched ? 1 : 0;
            document.getElementById('env').value = coverageTypeAndEnv[1];

            document.getElementById('ButtonAcceptAddress').click();
        }
        else
            document.getElementById('ctl00_ContentPlaceHolder1_ButtonAcceptAddress').click();
    },
    OnUpdateBuy4NowFailed: function(err) {
        alert(err);
    },
    _HideWater: function() {
        this._map.HideTileLayer("ThreeWater");
    },
    _ShowWater: function() {
        this._map.ShowTileLayer("ThreeWater");
    },
    _HideIslands: function() {
        this._map.HideTileLayer("ThreeIslands");
    },
    _ShowIslands: function() {
        this._map.ShowTileLayer("ThreeIslands");
    },
    _HideNBSCoverage: function() {
        this._TurnOffTileLayer("ThreeNBSDED");
    },
    _ShowNBSCoverage: function() {
        this._TurnOnTileLayer("ThreeNBSDED");
    },
    _HideNBSCPESCoverage: function() {
        this._TurnOffTileLayer("ThreeNBSDEDCPES");
    },
    _ShowNBSCPESCoverage: function() {
        if (this._map.GetTileLayerByID("ThreeNBSDEDCPES") != null) this._TurnOnTileLayer("ThreeNBSDEDCPES"); //#MI added this conditional test because of errors caused by the fact the layer didn't exist
    },
    _Hide3GCoverage: function() {
        this._TurnOffTileLayer("Three3GCoverage");
    },
    _Show3GCoverage: function() {
        this._TurnOnTileLayer("Three3GCoverage");
    },
    _Hide3GFuture: function() {
        this._TurnOffTileLayer("Three3GFuture");
    },
    _Show3GFuture: function() {
        this._TurnOnTileLayer("Three3GFuture");
    },
    _Hide3GCoverageInOut: function() {
        this._TurnOffTileLayer("ThreeInOut");
    },
    _Show3GCoverageInOut: function() {
        this._TurnOnTileLayer("ThreeInOut");
    },
    _ChangeMapStyleHandler: function(e) {
        this._RefreshCurrentTileLayer();
    },
    _RefreshCurrentTileLayer: function() {
        this._TurnOnTileLayer(this.TileLayerCurrentlyShown);
    },
    //For select list layers
    _TurnOnTileLayer: function(layername) {
        var browserVersion = Utility.DetectBrowser();
        //Hide all layers
        if (this._accessMode == "NBS") {
            this._map.HideTileLayer("ThreeNBSDED");
            if (browserVersion == "ie6") {
                this._map.HideTileLayer("ThreeNBSDEDr");
                this._map.HideTileLayer("ThreeNBSDEDa");
                this._map.HideTileLayer("ThreeNBSDEDh");
            }
            //this._map.HideTileLayer("ThreeNBSDED");
        }
        else if (this._accessMode == "NBSAgents") {
            if (this._map.GetTileLayerByID("ThreeNBSDEDCPES") != null) this._map.HideTileLayer("ThreeNBSDEDCPES");
            if (browserVersion == "ie6") {
                this._map.HideTileLayer("ThreeNBSDEDCPESr");
                this._map.HideTileLayer("ThreeNBSDEDCPESa");
                this._map.HideTileLayer("ThreeNBSDEDCPESh");
            }
            //this._map.HideTileLayer("ThreeNBSDED");
        }
        else if (this._accessMode == "Agents") {
            this._map.HideTileLayer("ThreeInOut");
            if (browserVersion == "ie6") {
                this._map.HideTileLayer("ThreeInOutr");
                this._map.HideTileLayer("ThreeInOuta");
                this._map.HideTileLayer("ThreeInOuth");
            }
            this._map.HideTileLayer("Three3GFuture");
            if (browserVersion == "ie6") {
                this._map.HideTileLayer("Three3GFuturer");
                this._map.HideTileLayer("Three3GFuturea");
                this._map.HideTileLayer("Three3GFutureh");
            }
            this._map.HideTileLayer("Three2GCoverage");
            if (browserVersion == "ie6") {
                this._map.HideTileLayer("Three2GCoverager");
                this._map.HideTileLayer("Three2GCoveragea");
                this._map.HideTileLayer("Three2GCoverageh");
            }
            if (layername == "SitesUnavailable") {
                layername = "";
                this._sitesUnavailableLayer.Show();
            }
            else this._sitesUnavailableLayer.Hide(); //~~
            //this._map.HideTileLayer("Three3GCoverage");
        }
        else if (this._accessMode == "") {
            this._map.HideTileLayer("ThreeInOut");
            if (browserVersion == "ie6") {
                this._map.HideTileLayer("ThreeInOutr");
                this._map.HideTileLayer("ThreeInOuta");
                this._map.HideTileLayer("ThreeInOuth");
            }
            this._map.HideTileLayer("Three2GCoverage");
            if (browserVersion == "ie6") {
                this._map.HideTileLayer("Three2GCoverager");
                this._map.HideTileLayer("Three2GCoveragea");
                this._map.HideTileLayer("Three2GCoverageh");
            }

            //this._map.HideTileLayer("Three3GCoverage");
            //this._map.HideTileLayer("SitesUnavailable");
        }

        //Set layer shown to null
        this.TileLayerCurrentlyShown = null;
        this.TileLayerCurrentlyShown = layername;
        //Show selected layer
        if (layername != null && layername != "") {
            if (browserVersion == "ie6") {
                layername = layername + this._map.GetMapStyle();
            }
            if (this._map.GetTileLayerByID(layername) != null) this._map.ShowTileLayer(layername);
        }
    },
    _TurnOffTileLayer: function(layername) {
        var browserVersion = Utility.DetectBrowser();
        this._map.HideTileLayer(layername);
        if (browserVersion == "ie6") {
            this._map.HideTileLayer(layername + "r");
            this._map.HideTileLayer(layername + "a");
            this._map.HideTileLayer(layername + "h");
        }
        this.TileLayerCurrentlyShown = false;
    },
    Dispose: function() {
        /// <summary>
        ///   cleans up all objects. Detaches all events.
        /// </summary>
        if (this._map != null && this._accessMode != "Buy4Now") {
            this._map.DetachEvent("onchangeview", this.GetTileServerLayersDelegate);

            /*this._map.DetachEvent("onmouseover", this.PinHoverDelegate);
            this._map.DetachEvent("onclick", this.PinHoverDelegate);
            this._map.Dispose();*/
        }
        this._service = null;
        this._mapArgs = null;

        this._map = null;
        this._pinID = null;
        this._zoomlevel = null;
        this._layer = null;

        //popup specific
        this._PopupPrefix = null;
        this._currentpin = null;
        this._currentindex = null;

        this.GetSitePinDataDelegate = null;
        this.PinHoverDelegate = null;
    },

    _GetSitePinData: function() { //Added 28/07/2010, MI
        /// <summary>
        ///   Get the latest map data from the webservice.
        /// </summary>

        //encode the current map bounds
        var points = new Array();
        var zoom;

        if (this._map.GetMapStyle() == VEMapStyle.Birdseye) {
            //set zoomlevel      
            zoom = 19;
            var be = this._map.GetBirdseyeScene();
            var rect = be.GetBoundingRectangle();
            points.push(rect.TopLeftLatLong);
            points.push(rect.BottomRightLatLong);

        } else {
            var view = this._map.GetMapView();
            points.push(view.TopLeftLatLong);
            points.push(view.BottomRightLatLong);

            //get zoomlevel
            zoom = this._map.GetZoomLevel();

        }
        var bounds = Utility.createEncodings(points);
        if (this._zoomlevel != zoom) {
            //clear existing pins
            //this._layer.DeleteAllShapes();
            this._zoomlevel = zoom;
        }

        //clear existing pins
        this._sitesUnavailableLayer.DeleteAllShapes();

        //call webservice
        this._service.GetClusteredMapData_outages(bounds, zoom, Function.createDelegate(this, this._OnMapDataSucceeded), Function.createDelegate(this, this._OnMapFailed));
    },

    _OnMapFailed: function() {
        alert("Could not read sites data. Automatic retry in " + refreshInt + " seconds.");
    },

    _OnMapDataSucceeded: function(results) {
        //alert(results.length + ' results found');

        /// <summary>
        ///   Receive data for map.
        /// </summary>
        /// <param name="result">The webservice result object - Optimised CSV string</param>

        //RESTART REFRESHING TIMER
        RestartRefreshTimer();

        if (results == null) {
            alert("Could not read sites data. Automatic retry in " + refreshInt + " seconds.");
            return;
        }

        //clear existing pins just before drawing the new ones
        this._sitesUnavailableLayer.DeleteAllShapes();
        //decode pins
        var result = results.split(",")
        var otherInfo = result[1];
        var otherInfoSplit = otherInfo.split('|');
        var totalPins = parseInt(otherInfoSplit[0]);
        var totalCells = parseInt(otherInfoSplit[1]);
        var sitesUnavailable = parseInt(otherInfoSplit[2]);
        var locs = Utility.decodeLine(result[0]);

        //Show number of sites on screen
        var divTxt = document.getElementById("divStatus");
        var msg = "";
        if (totalPins > 1 || totalPins < 1) {
            msg = totalPins + " sites";
        }
        else {
            msg = totalPins + " site";
        }

        if (totalCells > 1 || totalCells < 1) {
            msg += " " + totalCells + " cells";
        }
        else {
            msg += " " + totalCells + " cell";
        }

        if (sitesUnavailable > 1 || sitesUnavailable < 1) {
            msg += " (" + sitesUnavailable + " sites unavailable)";
        }
        else {
            msg += " (" + sitesUnavailable + " site unavailable)";
        }

        //divTxt.innerHTML = msg;

        //clear existing pins
        //do this before AJAX call now
        //this._sitesUnavailableLayer.DeleteAllShapes();

        var zoomLevel = this._map.GetZoomLevel();
        //CALCULATE THE RADIUS DEPENDING ON THE ZOOM
        if (locs.length > 0) {
            var siteRadius = this.CalculateRadiusByZoom(40, locs[0]); //we work with the same radius for all the cells in the site
            var R = 6371; // earth's mean radius in km
            var siteAngularDistance = parseFloat(siteRadius) / R;  // d = angular distance covered on earth's surface*/

            //add new sites
            for (locIndex = 0; locIndex < locs.length; locIndex++) {
                var loc = locs[locIndex];
                var resultInfo = result[locIndex + 2].split('|||');
                var bounds = resultInfo[0];
                // DEBUG START
                // Show region covered by clusters
                //            var decodedBounds = Utility.decodeLine(bounds);
                //            var pb1 = new VELatLong(parseFloat(decodedBounds[0].Latitude), parseFloat(decodedBounds[0].Longitude));
                //            var pb2 = new VELatLong(parseFloat(decodedBounds[0].Latitude), parseFloat(decodedBounds[1].Longitude));
                //            var pb3 = new VELatLong(parseFloat(decodedBounds[1].Latitude), parseFloat(decodedBounds[1].Longitude));
                //            var pb4 = new VELatLong(parseFloat(decodedBounds[1].Latitude), parseFloat(decodedBounds[0].Longitude));
                //            var pbAll = new Array(4);
                //            pbAll[0] = pb1;
                //            pbAll[1] = pb2;
                //            pbAll[2] = pb3;
                //            pbAll[3] = pb4;
                //            var boundsShape = new VEShape(VEShapeType.Polygon, pbAll);
                //            boundsShape.HideIcon();
                //            this._sitesUnavailableLayer.AddShape(boundsShape);
                // DEBUG END

                var isClustered = Utility.ConvertStringToBoolean(resultInfo[1]);
                var newShape;
                if (isClustered == true) {
                    var pinsClustered = resultInfo[2];

                    newShape = new ThreeIreland.SiteShape(pinsClustered, //Number of pins in the cluster
                                                "#FFFFFF",     //Color for the number of pins in the cluster
                                                this.TileLayerShown, //If there is a tile layer shown, force opacity to 1
                                                zoomLevel,           //ZOOM
                                                loc.Latitude, loc.Longitude, // LAT + LON
                                                "blackCentre"    //CENTRAL IMG
                                                );


                    //                    newShape = new ThreeIreland.SiteShape(pinsClustered, //Number of pins in the cluster
                    //                                                "#FFFFFF",     //Color for the number of pins in the cluster
                    //                                                this.TileLayerShown, //If there is a tile layer shown, force opacity to 1
                    //                                                zoomLevel,           //ZOOM
                    //                                                loc.Latitude, loc.Longitude, // LAT + LON
                    //                                                "blackCentre",    //CENTRAL IMG
                    //                                                40, 40, 40,     //CELLS 1-3 RADIUS
                    //                                                30, 30, 30,     //CELLS 3-6 RADIUS
                    //                                                20, 20, 20,     //CELLS 7-9 RADIUS
                    //                                                255, 0, 0, 0.3, //CELL 1 COLOR + OPACITY
                    //                                                0, 255, 0, 0.3, //CELL 2 COLOR + OPACITY
                    //                                                0, 0, 255, 0.3, //CELL 3 COLOR + OPACITY
                    //                                                255, 0, 0, 0.5, //CELL 4 COLOR + OPACITY
                    //                                                0, 255, 0, 0.5, //CELL 5 COLOR + OPACITY
                    //                                                0, 0, 255, 0.5, //CELL 6 COLOR + OPACITY
                    //                                                255, 0, 0, 1,   //CELL 7 COLOR + OPACITY
                    //                                                0, 255, 0, 1,   //CELL 8 COLOR + OPACITY
                    //                                                0, 0, 255, 1,   //CELL 9 COLOR + OPACITY
                    //                                                45, 135, 225,   // CELLS 1-3 ANGLES
                    //                                                45, 135, 225,   // CELLS 4-6 ANGLES
                    //                                                45, 135, 225,   // CELLS 7-9 ANGLES
                    //                                                -1,             // SITE CONGESTION LEVEL
                    //                                                -1, -1, -1,     // CELLS CONGESTION LEVELS
                    //                                                false, false, false,  // CELLS 1-3 VISIBILITY
                    //                                                false, false, false,  // CELLS 4-6 VISIBILITY
                    //                                                false, false, false,  // CELLS 7-9 VISIBILITY
                    //                                                0);
                }
                else {
                    var siteAvailability = resultInfo[3];
                    var centreImage;
                    switch (siteAvailability) {
                        case "Live":
                            centreImage = "greenCentre";
                            break;
                        case "Unavailable":
                            centreImage = "redCentre2";
                            break;
                        case "TotallyUnavailable":
                            centreImage = "redCentre";
                            break;
                        case "PartiallyDown": centreImage = "yellowCentre";
                            break;
                        case "RecentlyUnavailable":
                            centreImage = "amberCentre";
                            break;
                        case "PlannedLessThan3Months":
                            centreImage = "lightBlueCentre";
                            break;
                        case "PlannedGreaterThan3Months":
                            centreImage = "darkBlueCentre";
                            break;
                        case "NotInService":
                            centreImage = "greyCentre";
                            break;
                    }

                    var siteCongestionLevel = parseInt(resultInfo[4]);

                    var data = resultInfo[5].split('~');
                    var azimuths = new Array();
                    for (var i = 0; i < data.length; i++) {
                        azimuths[i] = parseFloat(data[i]);
                    }

                    var data = resultInfo[6].split('~');
                    var cellCongestions = new Array();
                    for (var i = 0; i < data.length; i++) {
                        cellCongestions[i] = parseInt(data[i]);
                    }

                    var cellAvailabilities = resultInfo[7].split('~');
                    var localCellIDs = resultInfo[8].split('~');

                    newShape = new ThreeIreland.SiteShape("", //Number of pins in the cluster
                                                "", //Color for the number of pins in the cluster
                                                this.TileLayerShown, //If there is a tile layer shown, force opacity to 1
                                                zoomLevel, //ZOOM
                                                loc.Latitude, loc.Longitude, // LAT + LON
                                                centreImage,    //CENTRAL IMG
                                                azimuths,
                                                siteCongestionLevel, //SITE CONGESTION LEVEL
                                                cellCongestions, //CONGESTION LEVELS
                                                siteAngularDistance,
                                                cellAvailabilities, siteAngularDistance);
                }
                newShape.AddToShapeLayer(this._sitesUnavailableLayer, false);
                newShape.CentreShape.Bounds = bounds;
            }
        }

        // Retrieve the layers' dates, if any has changed we update the this._tileLayers Object as well as the map's tile layers URLs. This will ensure that the latest tile layer is being correctly loaded
        this._UpdateLayerDates();

    },
    //CALCULATE RADIUS BY ZOOM: Obtains the "correct" radius depending on the zoom
    //------------------------  of the map.
    CalculateRadiusByZoom: function(radius, loc) {
        //LatLon in the centre of the site
        var ll1 = new VELatLong(loc.Latitude, loc.Longitude);
        //LatLon of the point situated at a distance from the centre in pixels
        //of the longitude of the radius received as parameter (at 90°)
        var ll2 = this.RadiusPixelToLatLon(radius, loc);
        //Get the Distance in Kms
        var distance = this.Distance(ll2, ll1);
        //Return the distance in Kms
        return distance;
    },
    //CONVERT PIXEL: We convert our radius in pixels to LatLon
    //-------------- depending on the zoom level.
    RadiusPixelToLatLon: function(radPixels, loc) {
        //CENTRE LatLon
        var centre = new VELatLong(loc.Latitude, loc.Longitude);
        //CELL LatLon (calculate the Latitude --> Longitude = contre.Longitude)
        var pixelCentre = this._map.LatLongToPixel(centre, this._map.GetZoomLevel());
        var pixelRadius = new VEPixel(pixelCentre.x, pixelCentre.y - radPixels);
        var radLatLon = this._map.PixelToLatLong(pixelRadius);
        //RETURN
        return radLatLon;
    },
    //DISTANCE: calculates the distance in kms between 2 ponts
    //--------- //http://viavirtualearth.com/Wiki/distance.ashx
    Distance: function(p1, p2) {
        p1.Latitude = this.LatLonToRadians(p1.Latitude);
        p1.Longitude = this.LatLonToRadians(p1.Longitude);
        p2.Latitude = this.LatLonToRadians(p2.Latitude);
        p2.Longitude = this.LatLonToRadians(p2.Longitude);
        var R = 6371; // earth's mean radius in km
        var dLat = p2.Latitude - p1.Latitude;
        var dLong = p2.Longitude - p1.Longitude;
        var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
		    Math.cos(p1.Latitude) * Math.cos(p2.Latitude) * Math.sin(dLong / 2) * Math.sin(dLong / 2);
        var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        var disKm = R * c;
        return disKm;
    },
    //CONVERT LatLon: convert lat/long in degrees to radians
    //--------------- http://viavirtualearth.com/Wiki/distance.ashx
    LatLonToRadians: function(point) {
        return point * Math.PI / 180;
    },

    RefreshSites: function() { //function called by the timer (interval expired
        this._GetSitePinData();
    },
    _PreviousRecord: function() {
        if (!this._loadingPin) {
            this._currentindex--;
            this._getAJAXContent();
        }
    },

    _NextRecord: function() {
        if (!this._loadingPin) {
            this._currentindex++;
            this._getAJAXContent();
        }
    }

}

function replaceDivContent(div, content)
{
    alert("replace div: " + div + " with: " + content);
}


function StringCompare(a, b)
{
    if (a < b) return -1;
    if (a > b) return 1;
    if (a == b) return 0;
}

function CleanStringPF(a)
{
    if (a == undefined || a == null || a == "") return "";
    return a.replace(/'/g, "%");
}

function EncodeStringPF(a)
{
    if (a == undefined || a == null || a == "") return "";
    return a.replace(/'/g, "%APOS%");
}

function DecodeStringPF(a)
{
    if (a == undefined || a == null || a == "") return "";
    return a.replace("%APOS%", escape("'"));
}

function DecodeStringPFDisplay(a)
{
    if (a == undefined || a == null || a == "") return "";
    return a.replace("%APOS%", "'");
}
function IntervalExpired() {
     //alert("Refresh the sites after " + refreshInterval + " seconds.");
    map.RefreshSites();
}


ThreeIreland.PublicMap.registerClass('ThreeIreland.PublicMap', null, Sys.IDisposable);

if (typeof (Sys) !== "undefined") Sys.Application.notifyScriptLoaded();

