﻿//--------------------------------------------
// GME.ascx.js
//--------------------------------------------
// Client side logic for the GME control
//--------------------------------------------
// Dave Bouwman - June 17th, 2008
// Data Transfer Solutions
//--------------------------------------------
        
var map = null;             //the gme.map object
var map = null;
var dtsUtility = null;

var _shapeLayerName = null;
var _atlasLayerCategories;
var GME_Is_Unloading = false;//set to true when page is unloading to suppress xhr error messages

/// <summary> Initialize the application when the page is loaded. </summary>
dojo.addOnLoad(function()
{
    //listen for onbeforeunload so we can suppress error messages induced by page navigation
    dojo.connect(window, 'onbeforeunload', function() { GME_Is_Unloading = true; });

    //dojo themes require body element to have the theme's cssClass
    document.body.className = "tundra";

    //Instantiate our utility class (from embedded assembly)
    dtsUtility = new dts.ve.Utility();

    //size everything appropriately before we instantiate the map
    dtsUtility.resizeContent();

    //build the links menu
    buildLinksMenu();

    //Deserialize the atlas layer categories that came down with the page
    _atlasLayerCategories = dojo.fromJson(atlasLayerCategoriesJson);

    //We send the initial map settings - based on a saved session, a query string, or the default
    //into the browser as JSON (from GME.ascx.cs).
    var mapSettings = Sys.Serialization.JavaScriptSerializer.deserialize(mapSettingsJson);

    //Create the mapArguments
    var mapArgs = new GME.MapArgs("veMap", new VELatLong(-27.5, 137), 2, mapSettings.MapStyle, false, VEMapMode.Mode2D, VEDistanceUnit.Kilometers);

    //Initialize the map
    map = new GME.Map(GME.Services.PointService, mapSettings, moduleId, portalId, userId, mapArgs);    

    //attach the slider to the map
    map.AttachSlider('zoomSliderVertical');

    //Hide the loader
    map.HideLoader('loader');

    //when the window resizes, resize the module
    dojo.connect(window, 'onresize', dtsUtility, dtsUtility.resizeContent);
    //when the map's content pane resizes, resize the ve map - this will also happen after a window resize because that will cause the mapcontentpane to resize
    dojo.connect(dijit.byId('mapContentPane'), 'resize', dojo.hitch(map, map.MapResizeCustom, 'mapContentPane'));

    //Load the help content
    dojo.query('#helpContent').addContent(mapSettings.HelpText, 'first');

    //Initialize the drawing tools
    DrawingTools.Init(map);    
});  

//Clean up all objects
dojo.addOnUnload(function () {
	if (map!=null) 
	{
        map.Dispose();
        map = null;
    }
});

///Builds the links menu on the gme toolbarfrom the linksJson sent down with the page
function buildLinksMenu()
{
    if (this.linksJson)
    {   //if we've got the json
        //get the toolbar and the links objec
        var toolbar = dijit.byId("mapTools");
        var links = dojo.fromJson(linksJson);

        if (toolbar && links && links.length > 0)
        {   //create a menu and a dropdown         
            var dijitMenu = new dijit.Menu();
            var dijitDropDown = new dijit.form.DropDownButton({ label: 'Links', dropDown: dijitMenu, iconClass: 'linksMenu' });
            //add to the toolbar
            toolbar.addChild(dijitDropDown);

            dojo.forEach(links, function(link)
            {   //add each of the links to the dropdown
                childMenuItem = new dijit.MenuItem({ label: link.Title, iconClass: 'linkMenuItem' });
                dojo.connect(childMenuItem, 'onClick', function(x) { window.open(link.Url); });

                dijitMenu.addChild(childMenuItem);
            });
        }
    }
}     

///Sets the zoom level of the map and sets the slider value
function SetMapZoomLevel(level){
    ///<summary>
    ///Used by the Slider
    ///</summary>
    map.SetZoom(level);
    //Also set the slider value - in some cases the map will only zoom to a certain level
    //this ensures that the slider doesn't indicate we zoomed to 18 but the map is still at 17
    dijit.byId('zoomSliderVertical').setValue(map.GetZoom());
}

///Shows the zoom to location dialog
function showZoomLocationDialog()
{
    //Call a function to work around a ve issue with firefox and dojo dialogs
    //dtsUtility.VEDojoDialogHack();
    
    //clear values
    dojo.byId(txtLatitude).value = "0";
    dojo.byId(txtLongitude).value = "0";
    dojo.byId(txtPlaceName).value = "";
    
    //show dialog
    dijit.byId('zoomLocationDialog').show();
}

