﻿/// <reference path="MicrosoftAjax.js" />
/// <reference path="Country.js" />
/// <reference path="Continent.js" />
/// <reference path="Countries.js" />
/// <reference path="Continents.js" />

// compressed function pointers for our dynamically loaded javascript
var l = VELatLong;
var s = VEShape;
var p = VEShapeType.Polygon;
var a = null;
var c = null;

Type.registerNamespace("fdi");

fdi.NavMap = function (element) {
    this._navmap = null;
    this._navmapinfo = null;
    this._continents = null;
    this._countries = null;
    this._mapcontrols = null;
    this._popupcountryurl = null;
    this._requiredZoomLevel = 3;
    this._standardZoomLevel = 3;
    this._maxZoomLevel = 5;
    this._lastCenterPoint;
    this._ibover = false;

    fdi.NavMap.initializeBase(this, [element]);
}

fdi.NavMap.prototype = {
    initialize: function () {
        this._continents = new fdi.Continents();
        this._countries = new fdi.Countries();
        this._navmapinfo = new fdi.NavMapInfo();

        $("#loadingMap").show();
        this._navmapinfo.CenterLatLong = new VELatLong(136.0, 37.0);
        this._createMapControl();
        this._attachEvents();

        //initialize global function pointers
        a = Function.createDelegate(this, this.AddContinent);
        c = Function.createDelegate(this, this.AddCountry);
    },
    //methods
    //#region
    _createMapControl: function () {
        var options = new VEMapOptions();
        options.LoadBaseTiles = false;

        this._navmap = new VEMap(this.get_element().id);
        this._navmap.LoadMap(null, 1, VEMapStyle.Road, false, VEMapMode.Mode2D, true, 0, options);
        this._navmap.SetCredentials("AoHiOE6KF3iNWiY2oanehot9wh3wZWKBlx4le9iVB-SRog8xF_aDHeVkXKV3c5nO");
        this._navmap.vemapcontrol.SetAnimationEnabled(false);
        this._navmap.EnableShapeDisplayThreshold(false);
        this._navmap.HideScalebar();
        this._navmap.HideDashboard();


        this._navmap.AttachEvent("onmousemove", new Function.createDelegate(this, this._navMapShapeMouseMoveHander));
        this._navmap.AttachEvent("onmouseover", new Function.createDelegate(this, this._navMapShapeMouseOverHander));

        this._navmap.AttachEvent("onclick", new Function.createDelegate(this, this._navMapShapeMouseClickHander));
        //this._navmap.AttachEvent("onmousewheel", this._navDisable);
        this._navmap.AttachEvent("onchangeview", new Function.createDelegate(this, this._onChangeView));
        this._navmap.AttachEvent("onendzoom", new Function.createDelegate(this, this._onEndZoom));

        //ero events
        $(".ero").mouseenter(new Function.createDelegate(this, this._ibMouseEnterHander))
        $(".ero").mouseleave(new Function.createDelegate(this, this._ibMouseLeaveHander))

        //create map controls
        this._mapcontrols = $create(fdi.MapControls, { Zoom: 1, MaxZoom: 5 }, null, null, $get("mapcontrols"));
        this._addMainTileLayer();
        this._navmap.HideBaseTileLayer();
        $(".map").addClass("MSVE_MapContainerImage");
        window.ero.setBoundingArea(new Msn.VE.Geometry.Point(0, 0), new Msn.VE.Geometry.Point(document.body.clientWidth, document.body.clientHeight + 600));

    },
    _addMainTileLayer: function () {
        var tileSourceSpec =
			new VETileSourceSpecification(
				"main", "", 1, null, 1, 5, new Function.createDelegate(this, this._getMainTileLayerPath)
        // tileSourceId, tileSource, numServers, bounds, minZoom, maxZoom, getTilePath, opacity, zindex
			);

        this._navmap.AddTileLayer(tileSourceSpec, true);

    },
    _getMainTileLayerPath: function (tileContext) {
        // Bing numbers quad keys from the top left of the map, GeoServer/GeoWebCache starts bottom left
        // so we need to reverse the y co-ordinates
        var numTiles = Math.pow(4, tileContext.ZoomLevel);
        var maxXYOnTile = Math.sqrt(numTiles);
        var magicNumber = Math.floor((tileContext.ZoomLevel / 2) - 0.5)
        var maxXYOnFolder = Math.pow(2, magicNumber);
        var digitsOnFolder = Math.floor(tileContext.ZoomLevel / 6) + 1;
        var digitsOnTile = digitsOnFolder * 2;

        var x = tileContext.XPos;
        var y = this._reverseY(tileContext.YPos, tileContext.ZoomLevel);

        var folderX = Math.floor(x / Math.pow(2, tileContext.ZoomLevel - magicNumber));
        var folderY = Math.floor(y / Math.pow(2, tileContext.ZoomLevel - magicNumber));

        folderX = this._padValue(folderX, digitsOnFolder);
        folderY = this._padValue(folderY, digitsOnFolder);

        x = this._padValue(x, digitsOnTile);
        y = this._padValue(y, digitsOnTile);

        var url = "/tiles/navmap/EPSG_900913_" + this._padValue(tileContext.ZoomLevel, 2) + "/" + folderX + "_" + folderY + "/" + x + "_" + y + ".png";

        return url;
    },
    _padValue: function (value, totalDigits) {
        value = value.toString();
        var pd = '';
        if (totalDigits > value.length) {
            for (i = 0; i < (totalDigits - value.length); i++) {
                pd += '0';
            }
        }
        return pd + value.toString();
    },
    _reverseY: function (value, zoomLevel) {
        var max = Math.pow(2, zoomLevel) - 1;
        return Math.abs((value - max));
    },
    _attachEvents: function () {
        $("#zoomToWorld").click(new Function.createDelegate(this, this._removeContinentFilter));
        $("#zoomToWorld").hide();
        $("#filterContinent").click(new Function.createDelegate(this, this._removeContinentFilter));
        $("#filterCountry").click(new Function.createDelegate(this, this._removeCountryFilter));
        $("#loadingMap").hide();

        //attach live event to all continent and country link hover events
        $("#continentList a").live("mouseover", new Function.createDelegate(this, this._onContinentMouseOver)).live("mouseout", new Function.createDelegate(this, this._onContinentMouseOut)).live("click", new Function.createDelegate(this, this._onContinentClicked));
        $("#searchResults a[class='countrylink']").live("mouseover", new Function.createDelegate(this, this._onCountryMouseOver)).live("mouseout", new Function.createDelegate(this, this._onCountryMouseOut)); ;

        //subscribe to map control events
        this._mapcontrols.add_zoomChanged(new Function.createDelegate(this, this._controlsZoomChanged));
        this._mapcontrols.add_onPan(new Function.createDelegate(this, this._controlsPanned));
        this._mapcontrols.add_mapstyleChanged(new Function.createDelegate(this, this._controlsMapStyleChanged));
    },
    CloseInfobox: function () {
        this._navmap.HideInfoBox();
    },
    //#endregion

    //event handlers
    //#region
    _navMapShapeMouseMoveHander: function (e) {
        var layerOver;
        $get("navMap").style.cursor = "pointer";
        if (e.elementID != null) {
            var shape = this._navmap.GetShapeByID(e.elementID);
            layerOver = shape.GetShapeLayer();

            if (this._navmapinfo.LayerLastOver == null) {
                fdi.ShapeUtils.HighLightShapesInLayer(layerOver);
                this._navmapinfo.LayerLastOver = layerOver;
            }
            if (this._navmapinfo.LayerLastOver != shape.GetShapeLayer()) {
                fdi.ShapeUtils.HighLightShapesInLayer(layerOver);
                fdi.ShapeUtils.UnHighLightShapesInLayer(this._navmapinfo.LayerLastOver);
                this._navmapinfo.LayerLastOver = layerOver;
            }
            if (this._navmapinfo.ZoomedTo == "central-and-south-america"
                && $.inArray(this._navmapinfo.LayerLastOver.EWUrlName, this._navmapinfo.NavMapSpecialCaribbeanUrlNames) > -1) {
                if (this._navmapinfo.NavMapSpecialCaribbeanHighLighted) {
                    this._navmapinfo.NavMapSpecialCaribbeanHighLighted = false;
                    fdi.ShapeUtils.UnHighLightShapesInLayerArray(this._navmapinfo.NavMapSpecialCaribbeanLayers);
                }
            }
            if (this._navmapinfo.ZoomedTo == "asia"
                && $.inArray(this._navmapinfo.LayerLastOver.EWUrlName, this._navmapinfo.NavMapSpecialSouthEastAsiaUrlNames) > -1) {
                if (this._navmapinfo.NavMapSpecialSouthEastAsiaHighLighted) {
                    this._navmapinfo.NavMapSpecialSouthEastAsiaHighLighted = false;
                    fdi.ShapeUtils.UnHighLightShapesInLayerArray(this._navmapinfo.NavMapSpecialSouthEastAsiaLayers);
                }
            }
            if (layerOver.EWType == "country") {
                if (this._navmapinfo.ZoomedTo == "central-and-south-america"
                    && $.inArray(layerOver.EWUrlName, this._navmapinfo.NavMapSpecialCaribbeanUrlNames) > -1) {
                    if (!this._navmapinfo.NavMapSpecialCaribbeanHighLighted) {
                        this._navmapinfo.NavMapSpecialCaribbeanHighLighted = true;
                        fdi.ShapeUtils.HighLightShapesInLayerArray(this._navmapinfo.NavMapSpecialCaribbeanLayers);
                    }
                }
                if (this._navmapinfo.ZoomedTo == "asia"
                    && $.inArray(layerOver.EWUrlName, this._navmapinfo.NavMapSpecialSouthEastAsiaUrlNames) > -1) {
                    if (!this._navmapinfo.NavMapSpecialSouthEastAsiaHighLighted) {
                        this._navmapinfo.NavMapSpecialSouthEastAsiaHighLighted = true;
                        fdi.ShapeUtils.HighLightShapesInLayerArray(this._navmapinfo.NavMapSpecialSouthEastAsiaLayers);
                    }
                }
            }
        } else {
            if (this._navmapinfo.LayerLastOver != null) {
                if (this._navmapinfo.ZoomedTo == "central-and-south-america"
                && $.inArray(this._navmapinfo.LayerLastOver.EWUrlName, this._navmapinfo.NavMapSpecialCaribbeanUrlNames) > -1) {
                    if (this._navmapinfo.NavMapSpecialCaribbeanHighLighted) {
                        this._navmapinfo.NavMapSpecialCaribbeanHighLighted = false;
                        fdi.ShapeUtils.UnHighLightShapesInLayerArray(this._navmapinfo.NavMapSpecialCaribbeanLayers);
                    }
                } else if (this._navmapinfo.ZoomedTo == "asia"
                && $.inArray(this._navmapinfo.LayerLastOver.EWUrlName, this._navmapinfo.NavMapSpecialSouthEastAsiaUrlNames) > -1) {
                    if (this._navmapinfo.NavMapSpecialSouthEastAsiaHighLighted) {
                        this._navmapinfo.NavMapSpecialSouthEastAsiaHighLighted = false;
                        fdi.ShapeUtils.UnHighLightShapesInLayerArray(this._navmapinfo.NavMapSpecialSouthEastAsiaLayers);
                    }
                } else {
                    fdi.ShapeUtils.UnHighLightShapesInLayer(this._navmapinfo.LayerLastOver);
                }
                this._navmapinfo.LayerLastOver = null;
            }
        }
    },
    _controlsMapStyleChanged: function (s, args) {
        //set map style
        this._mctrchangedstyle = true;
        this._navmap.SetMapStyle(args.get_newSelection() == "r" ? VEMapStyle.Road : VEMapStyle.Hybrid);
        if (args.get_newSelection() == "r") {
            this._navmap.ShowTileLayer(this._navmap.GetTileLayerByIndex(0).ID);
            this._navmap.HideBaseTileLayer();
        }
        else {
            this._navmap.HideTileLayer(this._navmap.GetTileLayerByIndex(0).ID);
            this._navmap.ShowBaseTileLayer();
        }
    },
    _navMapShapeMouseClickHander: function (e) {
        var continent;
        var country;

        if (e.elementID != null) {
            var shape = this._navmap.GetShapeByID(e.elementID);
            var layerOver = shape.GetShapeLayer();

            if (layerOver.EWType == "continent") {
                //this._countries.HideAll();
                //this._continents.HideAll();
                $("#loadingMap").show();
                fdi.ShapeUtils.UnHighLightShapesInLayer(layerOver);
                continent = this._continents.GetContinentByUrlName(layerOver.EWContinent.UrlName);
                this._navmapinfo.ZoomedTo = layerOver.EWContinent.UrlName;
                this._requiredZoomLevel = continent.Zoom;
                this._setFilters('', '', continent.UrlName, continent.Name);

                if (!continent.CountriesLoaded) {
                    $.getScript("scripts/mapdata/shapes-" + continent.UrlName + ".js",
					    new Function.createDelegate(this, function () {
					        this._navmapinfo.LayerLastOver = null;
					        continent.CountriesLoaded = true;
					        this._setFilterList(continent.Countries._countries);

					    }),
					    true
				    );
                    continent.CountriesLoaded = true;
                }
                else {
                    this._setFilterList(continent.Countries._countries);
                }
                this._navmap.SetCenterAndZoom(new VELatLong(continent.Lat, continent.Lon), continent.Zoom); //has to be after the data loading has started otherwise filters wont be set
            }
            if (layerOver.EWType == "country") {
                if (this._navmapinfo.ZoomedTo == "central-and-south-america"
                    && $.inArray(layerOver.EWUrlName, this._navmapinfo.NavMapSpecialCaribbeanUrlNames) > -1) {
                    this._navmap.SetCenterAndZoom(this._navmapinfo.NavMapSpecialCaribbeanCenter, this._navmapinfo.NavMapSpecialCaribbeanZoomLevel);

                    this._navmapinfo.ZoomedTo = "caribbean";
                    if (this._navmapinfo.NavMapSpecialCaribbeanHighLighted) {
                        this._navmapinfo.NavMapSpecialCaribbeanHighLighted = false;
                        fdi.ShapeUtils.UnHighLightShapesInLayerArray(this._navmapinfo.NavMapSpecialCaribbeanLayers);
                    }
                } else if (this._navmapinfo.ZoomedTo == "asia"
                    && $.inArray(layerOver.EWUrlName, this._navmapinfo.NavMapSpecialSouthEastAsiaUrlNames) > -1) {
                    this._navmap.SetCenterAndZoom(this._navmapinfo.NavMapSpecialSouthEastAsiaCenter, this._navmapinfo.NavMapSpecialSouthEastAsiaZoomLevel);

                    this._navmapinfo.ZoomedTo = "south-east-asia";
                    if (this._navmapinfo.NavMapSpecialSouthEastAsiaHighLighted) {
                        this._navmapinfo.NavMapSpecialSouthEastAsiaHighLighted = false;
                        fdi.ShapeUtils.UnHighLightShapesInLayerArray(this._navmapinfo.NavMapSpecialSouthEastAsiaLayers);
                    }
                } else {
                    $get("continentActionlink").href =
                    "/search/country/" + layerOver.EWContinentUrlName +
                    "/" + layerOver.EWUrlName;
                    $("#continentActionlink").trigger("click");
                    //not in tab any more $("#tab2Anchor").trigger("click");
                    country = this._countries.GetCountryByUrlName(layerOver.EWUrlName);
                    continent = this._continents.GetContinentByUrlName(layerOver.EWContinentUrlName);
                    this._setFilters(country.UrlName, country.Name, continent.UrlName, continent.Name);

                }
            }
        } else {
            //alert(navMap.GetCenter() + " " +this._ navmap.GetZoomLevel());
        }
    },

    _navMapShapeMouseOverHander: function (e) {
        if (e.elementID != null) {
            var shape = this._navmap.GetShapeByID(e.elementID);
            var layerOver = shape.GetShapeLayer();

            if (layerOver.EWType == "country") {

                this._popupcountryurl = layerOver.EWUrlName; //save so we can check still same popup when data returned

                //get country infobox details
                $.ajax({
                    url: "search/countrystats/" + layerOver.EWContinentUrlName + "/" + layerOver.EWUrlName,
                    type: "GET",
                    dataType: "json",
                    cache: true,
                    success: new Function.createDelegate(this, this._countryStatsLoaded)
                });

                

                //show infobox
                shape.SetDescription("<div id='popupcontent'>loading please wait...</div>");
                this._navmap.HideInfoBox();

                //check if centroid actual visible, otherwise use mouse position
                var cent = this._simplePolygonCentroid(shape.GetPoints());
                if (this._isInRectangle(this._navmap.GetMapView(), cent)) {
                    this._navmap.ShowInfoBox(shape,cent);
                }
                else {
                    this._navmap.ShowInfoBox(shape, new VEPixel(e.mapX, e.mapY));
                }


            }
        }
        else {
            if (!this._ibover) {
                //close infobox
                this._navmap.HideInfoBox();
            }
        }
    },



    _ibMouseEnterHander: function (e) {
        this._ibover = true;
    },

    _ibMouseLeaveHander: function (e) {
        this._ibover = false;
    },

    _navDisable: function () {
        return true;
    },
    _onEndZoom: function (e) {
        if (e.zoomLevel > this._maxZoomLevel) {
            this._navmap.SetZoomLevel(this._maxZoomLevel);
        }
    },
    _onChangeView: function () {

        //update zoom on controls
        this._mapcontrols.set_Zoom(this._navmap.GetZoomLevel());
        //this._countries.HideAll();
        //this._continents.HideAll();
        if (this._navmap.GetZoomLevel() != this._requiredZoomLevel) {
            this._requiredZoomLevel = this._standardZoomLevel;
        }
        if (this._navmap.GetCenter() != this._lastCenterPoint) {
            if (!$('#filterContinent').is(':hidden') && !$('#filterCountry').is(':hidden')) {
                this._setFilters("", "", "", "");
            }
        }

        if (this._navmap.GetZoomLevel() == 1) {
            this._countries.HideAll();
            this._continents.ShowAll();
            $("#zoomToWorld").hide()
        }
        else {
            if (this._navmap.GetZoomLevel() > 2) {
                this._continents.HideAll();
                this._countries.ShowAll();
            }
            $("#zoomToWorld").show();
        }

        this._lastCenterPoint = this._navmap.GetCenter();

        var view = this._navmap.GetMapView();
        if (this._navmap.GetZoomLevel() >= this._requiredZoomLevel) {

            var continentsInView = this._continents.GetInArea(view);

            for (i = 0; i < continentsInView.length; i++) {
                continent = this._continents.GetContinentByUrlName(continentsInView[i].UrlName);
                $("#continentList").hide();
                if (continent.CountriesLoaded) {
                    this._navmapinfo.LayerLastOver = null;

                    $("#loadingMap").hide();

                } else {
                    $("#loadingMap").show();
                    $.getScript("scripts/mapdata/shapes-" + continentsInView[i].UrlName + ".js",
					    new Function.createDelegate(this, function () {
					        this._navmapinfo.LayerLastOver = null;
					        continent.CountriesLoaded = true;
					        $("#zoomToWorld").show();
					        $("#loadingMap").hide();

					    }),
					    true
				    );
                    continent.CountriesLoaded = true;
                }

            }
            if ($('#filterContinent').is(':hidden') && $('#filterCountry').is(':hidden')) {
                this._setFilterList(this._countries.ShowInArea(view));
            }
            else {
                this._countries.ShowInArea(view)
            }

        }
        else {
            this._continents.ShowInArea(view);

            $("#continentList").show();
            $("#searchResults").html("");
        }
        this._setBackground();

    },

    _setBackground: function () {
        if (this._navmap.GetZoomLevel() == 1) {
            if (this._navmap.GetMapStyle() == VEMapStyle.Road) {
                $(".map").removeClass("MSVE_apContainer");
                $(".map").addClass("MSVE_MapContainerImage");
                $(".map").removeClass("MSVE_MapContainerBlue");
            }
            else {
                $(".map").removeClass("MSVE_MapContainerImage");
                $(".map").removeClass("MSVE_MapContainer");
                $(".map").addClass("MSVE_MapContainerBlue");
            }
        }
        else {
            $(".map").removeClass("MSVE_MapContainerImage");
            $(".map").addClass("MSVE_MapContainer");
            $(".map").removeClass("MSVE_MapContainerBlue");

        }
    },

    _setFilterList: function (countries) {
        countries.sort(function (a, b) {
            var nameA = a.Name.toLowerCase(), nameB = b.Name.toLowerCase()
            if (nameA < nameB) //sort string ascending
                return -1
            if (nameA > nameB)
                return 1
            return 0 //default return value (no sorting)
        });
        $("#searchResults").html("");
        for (var index in countries) {
            var url = "/area/" + countries[index].Layer.EWContinentUrlName + "/" + countries[index].Layer.EWUrlName;
            var item = "<ul class='listviewselections'><li><a class='countrylink' id='" + countries[index].Layer.EWUrlName + "' href='" + url + "'>" + unescape(countries[index].Name) + "</a></li></ul>";
            $("#searchResults").append(item);
        }
    },

    _navMapZoomToWorld: function () {
        $("#loadingMap").show();
        this._navmap.SetCenterAndZoom(this._navmapinfo.CenterLatLong, 1);
        $("#loadingMap").hide();
        this._countries.HideAll();
        this._continents.ShowAll();
        this._navmapinfo.ZoomedTo = "world";
        $("#zoomToWorld").hide();
        $("#tab1Anchor").trigger("click");
    },

    _removeCountryFilter: function () {
        $("#filterCountry").hide();
        $get("continentActionlink").href =
                    "/search/country/" + this._navmapinfo.continentUrlName;
        $("#continentActionlink").trigger("click");
    },
    _removeContinentFilter: function () {
        //zoom map back out
        this._navMapZoomToWorld();
        $("#searchResults").text("");
        this._setFilters('', '', '', '');
    },
    _onContinentMouseOver: function (e) {
        //get continent shape and highlight
        var l = this._findLayerByTitle("continent_" + e.target.id);
        if (l) fdi.ShapeUtils.HighLightShapesInLayer(l);
    },
    _onCountryMouseOver: function (e) {
        //get country shape and highlight
        var l = this._findLayerByTitle("country_" + e.target.id);
        if (l) fdi.ShapeUtils.HighLightShapesInLayer(l);
    },
    _onContinentMouseOut: function (e) {
        //get country shape and unhighlight
        var l = this._findLayerByTitle("continent_" + e.target.id);
        if (l) fdi.ShapeUtils.UnHighLightShapesInLayer(l);
    },
    _onCountryMouseOut: function (e) {
        //get country shape and unhighlight
        var l = this._findLayerByTitle("country_" + e.target.id);
        if (l) fdi.ShapeUtils.UnHighLightShapesInLayer(l);
    },
    _onContinentClicked: function (e) {
        //update list

        //get matching continent shape and click it
        var l = this._findLayerByTitle("continent_" + e.target.id);
        if (l) {
            //get first shape in layer and click it
            var s = l.GetShapeByIndex(0);
            if (s) {
                this._navMapShapeMouseClickHander({ elementID: s.GetID() });
            }
        }
        return false;

    },

    _controlsZoomChanged: function (s, args) {
        //change map zoom
        if (this._navmap) {
            Sys.Debug.trace("zoom: " + args.get_newSelection());
            this._navmap.SetZoomLevel(args.get_newSelection());
        }
    },

    _controlsPanned: function (s, args) {
        //change map zoom
        if (this._navmap) {
            this._navmap.Pan(args.get_newSelection().x, args.get_newSelection().y);
        }
    },

    _countryStatsLoaded: function (r) {

        //update popup info, if still showing same popup
        if (this._popupcountryurl == r.stats.CountryUrlName) {
            var content = "<img src='" + r.stats.ImageUrl + "' id='ibflag' /><div id='ibstats'><strong>" + r.stats.ProjectsCount + "</strong> investment projects in the last 12 months</div>"


            var items = new Array();

            for (var index in r.stats.Results.Results) {
                for (var index2 in r.stats.Results.Results[index].Cities) {
                    Array.add(items, { Name: r.stats.Results.Results[index].Cities[index2].Name, Url: "/area/" + r.stats.Results.Results[index].Cities[index2].ContinentUrlName + "/" + r.stats.Results.Results[index].Cities[index2].CountryUrlName + "/region/" + r.stats.Results.Results[index].Cities[index2].UrlName });
                }
                for (var index3 in r.stats.Results.Results[index].Regions) {
                    Array.add(items, { Name: r.stats.Results.Results[index].Regions[index3].Name, Url: "/area/" + r.stats.Results.Results[index].Regions[index3].ContinentUrlName + "/" + r.stats.Results.Results[index].Regions[index3].CountryUrlName + "/region/" + r.stats.Results.Results[index].Regions[index3].UrlName });
                }

            }
            items.sort(function (a, b) {
                var nameA = a.Name.toLowerCase(), nameB = b.Name.toLowerCase()
                if (nameA < nameB) //sort string ascending
                    return -1
                if (nameA > nameB)
                    return 1
                return 0 //default return value (no sorting)
            });
            if (items.length > 0) {
                content += "<div id='moreInfoParagraph'>More information is available about the following regions and cities...</div>";
                content += "<ul id='ibareas' class='lister'>";

                for (var index in items) {
                    content += "<li><a href='" + items[index].Url + "'>" + items[index].Name + "<span></span></a></li>"
                }
                content += "</ul>"
            }
            content += "<ul style='list-style-type: none;' id='lbmoreinfo'><li><a class='popUpBtn' href='" + r.stats.Url + "'>view full details</a></li></ul>";


            $("#popupcontent").html(content);
        }

    },
    //#endregion

    //helpers
    //#region

    _setFilters: function (countryUrlName, countryName, continentUrlName, continentName) {
        this._navmapinfo.countryUrlName = countryUrlName;
        this._navmapinfo.countryName = countryName;
        this._navmapinfo.continentUrlName = continentUrlName;
        this._navmapinfo.continentName = continentName;

        if (continentUrlName != "") {
            $("#filterContinent").text(unescape(continentName)).show();
            $("#continentList").hide();
        } else {
            $("#filterContinent").hide();
            $("#continentList").show();
        }
        if (countryUrlName != "") {
            $("#filterCountry").text(unescape(countryName)); //.show();
            $("#filterCountry").attr("style", "display:block;");
        } else {
            $("#filterCountry").hide();
        }
    },

    AddContinent: function (urlName, areaName, shapes, lat, lon, zoom) {
        var shapeLayer = new VEShapeLayer();
        shapeLayer.SetTitle("continent_" + urlName);

        var continent = new fdi.Continent(areaName, urlName, shapeLayer, lat, lon, zoom);
        this._continents.Add(continent);

        shapeLayer.EWType = "continent";
        shapeLayer.EWUrlName = urlName;
        shapeLayer.EWContinent = continent;

        for (var index in shapes) {
            shapes[index].SetTitle(areaName);
            shapes[index].SetCustomIcon("");
            shapes[index].HideIcon();
            shapes[index].SetLineColor(new VEColor(105, 106, 108, 0.0));
            shapes[index].SetFillColor(new VEColor(105, 106, 108, 0.0));
            shapes[index].SetLineWidth(2);
            shapeLayer.AddShape(shapes[index]);
        }
        this._navmap.AddShapeLayer(shapeLayer);
    },

    AddCountry: function (urlName, continentUrlName, areaName, shapes) {
        var shapeLayer = new VEShapeLayer();
        shapeLayer.SetTitle("country_" + urlName);

        var country = new fdi.Country(areaName, urlName, shapeLayer);
        this._countries.Add(country);

        var continent = this._continents.GetContinentByUrlName(continentUrlName);
        if (continent == null) {
            alert("Trying to add country " + areaName + " didn't find continent " + continentUrlName);
        } else {
            continent.Countries.Add(country);
        }
        shapeLayer.EWType = "country";
        shapeLayer.EWUrlName = urlName;
        shapeLayer.EWContinentUrlName = continentUrlName;

        for (var index in shapes) {
            shapes[index].SetTitle(areaName);
            shapes[index].SetCustomIcon("");
            shapes[index].HideIcon();
            shapes[index].SetLineColor(new VEColor(105, 106, 108, 0.0));
            shapes[index].SetFillColor(new VEColor(105, 106, 108, 0.0));
            shapes[index].SetLineWidth(2);
            shapeLayer.AddShape(shapes[index]);
        }

        if ($.inArray(urlName, this._navmapinfo.NavMapSpecialCaribbeanUrlNames) > -1) {
            this._navmapinfo.NavMapSpecialCaribbeanLayers.push(shapeLayer);
        }
        if ($.inArray(urlName, this._navmapinfo.NavMapSpecialSouthEastAsiaUrlNames) > -1) {
            this._navmapinfo.NavMapSpecialSouthEastAsiaLayers.push(shapeLayer);
        }

        this._navmap.AddShapeLayer(shapeLayer);
    },

    _findLayerByTitle: function (title) {
        /// <summary>
        /// checks if supplied shape id is in one of the layers in supplied layerarray
        /// </summary>
        /// <param name="shapeid">the id of the shape to find</param>
        /// <param name="layers">array of layers to search</param> 
        for (i = 0; i < this._navmap.GetShapeLayerCount(); i++) {
            if (this._navmap.GetShapeLayerByIndex(i).GetTitle() == title) return this._navmap.GetShapeLayerByIndex(i);
        }
        return null;

    },
    _simplePolygonCentroid: function (points) {
        var sumY = 0;
        var sumX = 0;
        var partialSum = 0;
        var sum = 0;

        //close polygon
        points.push(points[0]);

        var n = points.length;

        for (var i = 0; i < n - 1; i++) {
            partialSum = points[i].Longitude * points[i + 1].Latitude - points[i + 1].Longitude * points[i].Latitude;
            sum += partialSum;
            sumX += (points[i].Longitude + points[i + 1].Longitude) * partialSum;
            sumY += (points[i].Latitude + points[i + 1].Latitude) * partialSum;
        }

        var area = 0.5 * sum;

        return new VELatLong(sumY / 6 / area, sumX / 6 / area);
    },
    _isInRectangle: function (verect, latlong) {
        return verect.TopLeftLatLong.Latitude > latlong.Latitude && latlong.Latitude > verect.BottomRightLatLong.Latitude && verect.TopLeftLatLong.Longitude < latlong.Longitude && latlong.Longitude < verect.BottomRightLatLong.Longitude;
    },
    //#endregion

    dispose: function () {
        this._navmap = null;
        this._navmapinfo = null;
        this._continents = null;
        this._countries = null;
        this._mapcontrols = null;
    }
}