///Ok button handler for the zoom to location dialog
function zoomLocation(){  
    //get the current tab - that's how we'll know what to do
    var selectedTab = dijit.byId('zoomLocationTabContainer').selectedChildWidget
    
    //get the control values
    var lat = parseFloat(dojo.byId(txtLatitude).value);
    var lon = parseFloat(dojo.byId(txtLongitude).value);
    var placeName = dojo.byId(txtPlaceName).value;
    
    if (selectedTab.id == 'latlontab')
    {
        //validate... return if validation fails max latitude for ve/ mercator is 85.05
        if (lat < -85 || lat > 85 || lon < -180 || lon > 180 || isNaN(lat) || isNaN(lon)) return;
        
        //zoom to the point
        map.PanZoomToPoint(lat, lon, map.Get_ZoomToPointLevel());
    }
    else if (selectedTab.id =='placenametab')
    {
        //validate that there has been something entered
        if (placeName == "") return;
        try
        {
            //find the placename
            map.PanZoomToPlaceName(placeName);     
        }
        catch (e)
        {
            dtsUtility.DisplayUserMessage('Message_Toaster_Topic',e.message, 'error');
        }
    }
        
    //hide the dialog
    dijit.byId('zoomLocationDialog').hide();
}

//=======Drawing tools=============
///Shows the drawint tools dialog
function showDrawingToolsDialog()
{
    var dlg = dijit.byId('drawingToolsForm');
    if (dlg)
    {
        dlg.show();
        dlg.bringToTop();
    }
}

//==========Add Data=============
///Shows the add data dialog
function showAddDataDialog()
{
    var divUploadMessage = dojo.byId('divShapefileUploadMsg');
    divUploadMessage.innerHTML = '';
    divUploadMessage.style.display = '';
    
    divUploadMessage = dojo.byId('divKmlUploadMsg');
    divUploadMessage.innerHTML = '';
    divUploadMessage.style.display = '';

    divUploadMessage = dojo.byId('divGeoRssUploadMsg');
    divUploadMessage.innerHTML = '';
    divUploadMessage.style.display = '';

    dojo.byId(txtLayerName).value = '';
    dojo.byId(txtLayerUrl).value = '';
    dojo.byId('ad_serviceType').options.selectedIndex = 0;
    dojo.byId('ad_opacity').options.selectedIndex = 0;
    dojo.byId(txtTransparentColor).value = '255,255,255';
    
    dijit.byId('addDataDialog').show()
}

///Ok button handler for the add data dialog
function uploadData()
{    
    //get the current tab - that's how we'll know what to do
    var selectedTab = dijit.byId('addDataTabContainer').selectedChildWidget
    var fileExt;
    var divUploadMessage;
    
    switch (selectedTab.id)
    {
        case 'shapefiletab':
            //Get the name of the zip file - we'll use it as the layer tile
            _shapeLayerName = dojo.byId('ifrShapefileUpload').contentWindow.document.getElementById('uploadFilePath').value;
            //Check the file extension
            fileExt = _shapeLayerName.slice(_shapeLayerName.lastIndexOf('.')+1);
            if (fileExt.toLowerCase() != 'zip')
            {
                divUploadMessage = dojo.byId('divShapefileUploadMsg')
                divUploadMessage.innerHTML = '<span>Please select a valid zip file!</span>';
                divUploadMessage.style.display = '';
                dojo.byId('ifrShapefileUpload').contentWindow.document.getElementById('uploadFilePath').focus();
                return;
            }
            _shapeLayerName = _shapeLayerName.slice(_shapeLayerName.lastIndexOf('\\')+1);
            _shapeLayerName = _shapeLayerName.slice(0, _shapeLayerName.lastIndexOf('.'));
            dojo.byId('ifrShapefileUpload').contentWindow.document.getElementById('fileType').value = 'shapefile';
            dojo.byId('ifrShapefileUpload').contentWindow.document.getElementById('fileUpload').submit();
            break;
        case 'kmltab':
            //Get the name of the zip file - we'll use it as the layer tile
            _shapeLayerName = dojo.byId('ifrKmlUpload').contentWindow.document.getElementById('uploadFilePath').value;
            //Check the file extension
            fileExt = _shapeLayerName.slice(_shapeLayerName.lastIndexOf('.')+1);
            if (fileExt.toLowerCase() != 'kml')
            {
                divUploadMessage = dojo.byId('divKmlUploadMsg')
                divUploadMessage.innerHTML = '<span>Please select a valid kml file!</span>';
                divUploadMessage.style.display = '';
                dojo.byId('ifrKmlUpload').contentWindow.document.getElementById('uploadFilePath').focus();
                return;
            }
            _shapeLayerName = _shapeLayerName.slice(_shapeLayerName.lastIndexOf('\\')+1);
            _shapeLayerName = _shapeLayerName.slice(0, _shapeLayerName.lastIndexOf('.'));
            dojo.byId('ifrKmlUpload').contentWindow.document.getElementById('fileType').value = 'kml';
            dojo.byId('ifrKmlUpload').contentWindow.document.getElementById('fileUpload').submit();
            break;
        case 'georsstab':
            //Get the name of the zip file - we'll use it as the layer tile
            _shapeLayerName = dojo.byId('ifrGeoRssUpload').contentWindow.document.getElementById('uploadFilePath').value;
            //Check the file extension
            fileExt = _shapeLayerName.slice(_shapeLayerName.lastIndexOf('.') + 1);
            if (fileExt.toLowerCase() != 'xml')
            {
                divUploadMessage = dojo.byId('divGeoRssUploadMsg')
                divUploadMessage.innerHTML = '<span>Please select a valid xml file!</span>';
                divUploadMessage.style.display = '';
                dojo.byId('ifrGeoRssUpload').contentWindow.document.getElementById('uploadFilePath').focus();
                return;
            }
            _shapeLayerName = _shapeLayerName.slice(_shapeLayerName.lastIndexOf('\\') + 1);
            _shapeLayerName = _shapeLayerName.slice(0, _shapeLayerName.lastIndexOf('.'));
            dojo.byId('ifrGeoRssUpload').contentWindow.document.getElementById('fileType').value = 'georss';
            dojo.byId('ifrGeoRssUpload').contentWindow.document.getElementById('fileUpload').submit();
            break;
        case 'wmstab':
            var layerName = dojo.byId(txtLayerName).value;
            var layerUrl = dojo.byId(txtLayerUrl).value;
            var wmsOptions = dojo.byId('ad_serviceType').options;
            var wmsVersion = wmsOptions[wmsOptions.selectedIndex].value;
            var opacityOptions = dojo.byId('ad_opacity').options;
            var opacity = opacityOptions[opacityOptions.selectedIndex].value;
            var transparentColor = dojo.byId(txtTransparentColor).value;

            //Validate the values
            if (layerName == "") {
                dtsUtility.DisplayUserMessage('Message_Toaster_Topic',"You must enter a layer name!", 'warning');
                return;
            }
            if (layerUrl == "") {
                dtsUtility.DisplayUserMessage('Message_Toaster_Topic','You must ener a URL!', 'warning');
            }
            var transColorRGBValues = transparentColor.split(',');
            if (transColorRGBValues.length == 3) {
                var r = parseInt(transColorRGBValues[0]);
                var g = parseInt(transColorRGBValues[1]);
                var b = parseInt(transColorRGBValues[2]);
                if (isNaN(r) || r < 0 || r > 255 || isNaN(g) || g < 0 || g > 255 || isNaN(b) || b < 0 || b > 255) {
                    dtsUtility.DisplayUserMessage('Message_Toaster_Topic','Transparent Color must be a comma-delimited list of 3 numbers between 0 and 255', 'warning');
                    return;
                }
            }
            else {
                dtsUtility.DisplayUserMessage('Message_Toaster_Topic','Transparent Color must be a comma-delimited list of 3 numbers between 0 and 255', 'warning');
                return;
            }

            map.AddDynamicWMSLayer(layerName, layerUrl, wmsVersion, opacity, transparentColor);

            dijit.byId('addDataDialog').hide();
            break;
    }
}

///Callback handler for uploading data
function uploadDataCallback(data, isError, fileType)
{
    switch (fileType)
    {
        case 'shapefile':
            var divUploadMessage = dojo.byId('divShapefileUploadMsg');
            if (isError)
            {
                divUploadMessage.innerHTML = '<span>' + data + '</span>';
                divUploadMessage.style.display = '';
                dojo.byId('ifrShapefileUpload').contentWindow.document.getElementById('uploadFilePath').focus();
            }
            else if (data =='null')
            {
                divUploadMessage.innerHTML = '<span>' + 'Invalid shapefile.' + '</span>';
                divUploadMessage.style.display = '';
                dojo.byId('ifrShapefileUpload').contentWindow.document.getElementById('uploadFilePath').focus();
            }
            else 
            {
                divUploadMessage.innerHTML = '';
                divUploadMessage.style.display = '';
                dijit.byId('addDataDialog').hide();
                dtsUtility.DisplayUserMessage('Message_Toaster_Topic',map.AddLayerAndShapes(dojo.fromJson(data), _shapeLayerName) + ' shapes loaded!', 'info');
            }
            break;
        case 'kml':
            var divUploadMessage = dojo.byId('divKmlUploadMsg');
            if (isError)
            {
                divUploadMessage.innerHTML = '<span>' + data + '</span>';
                divUploadMessage.style.display = '';
                dojo.byId('ifrKmlUpload').contentWindow.document.getElementById('uploadFilePath').focus();
            }
            else if (data =='null')
            {
                divUploadMessage.innerHTML = '<span>' + 'Invalid KML file.' + '</span>';
                divUploadMessage.style.display = '';
                dojo.byId('ifrKmlUpload').contentWindow.document.getElementById('uploadFilePath').focus();
            }
            else 
            {
                divUploadMessage.innerHTML = '';
                divUploadMessage.style.display = '';
                dijit.byId('addDataDialog').hide();
                map.AddLayerFromFeed(VEDataType.ImportXML, data, _addKmlCallback);
            }
            break;
        case 'georss':
            var divUploadMessage = dojo.byId('divGeoRssUploadMsg');
            if (isError)
            {
                divUploadMessage.innerHTML = '<span>' + data + '</span>';
                divUploadMessage.style.display = '';
                dojo.byId('ifrGeoRssUpload').contentWindow.document.getElementById('uploadFilePath').focus();
            }
            else if (data == 'null')
            {
                divUploadMessage.innerHTML = '<span>' + 'Invalid GeoRSS file.' + '</span>';
                divUploadMessage.style.display = '';
                dojo.byId('ifrGeoRssUpload').contentWindow.document.getElementById('uploadFilePath').focus();
            }
            else
            {
                divUploadMessage.innerHTML = '';
                divUploadMessage.style.display = '';
                dijit.byId('addDataDialog').hide();
                map.AddLayerFromFeed(VEDataType.GeoRSS, data, _addKmlCallback);
            }
            break;
        default:
            if (isError)
            {
                dtsUtility.DisplayUserMessage('Message_Toaster_Topic',data, 'warning');
            }
            break;            
    }
}