fdi.NavMap.registerClass('fdi.NavMap', Sys.UI.Control);


fdi.NavMapInfo = function () {
    this.LayerLastOver = null;
    this.ZoomedTo = "world";
    this.NavMapSpecialCaribbeanUrlNames = ["cuba", "haiti", "dominican-republic", "cayman-islands",
"barbados", "dominica", "grenada", "guadeloupe", "jamaica", "martinique", "st-vincent-and-the-grenadines",
"the-bahamas", "trinidad-and-tobago", "virgin-islands"];
    this.NavMapSpecialCaribbeanLayers = [];
    this.NavMapSpecialCaribbeanZoomedTo = false;
    this.NavMapSpecialCaribbeanCenter = new VELatLong(18.4379, -72.1582);
    this.NavMapSpecialCaribbeanZoomLevel = 5;
    this.NavMapSpecialCaribbeanHighLighted = false;

    this.NavMapSpecialSouthEastAsiaUrlNames = ["south-korea", "north-korea", "thailand", "laos", "vietnam", "malaysia", "taiwan", "myanmar", "bangladesh",
    "bhutan", "cambodia", "philippines", "nepal", "brunei", "sri-lanka", "singapore"];
    this.NavMapSpecialSouthEastAsiaLayers = [];
    this.NavMapSpecialSouthEastAsiaZoomedTo = false;
    this.NavMapSpecialSouthEastAsiaCenter = new VELatLong(23.8858, 103.5351);
    this.NavMapSpecialSouthEastAsiaZoomLevel = 3;
    this.NavMapSpecialSouthEastAsiaHighLighted = false;
    this.CenterLatLong = null;
    this.countryUrlName = null;
    this.countryName = null;
    this.continentUrlName = null;
    this.continentName = null;
}