///Callback handler for adding kml layer
function _addKmlCallback(feedShapeLayer)
{
    dtsUtility.DisplayUserMessage('Message_Toaster_Topic',feedShapeLayer.GetShapeCount() + ' shapes loaded!', 'info');
}

//=================Manage Layers===========================
///Initializes and displays the Manage Map Layers dialog
function showManageLayersDialog(layers)
{
    try
    {
        var dlg = dijit.byId('manageLayersDialog');

        //get the viewport
        var vpt = dijit.getViewport();

        //get the height of the dialog
        var titleBar = dojo.query('.dijitDialogTitleBar', dlg.domNode)[0];
        var instructions = dojo.byId('ml_instructions');
        var dialogControls = dojo.byId('manageLayersDialogControls');
        var minusHeight = dojo.coords(titleBar).h + dojo.coords(instructions).h + dojo.coords(dialogControls).h + 50;
        var height = (Math.floor(vpt.h * .85)) - minusHeight; //the height of the dialog will be 85% of the viewport minus titlebar + instructions + dialogControls + 50px extra

        //get the width of the dialog
        var col2 = dojo.byId('ml_col2');
        var col4 = dojo.byId('ml_col4');
        var controlsWidth = dojo.coords(col2).w + dojo.coords(col4).w;
        var dlgWidth = (vpt.w * .85) - controlsWidth; // the width of the dialog will be 85% the width of the viewport minus the width of col2 + col4

        //style column 1
        var col1 = dojo.byId('ml_col1');
        dojo.style(col1, { height: height + 'px', width: Math.floor(dlgWidth * .65) + 'px' });

        //style column 3
        var col3 = dojo.byId('ml_col3');
        dojo.style(col3, { height: height + 'px', width: Math.floor(dlgWidth * .35) + 'px', margin: '0 0 0 ' + (Math.floor(dlgWidth * .6)) + 10 + 'px' });

        //size the tab container if it's there
        var tabCont = dijit.byId('availableLayersTabContainer');
        if (tabCont) { tabCont.resize(); }        

        if (!dlg.isInitialized) 
        {   //build the tabs appropriately
            _buildAtlasLayersUI(dlg);
        }
        else 
        {   //it has been initialized - just clear out the selects - we'll reload them appropriately below - the visibility of layers could have been changed outside of this dialog, ie by loading a saved session or 'add atlas layer from button click' on identify panel or popup
            dojo.query('select', dlg.domNode).forEach(function(select) { dtsUtility.ClearSelect(select) });
        }        

        //load atlas layers into ui
        _loadAtlasLayersDialog();

        dijit.byId('visibleLayersContainer').resize();

        //show dialog        
        dlg.show();
    }
    catch (err)
    {
        dtsUtility.DisplayUserMessage('Message_Toaster_Topic','An error ocurred displaying the Manage Map Layers dialog. Please refresh the page and try again.', 'error');
    }
}

///Builds the ui for the atlas layers dialog
function _buildAtlasLayersUI(dlg)
{
    //check if any atlas layers are in a category that does not exist
    if (!dojo.every(map.Get_AtlasLayers(), function(layer)
    {
        return (dojo.some(_atlasLayerCategories, function(cat)
        {
            return layer.Category === cat.Category_Name; 
        }))
    }))
    {   //if so, add an 'Uncategorized' tab
        _atlasLayerCategories.push({Category_Name: 'Uncategorized'});
    }

    var availableLyrsTabCont = dijit.byId('availableLayersTabContainer');
    if (_atlasLayerCategories.length < 2)
    {
        //If there is one or fewer categories, don't build tabs, just use a multiselect
        availableLyrsTabCont.destroyRecursive();
        dojo.byId('ml_col1').appendChild(new dijit.form.MultiSelect({ id: 'availableLayers__select' }).containerNode);
    }
    else
    {
        //multiple categories - build a tab and a select for each category
        var tab, select;
        dojo.forEach(_atlasLayerCategories, function(item)
        {
            tab = new dijit.layout.ContentPane({ id: 'availableLayers_' + item.Category_Name + '_tab' });
            tab.title = item.Category_Name;

            select = new dijit.form.MultiSelect({ id: 'availableLayers_' + item.Category_Name + '_select' });

            tab.setContent(select.containerNode);
            availableLyrsTabCont.addChild(tab);
        });
    }
    
    dlg.isInitialized = true;
}

///loads atlas layers into the atlas layers dialog according to their category and visibility state
function _loadAtlasLayersDialog()
{
    var loadedLayersSelect = dijit.byId("visibleLayers").containerNode;

    var opt, sel;
    dojo.forEach(map.Get_AtlasLayers(), function(item)
    {
        //if the category = '' set it to uncategorized
        if (item.Category == '') { item.Category = 'Uncategorized'; }
        //if the category does not exist, set it to uncategorized
        if (item.Category == 'Uncategorized' || dojo.some(map.Get_AtlasLayers(), function(cat) { return cat.Category_Name == item.Category; }))
        {
            item.Category = 'Uncategorized';
        }
        //if there is one or fewer categories, set the category to ''
        if (_atlasLayerCategories.length < 2) { item.Category = ''; }

        opt = dojo.doc.createElement('option');
        opt.innerHTML = item.LayerName;
        opt.value = dojo.toJson(item);

        sel = (item.IsLoaded) ? loadedLayersSelect : dojo.byId('availableLayers_' + item.Category + '_select');

        if (sel) sel.appendChild(opt);
    });
}

///Moves selected available layers into the visible layers select
function manageLayersMoveRight()
{    
    try
    {
        var availableLayersSel;
        
        var tabCont = dojo.byId('availableLayersTabContainer');
        if (tabCont)
        {
            var selectedTab = dijit.byId('availableLayersTabContainer').selectedChildWidget;
            //get the select inside the active tab
            availableLayersSel = dijit.byNode(dojo.query('select', selectedTab.domNode)[0]);
        }
        else
        {
            availableLayersSel = dijit.byId('availableLayers__select');
        }
                        
        //move the selected items into the visible layers select
        var visibleLayersSel = dijit.byId("visibleLayers")
        
        if (availableLayersSel && visibleLayersSel)
        {
            visibleLayersSel.addSelected(availableLayersSel);
            //Workaround an odd ie issue where stuff doesn't appear to move until the mouse moves off the dialog
            availableLayersSel.focus();
            visibleLayersSel.focus();
        }        
    }
    catch (err)
    {
        dtsUtility.DisplayUserMessage('Message_Toaster_Topic','An error ocurred moving the selected layers. Please refresh the page and try again.', 'error');
    }
}

///Moves selected visible layers into the appropriate available layers select
function manageLayersMoveLeft()
{    
    try
    {
        var visibleLayersSel = dijit.byId("visibleLayers");

        //Go through the selected items and add them to the appropriate select in the tab container
        var availableLayersSel, layer;
        var selected = visibleLayersSel.getSelected();
        dojo.forEach(selected, function(opt)
        {
            layer = dojo.fromJson(opt.value);
            availableLayersSel = dojo.byId('availableLayers_' + layer.Category + '_select');
            availableLayersSel.appendChild(opt);
        });

        //Workaround an odd ie issue where stuff doesn't appear to move until the mouse moves off the dialog
        visibleLayersSel.focus();
        var tabCont = dojo.byId('availableLayersTabContainer');
        if (tabCont)
        {
            dojo.query('select', dijit.byNode(dojo.byId('availableLayersTabContainer')).selectedChildWidget.domNode)[0].focus();
        }
        else
        {
            var availableLayersSel = dojo.byId('availableLayers__select');
            if (availableLayersSel){ availableLayersSel.focus(); }
        }
    }
    catch (err)
    {
        dtsUtility.DisplayUserMessage('Message_Toaster_Topic','An error ocurred moving the selected layers. Please refresh the page and try again.', 'error');
    }
}

///Moves selected layers up one position in the select
function manageLayersMoveUp()
{    
    try
    {
        var selectList = dojo.byId('visibleLayers');
        var selectOptions = selectList.getElementsByTagName('option');

        for (var i = 1; i < selectOptions.length; i++)
        {
            var opt = selectOptions[i];
            if (opt.selected)
            {
                selectList.removeChild(opt);
                selectList.insertBefore(opt, selectOptions[i - 1]);
            }
        }

        //Workaround an odd ie issue where stuff seems to disappear until the mouse moves over the select
        selectList.focus();
    }
    catch (err)
    {
        dtsUtility.DisplayUserMessage('Message_Toaster_Topic','An error ocurred moving the selected layers. Please refresh the page and try again.', 'error');
    }
}