fdi.NavMapInfo.prototype = {
    dispose: function () {
        this.LayerLastOver = null;
        this.ZoomedTo = null;
        this.NavMapSpecialCaribbeanUrlNames = null;
        this.NavMapSpecialCaribbeanLayers = null;
        this.NavMapSpecialCaribbeanZoomedTo = null;
        this.NavMapSpecialCaribbeanCenter = null;
        this.NavMapSpecialCaribbeanZoomLevel = null;
        this.NavMapSpecialCaribbeanHighLighted = null;

        this.NavMapSpecialSouthEastAsiaUrlNames = null;
        this.NavMapSpecialSouthEastAsiaLayers = null;
        this.NavMapSpecialSouthEastAsiaZoomedTo = null;
        this.NavMapSpecialSouthEastAsiaCenter = null;
        this.NavMapSpecialSouthEastAsiaZoomLevel = null;
        this.NavMapSpecialSouthEastAsiaHighLighted = null;
        this.CenterLatLong = null;
    }
}

fdi.NavMapInfo.registerClass('fdi.NavMapInfo', null, Sys.IDisposable);


// override the jQuery getScript function to allow caching
$.getScript = function (url, callback, cache) { $.ajax({ type: "GET", url: url, success: callback, dataType: "script", cache: cache }); };