///Moves selected layers down one position in the select
function manageLayersMoveDown()
{    
    try
    {
        var selectList = dojo.byId('visibleLayers');
        var selectOptions = selectList.getElementsByTagName('option');
        
        for (var i = selectOptions.length - 2; i >= 0; i--)
        {
            var opt = selectOptions[i];
            if (opt.selected)
            {
                var nextOpt = selectOptions[i + 1];
                opt = selectList.removeChild(opt);
                nextOpt = selectList.replaceChild(opt, nextOpt);
                selectList.insertBefore(nextOpt, opt);
            }
        }

        //Workaround an odd ie issue where stuff seems to disappear until the mouse moves over the select
        selectList.focus();
    }
    catch (err)
    {
        dtsUtility.DisplayUserMessage('Message_Toaster_Topic','An error ocurred moving the selected layers. Please refresh the page and try again.', 'error');
    }
}

///Processes the state of the dialog and applies appropriate changes to the map
function manageAtlasLayers()
{
    try
    {        
        //Get the listbox
        var loadedLayersSelect = dijit.byId('visibleLayers');
        //Get the atlas layers collection from the map
        var atlasLayers = dojo.clone(map.Get_AtlasLayers());

        //Go through the map's atlas layers collection
        var opt, zIndex, n = 0;
        dojo.forEach(atlasLayers, function(layer)
        {
            //if the layer is in the loadedLayersSelect
            if (dojo.query('option', loadedLayersSelect.domNode).some(function(item) { return item.innerHTML === layer.LayerName; }))
            {
                //it needs to be on if it is not already
                n = dtsUtility.GetOptionIndexByText(layer.LayerName, loadedLayersSelect.domNode); //the index of the item in the select
                zIndex = 30 - n;                
                //load layer into the map setting z-index appropriately if it is already in the map, update z-index and toggle visibility
                map.AddAtlasLayer(layer, zIndex);
                //set IsLoaded property to true
                layer.IsLoaded = true;
                layer.zIndex = zIndex;
            }
            else
            {
                //it needs to be off if it is not already
                if (layer.IsLoaded) map.DropAtlasLayer(layer)
                //set IsLoaded property to true
                layer.IsLoaded = false;
            }
        });

        //Set the new atlasLayers array on the map object sorting it appropriately first
        atlasLayers.sort(function(a, b)
        {   //sort the loaded ones first by zindex with the unloaded ones at the bottom
            if ((a.IsLoaded && b.IsLoaded)) { return b.zIndex - a.zIndex; }
            if (!a.IsLoaded && !b.IsLoaded) { return 0; }
            if (a.IsLoaded && !b.IsLoaded) { return -1; }
            if (!a.IsLoaded && b.IsLoaded === true) { return 1; }

        });
        map.Set_AtlasLayers(atlasLayers);

        //build the legend
        map.BuildAtlasLayersLegend();

        //Hide the dialog
        dijit.byId('manageLayersDialog').hide();
    }
    catch (err)
    {
        dtsUtility.DisplayUserMessage('Message_Toaster_Topic','An error ocurred managing map layers. Please refresh the page and try again.', 'error');
        var dlg = dijit.byId('manageLayersDialog');
        if (dlg) { dlg.hide(); }
    }
}

//======================Session Management====================
///Shows the manage sessions dialog
function showSessionManagementDialog()
{   
    try
    {
        //Call a function to work around a ve issue with firefox and dojo dialogs
        //dtsUtility.VEDojoDialogHack();

        var sendBtn = dojo.byId('sm_sendButton');
        var dialogDomNode = dojo.byId('sessionManagementDialog');
        var tabCont = dojo.byId('sessionManagementTabContainer');
        var callbackFcn;

        if (!dialogDomNode.isInitialized)//avoid adding connects twice
        {
            //Check if user is logged on
            if (userId == -1)
            {
                //user is not logged in - select the email session tab and hide the tab strip
                dijit.byNode(tabCont).selectChild(dijit.byId('emailSessionTab'));
                dojo.style(dojo.byId('sessionManagementTabContainer_tablist'), 'display', 'none');
                dojo.query('.dijitTabPaneWrapper', tabCont).style('border', 'none');
                dojo.query('[for="availableSessions"], #availableSessions', tabCont).style('display', 'none');
                dojo.query('span[id$="sm_instructions"]', dialogDomNode).style('display', 'none');
                var callbackFcn = dojo.hitch(this, 'saveUserSession');
                dojo.connect(sendBtn, 'onclick', this, dojo.hitch(this, '_validateEmailFields', callbackFcn));
            }
            else
            {
                dijit.byNode(tabCont).selectChild(dijit.byId('manageSessionTab'));
                dojo.query('span[id$="sm_instructions2"]', dialogDomNode).style('display', 'none');
                var callbackFcn = dojo.hitch(this, 'emailUserSession');
                dojo.connect(sendBtn, 'onclick', this, dojo.hitch(this, '_validateEmailFields', callbackFcn));

                //Show loading message
                showLoadingMessage();

                //Get the available sessions
                map.GetUserSessions(moduleId, userId, _getUserSessionsCallback);
            }
            dialogDomNode.isInitialized = true;
        }

        //Clear form fields
        dojo.byId(txtSessionName).value = '';
        dojo.byId(txtSender).value = '';
        dojo.byId(txtRecipient).value = '';
        dojo.byId(txtMessageBody).value = '';

        //Show the dialog
        dijit.byNode(dialogDomNode).show();
    }
    catch (err)
    {
        dtsUtility.DisplayUserMessage('Message_Toaster_Topic','An error ocurred displaying the session management dialog.', 'error');
    }
}

///Shows a loading message in the manage sessions dialog
function showLoadingMessage()
{
    var storedSessionsSelect = dojo.byId('storedSessions');
    var availableSessionsSelect = dojo.byId('availableSessions');

    //Clear the listboxes
    dtsUtility.ClearSelect(storedSessionsSelect);
    dtsUtility.ClearSelect(availableSessionsSelect);

    //Display the loading message
    var opt = dojo.doc.createElement('option');
    opt.innerHTML = 'Loading...';
    opt.value = '';
    storedSessionsSelect.appendChild(opt);
}

///Load the available sessions into the listbox and the combobox
function _getUserSessionsCallback(mapSettingsArray)
{
    //Get the listbox
    var storedSessionsSelect = dojo.byId('storedSessions');
    var availableSessionsSelect = dojo.byId('availableSessions');
    
    //Clear the listbox
    dtsUtility.ClearSelect(storedSessionsSelect)
    dtsUtility.ClearSelect(availableSessionsSelect);

    //Load the sessions
    dojo.forEach(mapSettingsArray, function(session)
    {
        try { storedSessionsSelect.add(new Option(session.Session_Name, session.User_Session_Id), null); } //FF
        catch (ex) { storedSessionsSelect.add(new Option(session.Session_Name, session.User_Session_Id)); } //IE

        try { availableSessionsSelect.add(new Option(session.Session_Name, session.User_Session_Id), null); } //FF
        catch (ex) { availableSessionsSelect.add(new Option(session.Session_Name, session.User_Session_Id)); } //IE
    });
}

///Saves a user session
function saveUserSession()
{
    var sessionName;
    var callback;
    if (userId != -1)
    {   //user is logged in, we are saving the session - validate it
        //Get the session name
        sessionName = dojo.byId(txtSessionName).value;

        //Validate it
        if (!sessionName)
        {
            dtsUtility.DisplayUserMessage('Message_Toaster_Topic','You must specify a session name!', 'warning');
            return;
        }

        callback = dojo.hitch(this, '_saveUserSessionCallback');
    }
    else
    {   //user is not logged in - we are saving the session just so the user can email it
        sessionName = 'Session saved for emailing';
        callback = dojo.hitch(this, '_saveAndEmailUserSessionCallback');
    }

    //Save the user session
    map.SaveMapSession(sessionName, userId, moduleId, callback);
    
    //Show loading message
    showLoadingMessage();
}

///Callback for save user session
function _saveUserSessionCallback(result)
{
    if(!result)
    {
        dtsUtility.DisplayUserMessage('Message_Toaster_Topic','An Error has occured saving your session.', 'error');
        return;
    } 
    
    //Reload the listbox
    map.GetUserSessions(moduleId, userId, _getUserSessionsCallback);
}

function _saveAndEmailUserSessionCallback(result)
{
    if (!result)
    {
        dtsUtility.DisplayUserMessage('Message_Toaster_Topic','An Error has occured saving your session.', 'error');
        return;
    }

    this.emailUserSession(result);
}

///Deletes a user session
function deleteUserSession()
{   
    //Get the listbox
    var storedSessionsSelect = dojo.byId('storedSessions');

    if (storedSessionsSelect.selectedIndex === -1) { dtsUtility.DisplayUserMessage('Message_Toaster_Topic','You must select a user session to delete!', 'warning'); return; }
    
    //Get the selected item
    var sessionId = storedSessionsSelect.value;
    //Validate it
    if (!sessionId)
    {
        dtsUtility.DisplayUserMessage('Message_Toaster_Topic','You must select a session to delete!', 'warning');
        return;
    }
    
    //Delete the session
    map.DeleteMapSession(sessionId, moduleId, userId, _deleteMapSessionCallback)
    
    //Show loading message
    showLoadingMessage();
}