fdi.ShapeUtils = function () {
    /// <summary>
    ///   static Utility class for shapes
    /// </summary>

};

fdi.ShapeUtils.HighLightShapesInLayerArray = function (layerArray) {
    for (var layerIndex = 0; layerIndex < layerArray.length; layerIndex++) {
        var layer = layerArray[layerIndex];
        var shapeCount = layer.GetShapeCount();
        for (var index = 0; index < shapeCount; index++) {
            var shape = layer.GetShapeByIndex(index);
            fdi.ShapeUtils.HighLightShape(shape);
        }
    }
};
fdi.ShapeUtils.UnHighLightShapesInLayerArray = function (layerArray) {
    for (var layerIndex = 0; layerIndex < layerArray.length; layerIndex++) {
        var layer = layerArray[layerIndex];
        var shapeCount = layer.GetShapeCount();
        for (var index = 0; index < shapeCount; index++) {
            var shape = layer.GetShapeByIndex(index);
            fdi.ShapeUtils.UnHighLightShape(shape);
        }
    }
};
fdi.ShapeUtils.HighLightShapesInLayer = function (layer) {
    var shapeCount = layer.GetShapeCount();
    for (var index = 0; index < shapeCount; index++) {
        var shape = layer.GetShapeByIndex(index);
        fdi.ShapeUtils.HighLightShape(shape);
    }
};
fdi.ShapeUtils.UnHighLightShapesInLayer = function (layer) {
    var shapeCount = layer.GetShapeCount();
    for (var index = 0; index < shapeCount; index++) {
        var shape = layer.GetShapeByIndex(index);
        fdi.ShapeUtils.UnHighLightShape(shape);
    }
};
fdi.ShapeUtils.HighLightShape = function (shape) {
    shape.SetLineColor(new VEColor(105, 106, 108, 1));
    shape.SetFillColor(new VEColor(105, 106, 108, 1));
};
fdi.ShapeUtils.UnHighLightShape = function (shape) {
    shape.SetLineColor(new VEColor(105, 106, 108, 0.0));
    shape.SetFillColor(new VEColor(105, 106, 108, 0.0));
};