///Callback for deleting a user session
function _deleteMapSessionCallback(result)
{
    if(!result)
    {
        dtsUtility.DisplayUserMessage('Message_Toaster_Topic','An Error has occured deleting your session.', 'error');
        return;
    } 
    
    //Reload the listbox
    map.GetUserSessions(moduleId, userId, _getUserSessionsCallback);
}

///Loads a user session into the map
function loadUserSession()
{
    //Get the listbox
    var storedSessionsSelect = dojo.byId('storedSessions');

    if (storedSessionsSelect.selectedIndex === -1) { dtsUtility.DisplayUserMessage('Message_Toaster_Topic','You must select a user session to load!', 'warning'); return; }

    //Load the user session
    map.LoadMapSession(storedSessionsSelect.value);
    
    //Close the dialog
    dijit.byId('sessionManagementDialog').hide();
}

 function _validateEmailFields(callback)
 {
     //Get the form fields
     var fromAdd = dojo.byId(txtSender).value;
     var toAdd = dojo.byId(txtRecipient).value;
     var body = dojo.byId(txtMessageBody).value;     

     //Validate the form fields
     var msg = '';
     if (userId != -1)
     {
         var sessionId = dojo.byId('availableSessions').value;
         if (sessionId == '') msg = 'You must select a session.';
     }

     if (!fromAdd) msg += 'You must specify a \'from\' address!';
     else if (!dtsUtility.IsValidEmail(fromAdd)) msg = 'Invalid \'from\' address!';

     if (!toAdd) msg += '\nYou must specify a \'to\' address!';
     else
     {
         var toAddAry = toAdd.split(';');
         toAddAry = dojo.map(toAddAry, function(add)
         {
             add = dojo.string.trim(add);
             if (!dtsUtility.IsValidEmail(add)) msg += '\nInvalid \'to\' address: "' + add + '"!';
             return add;
         });
     }

     if ((msg) && (msg != ''))
     {
         dtsUtility.DisplayUserMessage('Message_Toaster_Topic',msg, 'warning');
         return;
     }

     if (callback && dojo.isFunction(callback)) { callback(); }
 }

///Emails a user session
 function emailUserSession(sessionId)
 {
     //Get the form fields
     var sessionName = 'Session saved for emailing';
     var fromAdd = dojo.byId(txtSender).value;
     var toAdd = dojo.byId(txtRecipient).value;
     var toAddAry = toAdd.split(';');
     toAddAry = dojo.map(toAddAry, function(add)
     {
         add = dojo.string.trim(add);
         return add;
     });
     var body = dojo.byId(txtMessageBody).value;

     if (userId != -1)
     {   //user is logged in - need to get session id from the dialog
         sessionId = dojo.byId('availableSessions').value;
     }

     //Email the user session
     map.EmailSession(fromAdd, toAddAry, sessionName, body, sessionId, moduleId, _emailSessionCallback);

     //Close the dialog
     dijit.byId('sessionManagementDialog').hide();
 }

///Callback for emailing a user session
 function _emailSessionCallback(result)
 {
     var msg, level;
     if (result == true)
     {
         msg = 'Email has been sent.';
         level = 'info';
     }
     else
     {
         msg = 'An Error has occured sendng your email.'; ;
         level = 'error';
     }
     dtsUtility.DisplayUserMessage('Message_Toaster_Topic',msg, level);
 }

//==============Export Points Functions====================
///Shows the export points dialog
function showExportPointsDialog()
{
    //Call a function to work around a ve issue with firefox and dojo dialogs
    //dtsUtility.VEDojoDialogHack();

    //setup the radio group
    var pointLayers = map.Get_FeatureLayers();
    var layerName, htmlString;
    for (var l = 0; l < pointLayers.keys().length; l++)
    {
        layerName = pointLayers.keys()[l];
        if (l === 0) htmlString = '<div class="exportPointsInput"><input type="radio" checked="checked" name="layerName" value="' + layerName + '" /><span>' + layerName + '</span></div>';
        else htmlString += '<div class="exportPointsInput"><input type="radio" name="layerName" value="' + layerName + '" /><span>' + layerName + '</span></div>';
    }
    dijit.byId('layerNameContainer').setContent(htmlString);
    
    //show dialog
    dijit.byId('exportPointsDialog').show();
}

///Export points button handler for export points dialog
function exportPointsShapeFile()
{
    //get the selected value from the radio group
    var layerName = dojo.query('#layerNameContainer input[name="layerName"]').filter(function(el) { return el.checked })[0].value;
    
    //Export the points
    map.ExportPointsShapeFile(layerName)

    //hide dialog
    dijit.byId('exportPointsDialog').hide();
}

//=======================================================================
if (typeof(Sys) !== "undefined") Sys.Application.notifyScriptLoaded(); 