fdi.ShapeUtils.DoBoundingBoxesIntersect = function (bb1, bb2) {

    //First bounding box, top left corner, bottom right corner
    var ATLx = bb1.TopLeftLatLong.Longitude;
    var ATLy = bb1.TopLeftLatLong.Latitude;
    var ABRx = bb1.BottomRightLatLong.Longitude;
    var ABRy = bb1.BottomRightLatLong.Latitude;

    //Second bounding box, top left corner, bottom right corner
    var BTLx = bb2.TopLeftLatLong.Longitude;
    var BTLy = bb2.TopLeftLatLong.Latitude;
    var BBRx = bb2.BottomRightLatLong.Longitude;
    var BBRy = bb2.BottomRightLatLong.Latitude;

    var rabx = Math.abs(ATLx + ABRx - BTLx - BBRx);
    var raby = Math.abs(ATLy + ABRy - BTLy - BBRy);

    //rAx + rBx
    var raxPrbx = ABRx - ATLx + BBRx - BTLx;

    //rAy + rBy
    var rayPrby = ATLy - ABRy + BTLy - BBRy;

    if (rabx <= raxPrbx && raby <= rayPrby) {
        return true;
    }
    return false;
}

fdi.ShapeUtils.registerClass('fdi.ShapeUtils');

