﻿// JScript File

MapApiClient.MapApiSGE = function (rootObj) 
{
    MapApiClient.MapApiSGE.initializeBase(this, [rootObj]);

    //MapApiClient.MapApiSGE.initializeBase(this);
    // Save mapContainer as an object in derived class
    // Else it will not be available in base class after events/callbacks
    this._mapClientLoaded=false;
    this._loadPending = false;
    this._mapObject = rootObj;
    this._currMapMode;             // Enum keeping track of current map mode
    this._suspendedMapMode = null; // Store map mode during e.g digitize sessions 
    this._currZoomFactor=0.5;      //To be sett by callser for zoom in/out
    this._currPanVerticalFactor=0.5;  //To be sett by callser for Pan map
    this._currPanHorizontalFactor=0.5;  //To be sett by callser for Pan map
    this._configZoomOutFactor = 1.5;
    this._configZoomInFactor = 0.5;
    this._requestedMapScale=0;
    this._maxSymSelect = -1;
    this._mapLayerMngr = null;
    this._mapDataMngr = null;
    this._sDefaultMapLayers = null; //Defaults map layers to load
    this._sDefaultMapFilters = null;//Default filters to apply
    this._currentMapRequestId=0;    //Counter for map requests, 1 is only  a start value
    //Some class scope delegates
    this._delMapConfig = null;
    this._delPregenData = null;
    this._delLegendReturned = null;
    this._delMapRetured = null;
    this._delTooltipRetured = null;
    this._delWebServiceError = null;
    this._delNetworkData=null;
    
    this._loadingFlag = false;
    this._drawShapeRequest = null;    //Pending SHAPE draw reguest
    this._SelectionEnabled = false;   //Activate MapSelection
    this._ContextMenuEnabled = false; //Activate/Deactivate
    
    this._bDebug = false;
    this._coordTracking = false;
    this._ajaxTooltipEnabled = false;
    this._setLoadingText = null;
    this._mapNoresponseMessage = null;
    this._StartDate = null;
    this._shapeCanvas = 'SHAPE';
    this._selectCanvas = 'SELECT';
    this._drawPolIgnorePoint = false;
    this._pendingDynamicMapScale = null;
    this._pendingSplitMapScale = null;
    this._worldPoint= new Array(2);
    this._tooltipRequestCoord = null;
    this._mouseOverElement = null;
 }
 
 MapApiClient.MapApiSGE.prototype={
    
    
    initialize: function( i_config, i_resources) {
        // register the global mapApi
        // Initialize the mapObject and hook up callbacks from the mapObject to the MapApi
        var mapContextMenu = i_config ? i_config.mapContextMenu : null;
        this._mapObject.initialize( i_resources, mapContextMenu,
                                    Function.createDelegate(this, this.OnMapMoved), 
                                    Function.createDelegate(this, this.OnMapZoomed), 
                                    Function.createDelegate(this, this.OnMapZoomedToPoint), 
                                    Function.createDelegate(this, this.OnMapClicked), 
                                    Function.createDelegate(this, this.OnMapResize), 
                                    Function.createDelegate(this, this.OnMapMouseMove), 
                                    Function.createDelegate(this, this.OnMapContextDataRequest) , 
                                    Function.createDelegate(this, this.OnRequestSetMapMode),
                                    Function.createDelegate(this, this.OnMapAreaSelected),
                                    Function.createDelegate(this, this.OnAreaItemSelected));
                      
          /*
           this._mapObject.initialize( this.OnMapMoved, 
                    this.OnMapZoomed, 
                    this.OnMapZoomedToPoint, 
                    this.OnMapClicked, 
                    this.OnMapResize, 
                    this.OnMapMouseMove, 
                    this.OnMapContextDataRequest , 
                    this.OnRequestSetMapMode);
          */
                      
                      
         //Connecting to application events
         Global.EventController().subscribe("evtSystemChanged", Function.createDelegate(this, this.onSystemChanged));               
         Global.EventController().subscribe("evtStatusChanged", Function.createDelegate(this, this.onStatusChanged));
         Global.EventController().subscribe("evtServiceChanged", Function.createDelegate(this, this.onServiceChanged));
         Global.EventController().subscribe("evtQualityChanged", Function.createDelegate(this, this.onQualityChanged));
         Global.EventController().subscribe("evtSeverityChanged", Function.createDelegate(this, this.onSeverityChanged));
         Global.EventController().subscribe("evtTimeLevelChanged", Function.createDelegate(this, this.onTimeLevelChanged));
         Global.EventController().subscribe("evtHistoryChanged", Function.createDelegate(this, this.onHistoryChanged));
         Global.EventController().subscribe("evtSelectionListChanged", Function.createDelegate(this, this.onSelectionListChanged));
         Global.EventController().subscribe("evtMccChanged", Function.createDelegate(this, this.onMccChanged));
         Global.EventController().subscribe("evtMncChanged", Function.createDelegate(this, this.onMncChanged));
         Global.EventController().subscribe("evtNetworkChanged", Function.createDelegate(this, this.onNetworkChanged));
        //Create mapLayer manager
        this._mapLayerMngr = new MapApiClient.MapLayerMngr();
        
        //Create mapData manager (map overlays)
        this._mapDataMngr  = new MapApiClient.MapDataMngr();
        this._mapDataMngr.setHitMode( this._EnumObjectHitMode );  
                     
        //Configure from config
        if ( i_config ){
            if ( i_config.mapMaxSymSelect ){
                this._maxSymSelect = parseInt(i_config.mapMaxSymSelect);
            }
            if ( i_config.mapZoomOutFactor ){
                this._configZoomOutFactor = i_config.mapZoomOutFactor;
            }
            if ( i_config.mapDalDebug && i_config.mapDalDebug != "false"){
                this._bDebug=true;
            }
            if ( i_config.mapCoordTracking && i_config.mapCoordTracking == "true"){
                this._coordTracking=true;
                //Enable mouse stopped event for coordTrack
                this._mapObject.setMouseMoveStoppedEvent(true); 
            }
            if ( i_config.mapSetLoadingText && i_config.mapSetLoadingText != "null" ){
                this._setLoadingText = i_config.mapSetLoadingText;
                this._mapObject.setLoadingText( this._setLoadingText );
            }
            var ttWidth = null;
            var ttHeight = null;
            if ( i_config.mapTooltipHeight && i_config.mapTooltipHeight != "null" ){
                ttHeight = i_config.mapTooltipHeight;
            }
            if ( i_config.mapTooltipWidth && i_config.mapTooltipWidth!= "null" ){
                ttWidth = i_config.mapTooltipWidth;
            }
            if (ttWidth != null || ttHeight != null ){
                this._mapObject.setTooltipSize(ttWidth, ttHeight)
            }
             if ( i_config.mapNoresponseMessage ){
                this._mapNoresponseMessage = i_config.mapNoresponseMessage;
            }
        }
                                
        //Set current map mode, and also set this in map object
        var CurrMapMode = Global.DataController().getData("evtMapModeChanged");
        if ( CurrMapMode != null){
            this.setMapMode( CurrMapMode );
        } else {
            this.setMapMode(  this.EnumMapMode().MAP_MODE_SELECT );
        }
        
        //Get some defults
        var aGlobalStatus = Global.DataController().getData("evtStatusChanged");
        if ( (aGlobalStatus != null) && (this._mapLayerMngr != null))
        {
            this._mapLayerMngr.setStatus( aGlobalStatus );
        }
        var sGlobalSystem = Global.DataController().getData("evtSystemChanged");
        if ( (sGlobalSystem != null) && (this._mapLayerMngr != null))
        {
            this._mapLayerMngr.setSystype( sGlobalSystem );
        }
        var sGlobalService = Global.DataController().getData("evtServiceChanged");
        if ( (sGlobalService != null) && (this._mapLayerMngr != null))
        {
            this._mapLayerMngr.setService( sGlobalService );
        }
        var sGlobalQuality = Global.DataController().getData("evtQualityChanged");
        if ( (sGlobalQuality != null) && (this._mapLayerMngr != null))
        {
            this._mapLayerMngr.setQuality( sGlobalQuality );
        }
        var sGlobalSeverity = Global.DataController().getData("evtSeverityChanged");
        if ( (sGlobalSeverity != null) && (this._mapLayerMngr != null))
        {
            this._mapLayerMngr.setSeverity( sGlobalSeverity );
        }
        
        var sGlobalHistory = Global.DataController().getData("evtHistoryChanged");
        if ( (sGlobalHistory != null) && (this._mapLayerMngr != null))
        {
            this._mapLayerMngr.setHistory( sGlobalHistory );
        }
        var sGlobalMcc= Global.DataController().getData("evtMccChanged");
        if ( (sGlobalMcc != null) && (this._mapLayerMngr != null))
        {
            this._mapLayerMngr.setNetworkFilter( 'MCC', sGlobalMcc );
        }
        var sGlobalMnc= Global.DataController().getData("evtMncChanged");
        if ( (sGlobalMnc != null) && (this._mapLayerMngr != null))
        {
            this._mapLayerMngr.setNetworkFilter( 'MNC', sGlobalMnc );
        }
        var sGlobalNetwork= Global.DataController().getData("evtNetworkChanged");
        if ( (sGlobalNetwork != null) && (this._mapLayerMngr != null))
        {
            this._mapLayerMngr.setNetworkFilter( 'NetworkId', sGlobalNetwork );
        }
        
        this._sDefaultMapLayers = Global.DataController().getData("evtMapInitialize");
        this._sDefaultMapFilters = Global.DataController().getData("evtMapFilterInit");
      
        var stateList = Global.DataController().getData("evtInitialStates");
        //debugger
        if(stateList)
        {
            for (var idx=0; idx<stateList.length; idx++)
            {
                switch( stateList[idx][0] )
                {
                    case 'PLOT_OVER_WATER':
                        var bVisibility = stateList[idx][1]=='on' ? true : false;
                        this._mapLayerMngr.setPlotOverWaterVisibility(bVisibility);
                    break;
                    case 'SYMBOL_LABEL':
                        var bVisibility = stateList[idx][1]=='on' ? true : false;
                        this._mapLayerMngr.setSymbolLabelVisibility(bVisibility);
                    break;
                }
            }    
        }
        
        //Create delegates for web service call
        this._delMapConfig = Function.createDelegate(this, this.OnMapConfigReturned);
        this._delPregenData = Function.createDelegate(this, this.OnPregenDataReturned);
        this._delLegendReturned = Function.createDelegate(this, this.OnLegendDataReturned);
        this._delMapRetured = Function.createDelegate(this, this.OnMapReturned);
        this._delTooltipRetured = Function.createDelegate(this, this.OnTooltipReturned);
        this._delWebServiceError = Function.createDelegate(this, this.OnMapServiceError);
        this._delNetworkData = Function.createDelegate(this, this.OnMapNetworkDataReturned);
        
        //Call server for MapConfig, will initialize _mapLayerConfig;
        requestMapLayerService = CV.mBOSS.DAL.MapLayerWebService.GetMapConfig( Global.getConfigId(), 
                                                                               this._delMapConfig, 
                                                                               this._delWebServiceError );
        return true;
    },
    
    // *****************************************************************
    // API functions - Interface functions for users of this class
    // *****************************************************************
     
    setLayerGroupVisibility: function( layerGroup, layerVisible, reloadMap){
        //debugger
        this._mapLayerMngr.setLayerGroupVisibility(layerGroup, layerVisible);
        if (reloadMap == true ){
            this.loadMap();
        }
    },
    
    clearLayerGroupFilter: function(layerGroup,  filterMapType, reloadMap)
    {
        if (layerGroup != null ){
            this.setLayerGroupFilter(layerGroup, filterMapType, null, null );
        } else if (filterMapType != null){
            var layerFilterMap = this._mapLayerMngr.getLayerGroupsForFilterType(filterMapType);
            if ( layerFilterMap )
            {
                var layerGroupList = layerFilterMap.LayerGroupList;
                var filterType = layerFilterMap.FilterType != null ? layerFilterMap.FilterType : filterMapType;
                for( var i=0; i<layerGroupList.length; i++){
                    this._mapLayerMngr.setLayerGroupFilter(layerGroupList[i], filterType, null, null);
                }
                if (reloadMap == true ){
                    this.loadMap();
                }
            }
        }
        if (reloadMap){
            this.loadMap();
        }
    },
    setLayerGroupFilter: function(layerGroup, filterType, filerLogic, filterData, reloadMap)
    {
        //QueryFilter;
       //debugger
       if ( layerGroup != null )
       {
            var layerIdx=this._mapLayerMngr.getLayerGroupDataPregenStatus( layerGroup );
            if ( layerIdx == null ){
                this._mapLayerMngr.setLayerGroupFilter(layerGroup, filterType, filerLogic, filterData);
                if (reloadMap == true ){
                    this.loadMap();
                }
            } else {
                //Pregen layer we have to pregenerate data first
                //Then we prepare the request, including data filter
                var dataRequest = new CV.mBOSS.DAL.PregenDataRequest();
                dataRequest.ModuleName = this._mapLayerMngr.getModuleName();;
                dataRequest.LayerGroupId = layerGroup;
		        dataRequest.dataFilter  =  new CV.mBOSS.DAL.QueryFilter();
		        dataRequest.dataFilter.NeIdFilter = filterData;
		        dataRequest.dataFilter.NeFilterType = filterType;
                //Send an AJAX call to generate data
                //Increase Request ID
                //debugger
                requestResponse = CV.mBOSS.DAL.MapLayerWebService.PregenFileDataLayer( 
                                dataRequest,
                                Global.getConfigId(),
                                this._delPregenData, 
                                this._delWebServiceError, 
                                reloadMap);
                                
                //Set pendingLayer flagg, we reload map when data is returned.
                
            }
        } else {
            var layerFilterMap = this._mapLayerMngr.getLayerGroupsForFilterType(filterType);
            if ( layerFilterMap )
            {
                var filterType = layerFilterMap.FilterType != null ? layerFilterMap.FilterType : filterType;
                var layerGroupList = layerFilterMap.LayerGroupList;
                for( var i=0; i<layerGroupList.length; i++){
                    this._mapLayerMngr.setLayerGroupFilter(layerGroupList[i], filterType, filerLogic, filterData);
                }
                if (reloadMap == true ){
                    this.loadMap();
                }
            }
        
        }
    },
    // Check ./js/MapApi.js for parameter spesifications
    getLayerGroupNeFilters: function(filterIds)
    {
        return this._mapLayerMngr.getLayerGroupNeFilters(filterIds);
        
    },
    // Check ./js/MapApi.js for parameter spesifications
    setLayerGroupColumnFilter: function(i_layerGroupId, i_filterMapKey, i_columnFilterList, i_reloadMap)
    {
       if ( i_layerGroupId != null )
       { 
            var layerGroup = this._mapLayerMngr.setLayerGroupColumnFilter(i_layerGroupId, i_filterMapKey, i_columnFilterList);
            if (i_reloadMap == true ){
                this.loadMap();
            }
        } else if (i_filterMapKey != null) {
            //layerGroupId was null, we look up if ant FilterLayerGroup exists for i_filterMapKey
            //And apply filter to all LayerGroup in list
            var layerFilterMap = this._mapLayerMngr.getLayerGroupsForFilterType(i_filterMapKey);
            if ( layerFilterMap )
            {
                var filterType = layerFilterMap.FilterType != null ? layerFilterMap.FilterType : i_filterMapKey;
                var layerGroup;
                var layerGroupList = layerFilterMap.LayerGroupList;
                for( var i=0; i<layerGroupList.length; i++){
                    layerGroup = this._mapLayerMngr.setLayerGroupColumnFilter(layerGroupList[i], filterType, i_columnFilterList);
                }
                if (i_reloadMap == true ){
                    this.loadMap();
                }
            }
        }
    },
    
    clearLayerGroupColumnFilter: function(i_layerGroup, i_filterMapKey, i_reloadMap)
    {
        this.setLayerGroupColumnFilter(i_layerGroup, i_filterMapKey, null, i_reloadMap )
    },
    
    //See MapApi for explanation
    setLayerGroupDynamicMapScale: function(i_layerGroupId, i_maxScale, i_minScale, i_reloadMap)
    {
       if ( i_layerGroupId != null )
       { 
           var newMaxScale = i_maxScale ? i_maxScale : 100000000;//1:100M//this.getMapScale();
          var newMinScale = i_minScale ? i_minScale : -1;
          this._mapLayerMngr.setLayerGroupDynamicMapScale(i_layerGroupId, newMaxScale, newMinScale);
          //If maxScale undefined or null, we define a pending maxScale
          if ( i_maxScale == undefined || i_maxScale == null ){
            if ( this._pendingDynamicMapScale == null || this._pendingDynamicMapScale.length == 0){
                this._pendingDynamicMapScale = i_layerGroupId;
            } else {
                this._pendingDynamicMapScale += '|' + i_layerGroupId;
            }
          }
          if (i_reloadMap != undefined && i_reloadMap == true ){
              this.loadMap();
          }
       }
    },
    //See MapApi for explanation
    setLayerGroupSplitMapScale: function(i_UpperGroup, i_LowerGroup, i_SplitScale, i_reloadMap)
    {
       if ( i_UpperGroup!= null || i_LowerGroup != null)
       { 
          var newSplitScale = i_SplitScale ? i_SplitScale : this.getMapScale();
         
          //At splitt, upper non active (+1), lower active
          this._mapLayerMngr.setLayerGroupDynamicMapScale(i_UpperGroup, null, (newSplitScale+1));
          this._mapLayerMngr.setLayerGroupDynamicMapScale(i_LowerGroup, newSplitScale, null);
          
          
          //If maxScale undefined or null, we define a pending maxScale
          if ( i_SplitScale== undefined || i_SplitScale== null ){
            if ( this._pendingSplitMapScale == null || this._pendingSplitMapScale.length == 0){
                this._pendingSplitMapScale = i_UpperGroup+','+i_LowerGroup;
            } else {
                this._pendingSplitMapScale += '|' + i_UpperGroup+','+i_LowerGroup;
            }
          }
          if (i_reloadMap != undefined && i_reloadMap == true ){
              this.loadMap();
          }
       }
    },
    //See map api for explanation
    clearLayerGroupDynamicMapScale: function(i_layerGroupId)
    {
        if ( i_layerGroupId ){
            this._mapLayerMngr.setLayerGroupDynamicMapScale(i_layerGroupId, -1, -1);
        }
    },
    
    
    
    setPlotOverWaterVisibility: function( bVisibility, i_reloadMap )
    {
    
        //Set visibility
        this._mapLayerMngr.setPlotOverWaterVisibility(bVisibility);
        //Redraw map
        if (i_reloadMap != false)
            this.loadMap();
    },
    
    getPlotOverWaterVisibility: function( )
    {
        //Get visibility
        return this._mapLayerMngr.getPlotOverWaterVisibility();
    },
    
    setSymbolLabelVisibility: function( bVisibility, i_reloadMap )
    {
    
        //Set visibility
        this._mapLayerMngr.setSymbolLabelVisibility(bVisibility);
        //Redraw map
        if (i_reloadMap != false)
            this.loadMap();
    },
    
    getSymbolLabelVisibility: function( )
    {
        //Get visibility for symbol label
        return this._mapLayerMngr.getSymbolLabelVisibility();
    },
    
    setMapLabelText: function(location, text, visibility, redraw)
    { 
        this._mapDataMngr.setMapLabelText(location, text, visibility);
        if ( redraw && redraw == true ){
            this.loadMap();
        }
    },
    
    setMapLabelVisibility: function(location, visibility, redraw)
    { 
        this._mapDataMngr.setMapLabelVisibility(location, visibility);
        if ( redraw && redraw == true ){
            this.loadMap();
        }
    },
    
    /// Return the current MapScale e.g 1:100K returning 100000
    getMapScale: function()
    {
        return this._mapLayerMngr.getMapScale();
    },
    
    /// Returning the map rectangle in World(application) coordinates
    getMapRect: function() 
    { 
        return this._mapLayerMngr.getMapRect(); 
    },
    ///
    getMapWidthMeter: function() 
    { 
        return this._mapLayerMngr.getMapWidthMeter(); 
    },
    ///
    /// Check if any of the layers in the group is Active (Visible)
    ///
    getLayerGroupVisibility: function( i_layerGroup )
    {
        return this._mapLayerMngr.getLayerGroupVisibility( i_layerGroup );
    },
    ///
    /// Check if any of the layers in the group is potentially visible
    ///
    getLayerGroupPotVisibility: function( i_layerGroup )
    {
        return this._mapLayerMngr.getLayerGroupPotVisibility( i_layerGroup );
    },
    ///
    /// return an arr[2]
    /// arr[0] = Pipe separated list of active layergroups
    /// arr[1] = Pipe separated list of active data layers
    /// null if layerManager not initialized
    ///
    getListOfActiveLayerGroups: function()
    { 
        if ( this._mapLayerMngr != null ){
            return this._mapLayerMngr.getListOfActiveLayerGroups();
        }
        return null;
    },
    
    loadMap: function(action, param)
    {
        //If suspend flag is true, we bypass the loadMap
        if ( this._bSuspendMapLoad == true ){
            return;
        }
        
        if (this._mapClientLoaded){
            //set loading indicator visible in mBoss. The indicator is turned of in ImageLoad.js
            if ( this._loadingFlag == true ){
                Global.setLoading(false);
            }
            Global.setLoading(true);
            this._loadingFlag = true;
            this._loadPending = false;
            this._mapObject.SetWaitCursor();
            //Call MaplayerWebService to get map URL and map ObjectList
            //only do this if MapClient (Map.htm) is actuallt loaded!!!
            var mapRequest = new CV.mBOSS.DAL.MapRequest();
            var mapXmlParams = '<?xml version="1.0"?><MapParams>';
         
            //Sett screen size
            mapRequest.MapWidthPix  =  this._mapObject.getClientWidth();
            mapRequest.MapHeightPix =  this._mapObject.getClientHeight();
            if ( mapRequest.MapHeightPix == 0){
                mapRequest.MapHeightPix = mapRequest.MapWidthPix;
            }
            //Send current map location if not first time
            mapRequest.CurrWorldRect = this._mapLayerMngr.getMapRect( );
            //Get plot ower water visibility
            mapRequest.PlotOverWater = this._mapLayerMngr.getPlotOverWaterVisibility();
            //Get symbol Label visibility
            mapRequest.SymbolLabelVisibility = this._mapLayerMngr.getSymbolLabelVisibility();
            
            //Decode action & param
            switch(action){
            case CV.mBOSS.DAL.MAP_API_ACTION.MAP_API_ACTION_ZOOM:
            case CV.mBOSS.DAL.MAP_API_ACTION.MAP_API_ACTION_ZOOM_WORLD_RECT:
                mapRequest.Action = action;
                mapRequest.Rect = param;
                if ( this._requestedMapScale > 0 ){
                    mapXmlParams += this.addXmlNode("MapScale", this._requestedMapScale);
                }
                //mapRequest.ZoomFactor = this._currZoomFactor;
             break;
             case CV.mBOSS.DAL.MAP_API_ACTION.MAP_API_ACTION_MOVE:
                mapRequest.Action = action;
                mapRequest.Point  = param;
             break;
             case CV.mBOSS.DAL.MAP_API_ACTION.MAP_API_ACTION_ZOOM_POINT:
             case CV.mBOSS.DAL.MAP_API_ACTION.MAP_API_ACTION_ZOOM_WORLD_POINT:
                mapRequest.Action = action;
                mapXmlParams += this.addXmlNode("PointX", param.x);
                mapXmlParams += this.addXmlNode("PointY", param.y);
                mapXmlParams += this.addXmlNode("ZoomFactor", this._currZoomFactor);
                mapXmlParams += this.addXmlNode("MapScale", this._requestedMapScale);
                mapRequest.Point  = param;
             break;
             case CV.mBOSS.DAL.MAP_API_ACTION.MAP_API_ACTION_SET_SCALE:
                mapRequest.Action = action;
                mapXmlParams += this.addXmlNode("MapScale", this._requestedMapScale);
             break;
             case CV.mBOSS.DAL.MAP_API_ACTION.MAP_API_ACTION_START:
                mapRequest.Action = action;
             break;
             case CV.mBOSS.DAL.MAP_API_ACTION.MAP_API_ACTION_PAN:
                mapRequest.Action = action;
                mapXmlParams += this.addXmlNode("verticalFactor", this._currPanVerticalFactor);
                mapXmlParams += this.addXmlNode("horizontalFactor", this._currPanHorizontalFactor);
             break;
             default:
                //No change in geograpgic coordinates, possible new data layers
                mapRequest.Action = CV.mBOSS.DAL.MAP_API_ACTION.MAP_API_ACTION_GETMAP;
             break;
            }
            //Register the mapparameters End xml tag MapParams
             //debugger
            mapXmlParams += '</MapParams>';
            mapRequest.XmlMapParameters = mapXmlParams;
            //debugger
           
            mapRequest.DataRequest = this._mapLayerMngr.getLayersRequest();
            mapRequest.DataRequest.MapLabels = this._mapDataMngr.getMapLabel();
            mapRequest.DataRequest.PendingDynMapScaleGroups = this._pendingDynamicMapScale;
			mapRequest.DataRequest.PendingSplitMapScaleGroups = this._pendingSplitMapScale;
			
            //WE DONT Send the GroupList itself
            var bckGroupList = mapRequest.DataRequest.LayerGroups;
            mapRequest.DataRequest.LayerGroups = null;
            //debugger
            //this.SetDataRequest( mapRequest.DataRequest );
            
            //We count up the request counter and sens as parameter
            this._currentMapRequestId++;
            mapRequest.MapRequestId = this._currentMapRequestId;
            if ( this._bDebug == true ){
                var curtime = new Date();
                this._StartDate = curtime.getTime();
            }
            if ( this._setLoadingText != null ){
                this._mapObject.setLoadingImg();
            }
            requestMapLayerService = CV.mBOSS.DAL.MapLayerWebService.GetMap(
                     mapRequest,            //params
                    Global.getConfigId(),
                    this._delMapRetured,         //Complete event
                    this._delWebServiceError   //Timeout event
            );
            //Restore GroupList
            mapRequest.DataRequest.LayerGroups = bckGroupList;
            var bNewCoordMap = (mapRequest.Action == CV.mBOSS.DAL.MAP_API_ACTION.MAP_API_ACTION_GETMAP) ? false : true;
            Global.EventController().fireThisEvent("evtLoadingMap", this, bNewCoordMap); 
        } else {
            this._loadPending = true;
        }
    },
    
        
    // Zoom to initial zoomlevel an map centre
    zoomStart: function()
    {
        this.setMapMode(this.EnumMapMode().MAP_MODE_ZOOM_START);
    },
    
    // Zoom to the specified point in world coordinates
    zoomToWorldPoint: function( easting, northing, scale)
    {   
        //debugger
        var point = new CV.mBOSS.DAL.Point();
        point.x = easting;
        point.y = northing;
        var action = CV.mBOSS.DAL.MAP_API_ACTION.MAP_API_ACTION_ZOOM_WORLD_POINT;
       
        //this.drawShape(easting, northing, 'CIRCLE', 40, "red");
       
        if( scale ){
            this._requestedMapScale = scale;
        }
       
        this.loadMap( action,  point);
        
        //Reset requestscale
        this._requestedMapScale = 0;
    },
    
    zoomToWorldRect:  function(X1, Y1, X2, Y2, i_minscale, i_extendPercent)
    {
        // DO a zero size test first
        if( (X2-X1) == 0 && (Y2-Y1)==0 ){
            //Defaulter til 1:1000 scale, should be read from config
            //But this is more or less error check anyway
            var minScale = (i_minscale) ? i_minscale : 8000;
            return this.zoomToWorldPoint(X1, Y1, minScale);
        }   
    
        var rect = new CV.mBOSS.DAL.Rectangle();

        //In case points
        var LLX = Math.min(X1,X2);
        var LLY = Math.min(Y1,Y2);
        var URX = Math.max(X1,X2);
        var URY = Math.max(Y1,Y2);
        
        if ( i_extendPercent )
        {
            //debugger
            //We extend the area with the percentage given
            var eastExtend = (URX - LLX)*(i_extendPercent/100)/2;
            var northExtend = (URY - LLY)*(i_extendPercent/100)/2;
            rect.LLX = LLX - eastExtend;
            rect.LLY = LLY - northExtend;
            rect.URX = URX + eastExtend;
            rect.URY = URY + northExtend;
        } else 
        {
            rect.LLX = LLX;
            rect.LLY = LLY;
            rect.URX = URX;
            rect.URY = URY;
        }
        
        var action = CV.mBOSS.DAL.MAP_API_ACTION.MAP_API_ACTION_ZOOM_WORLD_RECT;
        
        // Note:
        // Callback from mapiFrame, We are therefore in the iFrame document context(Map.htm)
        // Therefore need to call loadMap function from global MapApi object
       this._requestedMapScale = (i_minscale) ? i_minscale : 8000;
       this.loadMap( action,  rect);
       this._requestedMapScale = 0;
     },
     
     //Pan the map window with a factor relative to the screen width
     panMap: function(i_verticalFactor, i_horizontalfactor)
     { 
        this._currPanVerticalFactor=i_verticalFactor; 
        this._currPanHorizontalFactor=i_horizontalfactor; 
         
        this.loadMap( CV.mBOSS.DAL.MAP_API_ACTION.MAP_API_ACTION_PAN );
        return true;
     },
     
     setMapScale: function( scale ) 
    { 
        var action = CV.mBOSS.DAL.MAP_API_ACTION.MAP_API_ACTION_SET_SCALE;
        if( scale ){
            this._requestedMapScale = scale;
        }
       
        this.loadMap( action );
        
        //Reset requestscale
        this._requestedMapScale = 0;
    },
    
    setMapMode: function( enumMapMode )
    {
       switch ( enumMapMode ){
            case this.EnumMapMode().MAP_MODE_MOVE:
                this._mapObject.setAction(this._mapObject.MAP_ACTION_MOVE);
                this._currMapMode = enumMapMode;
            break;
            case this.EnumMapMode().MAP_MODE_SELECT:
                this._mapObject.setAction(this._mapObject.MAP_ACTION_SELECT);
                this._currMapMode = enumMapMode;
            break;
            case this.EnumMapMode().MAP_MODE_ZOOM_RECT:
                this._currZoomFactor = this._configZoomInFactor;
                this._mapObject.setAction(this._mapObject.MAP_ACTION_ZOOM_IN);
                this._currMapMode = enumMapMode;
            break;
            case this.EnumMapMode().MAP_MODE_ZOOM_OUT:
                this._currZoomFactor = this._configZoomOutFactor;
                this._mapObject.setAction(this._mapObject.MAP_ACTION_ZOOM_OUT);
                this._currMapMode = enumMapMode;
            break;
            case this.EnumMapMode().MAP_MODE_ZOOM_START:
            {
                //Send message tha map is going to initial state
                 Global.EventController().fireThisEvent("evtMapZoomStart", this, null); 
                //This is actually not a "Mode", but we use it for convinience as map action
                var action = CV.mBOSS.DAL.MAP_API_ACTION.MAP_API_ACTION_START;
                this.loadMap( action);
            }
            break;
            case this.EnumMapMode().MAP_MODE_DIGITIZE_RECT:
                this._mapObject.setAction(this._mapObject.MAP_ACTION_SELECT);
                this._currMapMode = enumMapMode;
             break;
            case this.EnumMapMode().MAP_MODE_DIGITIZE_POLYGON:
                this._mapObject.setAction(this._mapObject.MAP_ACTION_SELECT);
                this._currMapMode = enumMapMode;
            break;
            case this.EnumMapMode().MAP_MODE_SELECT_BY_POLYGON:
            {
                this._mapDataMngr.getSelectPolygon().clear();
                this._mapObject.clearCanvas(this._shapeCanvas);
                this._mapObject.setAction(this._mapObject.MAP_ACTION_CLICK);
                this._drawPolIgnorePoint= true;
                this._suspendedMapMode = this._currMapMode;
                this._currMapMode = enumMapMode;
           }
           break;
           case this.EnumMapMode().MAP_MODE_MEASUREMENT_RULER:
            {
                this._mapDataMngr.getSelectPolygon().clear();
                this._mapObject.clearCanvas(this._shapeCanvas);
                this._mapObject.setAction(this._mapObject.MAP_ACTION_RULER);
                this._drawPolIgnorePoint= true;
                this._suspendedMapMode = this._currMapMode;
                this._currMapMode = enumMapMode;
           }
           
            break;
        }
    },
    
    getMapURL: function()
    {
        if ( this._mapObject != null ){
            return this._mapObject.getMapURL();
        }
        return null;
    },
    
    getMapMode: function()
    {
        return this._currMapMode;
    },
    getLegendData: function()
    {
        return this._mapLayerMngr.getLegendData();
    },
    
    //Return a container "div" above the map which can contain a floating legend
    getLegendContainer: function()
    { 
        return this._mapObject.getLegendContainer();
    },
    //
    // See arg definitions in MapApi.js
    //
    drawImage: function(Easting, Northing, image, text, hint)
    { 
        var clientWidth  = this._mapObject.getClientWidth();
        var clientHeight = this._mapObject.getClientHeight();
        var mapRect = this.getMapRect();
        // Calculate device coordinates
        //Use temp variables for radability
        //Check if position is null, then use map centre
        if (Easting != null && Northing != null )
        {
            x_dev = parseInt(((Easting - mapRect.LLX)/(mapRect.URX - mapRect.LLX))*clientWidth);
            y_dev = parseInt(((mapRect.URY - Northing)/(mapRect.URY - mapRect.LLY))*clientHeight);
        } else {
            x_dev = parseInt(clientWidth/2);
            y_dev = parseInt(clientHeight/2);
        }
        //debugger
        //Then draw shape, but incase someone draw on large scales we accumulate equal points
        this._mapObject.drawImage(x_dev, y_dev, image, text, hint);
    },
    
    
    //
    //See arg definitions in MapApi.js
    //
    drawShape: function(Easting, Northing, shapeType, shapeParam, lineColor, shadowColor, innerColor, fillColor, bAppendToCanvas, bZoomIfOutside)
    { 
        //Convert request from Single point request to ArrayList request
         var posList = new Array(1);
         posList[0] = new Array(2);
         posList[0][0] = Easting;
         posList[0][1] = Northing;
    
        //Call the actual draw function
        this.drawShapeList(posList, shapeType, shapeParam, lineColor, shadowColor, innerColor, fillColor, bAppendToCanvas, bZoomIfOutside);
    },
    
    drawShapeList: function(posList, shapeType, shapeParam, lineColor, shadowColor, innerColor, fillColor, bAppendToCanvas, bZoomIfOutside)
    { 
        //First convert from World coordinates to Device coordinates
        var mapRect = this.getMapRect();
         //Check if any point outside current map area
        if ( (bZoomIfOutside && bZoomIfOutside==true) )
        {
            var bOutside = false;
            var lly=null,llx=null,ury=null,urx=null;
             
            var Easting, Northing;
            for (var i=0; i< posList.length; i++){
                //Create the new bounding box
                lly = (lly && lly<posList[i][1]) ? lly : posList[i][1];
                llx = (llx && llx<posList[i][0]) ? llx : posList[i][0];
                ury = (ury && ury>posList[i][1]) ? ury : posList[i][1];
                urx = (urx && urx>posList[i][0]) ? urx : posList[i][0];
                
                //Use temp variables for readability
                Easting  = posList[i][0];
                Northing = posList[i][1];
                if (Easting < mapRect.LLX || Easting > mapRect.URX || 
                    Northing < mapRect.LLY || Northing > mapRect.URY) 
                {
                    bOutside = true;
                }
            }
            
            //Check if outside current map area
            if (bOutside == true) 
            {
                //Then we should change map center first
                // 1) Save request
                
                //Create an array ofe one coordinate to have a generic interface
                var idx=0
                this._drawShapeRequest = new Array();
                this._drawShapeRequest[idx++] = posList;
                this._drawShapeRequest[idx++] = shapeType;
                this._drawShapeRequest[idx++] = shapeParam;
                this._drawShapeRequest[idx++] = lineColor;
                this._drawShapeRequest[idx++] = shadowColor;
                this._drawShapeRequest[idx++] = shadowColor;
                this._drawShapeRequest[idx++] = fillColor;
                
                // If one position or current scale is large enoufgh to fit all points, we only change map centre
                //Else we zoom to new maprect
                if ( posList.length == 1 || 
                    (((urx - llx) < (mapRect.URX - mapRect.LLX)) && ((ury - lly) < (mapRect.URY - mapRect.LLY))))
                {
                    //The zoom center point
                    this.zoomToWorldPoint((urx + llx)/2, (ury + lly)/2);
                } else {
                    //Zoom to new rect (Increase 10percent, min scale 1:8000)
                    this.zoomToWorldRect(llx, lly, urx, ury, 8000, 10);
                }
                return;
            }
        }
        //First clear previous symbols
        if (!bAppendToCanvas){
            this._mapObject.clearCanvas(this._shapeCanvas);
        }
        
        //then draw all pending shapes
        var Easting, Northing;
        var clientWidth  = this._mapObject.getClientWidth();
        var clientHeight = this._mapObject.getClientHeight();
        var x_dev, y_dev, x_prev = -99999, y_prev=-99999;
        for(var i=0; i<posList.length; i++){
            // Calculate device coordinates
            //Use temp variables for radability
            Easting  = posList[i][0];
            Northing = posList[i][1];
            //Check if position is null, then use map centre
            if (Easting != null && Northing != null )
            {
                x_dev = parseInt(((Easting - mapRect.LLX)/(mapRect.URX - mapRect.LLX))*clientWidth);
                y_dev = parseInt(((mapRect.URY - Northing)/(mapRect.URY - mapRect.LLY))*clientHeight);
            } else {
                x_dev = parseInt(clientWidth/2);
                y_dev = parseInt(clientHeight/2);
            }
            //debugger
            //Then draw shape, but incase someone draw on large scales we accumulate equal points
            //Cells on same site
            if ( x_dev != x_prev && y_dev != y_prev)
            {
                this._mapObject.drawShape(this._shapeCanvas, x_dev, y_dev, shapeType, shapeParam, lineColor, shadowColor, innerColor, fillColor);
            }
            x_prev = x_dev;
            y_prev = y_dev;
        }
    },
    
    ///
    /// If a Pending shape is defined, draw it
    ///
    drawPendingShape: function( drawShapeRequest )
    {
        if ( this._drawShapeRequest )
        {
            var idx=0;
            this.drawShapeList(this._drawShapeRequest[idx++],//PosList
                               this._drawShapeRequest[idx++],  // shapeType;
                               this._drawShapeRequest[idx++],  // shapeParam;
                               this._drawShapeRequest[idx++],  // lineColor;
                               this._drawShapeRequest[idx++],  // shadowColor;
                               this._drawShapeRequest[idx++],  // innerColor;
                               this._drawShapeRequest[idx++]); // fillColor;);
        }
    },
    
    drawLine: function (p1_easting, p1_northing, p2_easting, p2_northing, lineThickness, lineColor, shadowColor, bAppendToCanvas )
    { 

        var pos1 = this.worldToDevPoint(p1_easting, p1_northing);
        var pos2 = this.worldToDevPoint(p2_easting, p2_northing);
        
        //First clear previous symbols
        if ( !bAppendToCanvase){
            this._mapObject.clearCanvas(this._shapeCanvas);
        }
        
        if ( shadowColor!= null && shadowColor.length > 0){
            this._mapObject.drawShape(this._shapeCanvas, pos1, pos2, 'LINE', 
                                      lineThickness+2, shadowColor, null,null,null, true);
        }
        this._mapObject.drawShape(this._shapeCanvas, pos1, pos2, 'LINE', 
                                  lineThickness, lineColor, null,null,null,false);
        return true;
    },
    
    drawLineList: function (posList, lineThickness, lineColor, shadowColor, bAppendToCanvas )
    { 
        if ( posList==null || posList.length==0){
            return false;
        }
         //First clear previous symbols
        if ( !bAppendToCanvas){
            this._mapObject.clearCanvas(this._shapeCanvas);
        }
        for (var i=0; i<posList.length; i++){
            this.drawLine(posList[i][0], posList[i][1], posList[i][2], posList[i][3], lineThickness, lineColor, shadowColor, true);
        }
        return true;
    },
    
    
    ///
    /// Check if the provided layergroup has dynamicLegend, if null, check all
    /// Call MapDataLayer for Legends
    ///
    getDynamicLegend: function( i_layerGroup )
    {
        var requestList = "";
        if ( i_layerGroup != undefined && i_layerGroup != null ){
            if ( i_layerGroup.Property.Active == true &&  i_layerGroup.Property.bDynamicLegend == true ){
                requestList = i_layerGroup.LayerGroupId;
            }
        } else {
            requestList = this._mapLayerMngr.getDynamicLegendGroups();
        }
        if ( requestList != null && requestList.length > 0 ){
            var dataRequest = this._mapLayerMngr.getLayersRequest( false );
            //WE DONT Send the GroupList itself
            dataRequest.ActiveLayerGroupList = requestList;
            dataRequest.DataFilter.MapLim   = this._mapLayerMngr.getMapRect();
            dataRequest.DataFilter.MapScale = this._mapLayerMngr.getMapScale();
            var bckGroupList = dataRequest.LayerGroups;
            dataRequest.LayerGroups = null;
                

            CV.mBOSS.DAL.MapLayerWebService.GetLegend(
                    dataRequest, 
                    Global.getConfigId(),
                    this._delLegendReturned,         //Complete event
                    this._delWebServiceError
            );
             
             dataRequest.LayerGroups = bckGroupList;
        }
        else
            Global.EventController().fireThisEvent("evtDynamicLegendChanged", this, true); 
    },
    
    
    ///
    ///MapApi Initiate digitize rectangle operation
    ///Result broadcasted as evtDigitizeRect
    ///
    digitizeRect: function()
    { 
        this._suspendedMapMode = this._currMapMode;
        this.setMapMode( this.EnumMapMode().MAP_MODE_DIGITIZE_RECT );
        return true;
    },
    
    ///
    ///MapApi change current module
    ///
    changeModule: function( newModule )
    {
        if ( this._mapLayerMngr != null)
        {
            var oldModule = this._mapLayerMngr.getModuleIdx();
            this._mapLayerMngr.setModule( newModule )
            if ( oldModule != this._mapLayerMngr.getModuleIdx() ){
                //Clear selection list
                Global.EventController().fireThisEvent("evtSelectionListChanged", this, null);
                this.loadMap();
            }
        }
    },
    
    printPreview: function()
    {   
        this._mapObject.onContextActionRequest( "ACTION_PRINT_PREVIEW_MAP" );
        return true;
    },
    printMap: function()
    { 
        this._mapObject.onContextActionRequest( "ACTION_PRINT_MAP" );
        return true;
    },
    
    ///
    /// Class Event function 
    ///
    
    onSystemChanged: function( sender, context )
    {
        if ( this._mapLayerMngr != null)
        {
            this._mapLayerMngr.setSystype(context)
            this.loadMap();
        }
    },
    
    
    
    
    onStatusChanged: function( sender, context )
    {
        if ( this._mapLayerMngr != null)
        {
           this._mapLayerMngr.setStatus(context)
           this.loadMap();
        }
    },
    
    onServiceChanged: function( sender, context )
    {
        if ( this._mapLayerMngr != null)
        {
           this._mapLayerMngr.setService(context)
           this.loadMap();
        }
    },
    onQualityChanged: function( sender, context )
    {
        if ( this._mapLayerMngr != null)
        {
           this._mapLayerMngr.setQuality(context)
           this.loadMap();
        }
    },
    onSeverityChanged: function( sender, context )
    {
        if ( this._mapLayerMngr != null)
        {
           this._mapLayerMngr.setSeverity(context)
           this.loadMap();
        }
    },
    
    onTimeLevelChanged: function( sender, context )
    {
        if ( this._mapLayerMngr != null)
        {
           this._mapLayerMngr.setTimeLevel(context)
           this.loadMap();
        }
    },
    
    onHistoryChanged: function( sender, context )
    {
        if ( this._mapLayerMngr != null)
        {
           this._mapLayerMngr.setHistoryFilter(context)
           this.loadMap();
        }
    },
    onSelectionListChanged: function( sender, contextSelectionList )
    {
        if ( sender != this ){
            this.drawOutlineSymbols(contextSelectionList, this._mapDataMngr.getDevicePropertyList(contextSelectionList) );
            //alert("some sendt");
        
        } else {
            //alert("I sendt:"+context);
        }
    },
    onMccChanged: function( sender, context )
    {
        if ( this._mapLayerMngr != null)
        {
           this._mapLayerMngr.setNetworkFilter('MCC', context)
           this.loadMap();
        }
    },
    onMncChanged: function( sender, context )
    {
        if ( this._mapLayerMngr != null)
        {
           this._mapLayerMngr.setNetworkFilter('MNC', context)
           this.loadMap();
        }
    },
    onNetworkChanged: function( sender, context )
    {
        if ( this._mapLayerMngr != null)
        {
           this._mapLayerMngr.setNetworkFilter('NetworkId',context)
           this.loadMap();
        }
    },
    
    
    /// 
    /// Callback from WebService, Map is returned with data
    ///
    OnMapReturned: function( mapResponse )
    {
        //Reset cursor if set to e.g wait, and reset loading indicator
        Global.setLoading(false);
        this._mapObject.setCurrCursor();
        this._mapObject.clearCanvas(this._selectCanvas);
        this._loadingFlag = false;
        
        if ( mapResponse == null){
            if (this._mapNoresponseMessage && this._mapNoresponseMessage != "null"){
                alert(this._mapNoresponseMessage);
            } else {
                alert("Map server busy, sorry for the inconvenience. Please try again in a few moments");
            }
            return;
        }
    
        //Fitst we check if this is the request we are waiting for
        if (this._currentMapRequestId != mapResponse.MapRequestId)
        {
            //alert("Not the map I was waiting for: Sent:"+this._currentMapRequestId+" Returned:"+mapResponse.MapRequestId);
            return;
        }
         
        if ( this._bDebug == true ){
           var curtime = new Date();
           var RequestTime_ms = "Client Map request Time ms = "+(curtime.getTime() - this._StartDate)+" Reqid="+mapResponse.MapRequestId;
           CV.mBOSS.DAL.MapLayerWebService.ClientLog( RequestTime_ms ); 
        }
        
        //reset possibloe map move offset
         this._mapObject.ResetMapMove();
        if( this._mapObject ){
            //Set the map URL from the Map web service
            //The web service return URL relative to application root
            //Here we all the current path relative to the root
            if ( mapResponse ){
                // REMOVED Now config: var mapURL = "../../.."+mapResponse.MapURL;
                this._mapObject.loadURL( mapResponse.MapURL );
                
                //Set MapLocation (Contains: mapLimit, mapScale )
                if ( this._mapLayerMngr != null)
                {
                     this._mapLayerMngr.setMapLocation( mapResponse.MapLocation );
                    if ( this._pendingDynamicMapScale != null ){
                        var newScale = this.getMapScale();
                        var pendingList = this._pendingDynamicMapScale.split('|');
                        for( var i=0; i<pendingList.length; i++){
                            this._mapLayerMngr.setLayerGroupDynamicMapScale(pendingList[i], newScale, -1);
                        }
                        this._pendingDynamicMapScale = null;
                    }
                    if ( this._pendingSplitMapScale != null ){
                        var newScale = this.getMapScale();
                        var pendingList = this._pendingSplitMapScale.split('|');
                        for( var i=0; i<pendingList.length; i++){
                            var splitGroups = pendingList[i].split(',');
                            //Upper, not active, Lower active
                            this._mapLayerMngr.setLayerGroupDynamicMapScale(splitGroups[0], null, (newScale+1));
                            this._mapLayerMngr.setLayerGroupDynamicMapScale(splitGroups[1], newScale, null);
                        }
                        this._pendingSplitMapScale = null;
                    }
                }
                // Set map overlay data
                if ( this._mapDataMngr != null )
                {
                    if ( mapResponse.DataLayer != null )
                    {
                        //Apply provided data
                        this.setNewLayerData(mapResponse.DataLayer);
                    } 
                    else 
                    {
                        //Clear old data and call server for MapConfig, will initialize _mapLayerConfig;
                        Global.setLoading(true);
                        //Clear Data, and potential spatialMap
                        this._mapDataMngr.setData( null );
                        this._mapObject.setAreaLayerMap( "" );
                        
                        CV.mBOSS.DAL.MapLayerWebService.GetMapNetworkData( 
                            mapResponse.MapURL,
                            this._delNetworkData, 
                            this._delWebServiceError, 
                            mapResponse.MapRequestId );  
                    }
                }
            } else {
                alert("Map server failed, contact sysadm");
                return;
            }
        } else {
            alert("Map not Created!!");
            return;
        }
        
        //If ant Pending draw shapes, we draw it noe
        if (this._drawShapeRequest != null)
        {
            this.drawPendingShape();
            this._drawShapeRequest = null;
        }else{
            //Since we don't store the canvas we clear if map redrawn without pending shapes
            this._mapObject.clearCanvas(this._shapeCanvas);
        }
        // Fire evtMapWindowChanged event
        Global.EventController().fireThisEvent("evtMapWindowChanged", this, null); 
        // Update legend
        Global.EventController().fireThisEvent("evtDynamicLegendChanged", this, true);
        
        //Check if a dynamic legend has to be updated from server side
        this.getDynamicLegend();
     },
     
     ///
     /// Callback from WebService, return the network data collection for the current map
     ///
     OnMapNetworkDataReturned : function( dataLayer, context)
     {
        //Turn off loading indicator
        Global.setLoading(false);
        
        //Check if this was the correct request. Context parameter send the request ID
        if ( context != null && this._currentMapRequestId != context)
        {
            //alert("Not the map I was waiting for: Sent:"+this._currentMapRequestId+" Returned:"+context);
            return;
        }
        // Then it's time to send network data to MapDataManager
        if ( dataLayer != null && this._mapDataMngr != null){
            //Apply new data
            this.setNewLayerData(dataLayer);
        }
        //Send separate request to clear data cache on server
        if ( dataLayer && dataLayer.MapURL ){
            CV.mBOSS.DAL.MapLayerWebService.ClearRequestCache( dataLayer.MapURL );
        }
     },
     
     OnTooltipReturned: function( i_tooltipResponse , i_tooltipCoord)
     {
       if ( i_tooltipResponse != null ){
            if ( this._tooltipRequestCoord == i_tooltipCoord){
                var coordPoint = i_tooltipCoord.split(',');
                this._mapObject.setTooltip(i_tooltipResponse.Tooltip, parseInt(coordPoint[0]), parseInt(coordPoint[1]));
                if ( i_tooltipResponse.PropertyList!= null && i_tooltipResponse.PropertyList.length > 0){
                    Global.EventController().fireThisEvent("evtTooltipDataChanged", this, i_tooltipResponse.PropertyList); 
                } 
            }
         }
     },
     
     OnPregenDataReturned: function( pregenResponse, bRedraw )
     {
        //Turn off loading indicator
        Global.setLoading(false);
        
        //Then we do what we need whith the data
        //debugger
        //And redraw map I quess
        if ( bRedraw == true ){
            
        }
     
     },
     
     OnLegendDataReturned:function (legendData)
     {
        if ( legendData ){
            this._mapDataMngr.setData(legendData);
            Global.EventController().fireThisEvent("evtDynamicLegendChanged", this, true); 
            
        }
     },
     
     ///
     /// Callback from webservice
     ///
     OnMapConfigReturned: function(retObject)
     {
        //debugger
        if (retObject == null){
            alert("MapApi: No map configuration found. Contact Sysadm");
        }
        this._mapLayerMngr.initialize( retObject );
        this._mapClientLoaded = true;
        
        // We also check and set the current Module
        var sGlobalModule = Global.DataController().getData("evtModuleChanged");
        if ( (sGlobalModule != null) && (this._mapLayerMngr != null)){
            
            this._mapLayerMngr.setModule( sGlobalModule );
        } else {
            alert("MapApi : No default module defined, defaults to FaultiX");
            this._mapLayerMngr.setModule( 'FaultiX' );
        }
        //Turn On/Off some global map layer settings
        //debugger
        this._SelectionEnabled = this._mapLayerMngr.getMapSelectionEnabled();
        this._ContextMenuEnabled = this._mapLayerMngr.getMapContextMenuEnabled();
        if ( this._mapLayerMngr.getMapAjaxTooltipEnabled() == true ){
            //This will enable ajax tooltip, as stop events will be sent
            this._ajaxTooltipEnabled = true;
            this._mapObject.setMouseMoveStoppedEvent(true); 
        }
        
        if (this._sDefaultMapLayers != null && this._sDefaultMapLayers.length > 0){
            //Default map layers
            if (this._sDefaultMapLayers[0] instanceof Array){
                for (var i=0; i<this._sDefaultMapLayers.length; i++){
                    for (var j=1; j<this._sDefaultMapLayers[i].length; j++) {
                       this._mapLayerMngr.setLayerGroupVisibility(this._sDefaultMapLayers[i][j], true, this._sDefaultMapLayers[i][0]);
                    }
                }
            }
            else {
            for (var i=0; i<this._sDefaultMapLayers.length; i++){
                this._mapLayerMngr.setLayerGroupVisibility(this._sDefaultMapLayers[i], true);
                }
            }
        }



        if ( this._sDefaultMapFilters != null ){
            for (var i=0; i<this._sDefaultMapFilters.length; i++){
                var filter = this._sDefaultMapFilters[i];
                switch ( filter[0]){
                    case 'COL_FILTER':
                        this._mapLayerMngr.setLayerGroupColumnFilter(filter[1],filter[2], filter[3], false);
                    break;
                
                }
            }
        }
        if ( this._loadPending == true){
            this.loadMap(CV.mBOSS.DAL.MAP_API_ACTION.MAP_API_ACTION_START);
        }
     },
     /// 
     /// Callback from WebService - Service timeout
     ///
    OnMapServiceError: function(retObject)
    {
        //turn off loading icon
        Global.setLoading(false);
        this._loadingFlag = false;
     
        if ( retObject ){
            alert("OnMapServiceError: "+retObject.get_message());
        } else{
            alert("OnMapServiceError");
        }
    },
    
    
    
    // *********************************************************************************
    // Callback / Action handlers from mapObject
    // Note that local function in this class is referenced by mapApi.  not this
    // These callbacks are in the mapObject document context
    // *********************************************************************************
    
    /* Responding to zoom action in map */
   OnMapZoomedToPoint: function(x, y, bWorldCoordinates){
        //debugger
       //requestMap(ACTION_ZOOM_TO_POINT, "&x=" + x + "&y=" + y + "&factor=" + zoomFactor);
        var point = new CV.mBOSS.DAL.Point();
        point.x = x;
        point.y = y;
        var action;
        if ( bWorldCoordinates && bWorldCoordinates == true ){
            this._requestedMapScale = 10000;
            action = CV.mBOSS.DAL.MAP_API_ACTION.MAP_API_ACTION_ZOOM_WORLD_POINT;
        } else {
            action = CV.mBOSS.DAL.MAP_API_ACTION.MAP_API_ACTION_ZOOM_POINT;
        }
        this.loadMap( action,  point);
        this._requestedMapScale = 0;
    },
    
    /* Responding to "zoom to rect" action in map */
   OnMapZoomed: function(LLX, LLY, URX, URY){
        if ( this._currMapMode == this.EnumMapMode().MAP_MODE_ZOOM_RECT ){
            var rect = new CV.mBOSS.DAL.Rectangle();
            rect.LLX = LLX;
            rect.LLY = LLY;
            rect.URX = URX;
            rect.URY = URY;
            var action = CV.mBOSS.DAL.MAP_API_ACTION.MAP_API_ACTION_ZOOM;
            
            // Note:
            // Callback from mapiFrame, We are therefore in the iFrame document context(Map.htm)
            // Therefore need to call loadMap function from global MapApi object
           this.loadMap( action,  rect);
       } else if (this._currMapMode == this.EnumMapMode().MAP_MODE_ZOOM_OUT){
            var point = new CV.mBOSS.DAL.Point();
            point.x = (LLX + URX)/2;
            point.y = (LLY+URY)/2;
            var action = CV.mBOSS.DAL.MAP_API_ACTION.MAP_API_ACTION_ZOOM_POINT;
            this.loadMap( action,  point);
       } else {
            //No action, we reset map cursor
           this._mapObject.setCurrCursor();
       }
    },
    
    ///
    /// Event from map: map moved with device delta dx and dy
    ///
    OnMapMoved: function(dx, dy){
        //requestMap(ACTION_MOVE,  "&x=" + dx + "&y=" + dy);
        var point = new CV.mBOSS.DAL.Point();
        point.x = dx;
        point.y = dy;
        var action = CV.mBOSS.DAL.MAP_API_ACTION.MAP_API_ACTION_MOVE;
        
        //Reload map
        this.loadMap( action,  point);
    },
    ///
    ///Event from Map. The img <map> has broadcasted an onClick event
    ///
    OnAreaItemSelected: function(mapAreaItem)
    {
        if(this._SelectionEnabled == true && this._currMapMode == this.EnumMapMode().MAP_MODE_SELECT){
            //String Format==  layerGroup.LayerGroupId + ":" + layer.LayerSpec.LayerId+ ":" + ne.Id;
            var infoArr = mapAreaItem.split(':');
            var areaItem=this._mapDataMngr.findAreaItem(infoArr[0], infoArr[1], infoArr[2]);
            Global.EventController().fireThisEvent("evtAreaElementSelected", this, areaItem); 
        }
    },
    ///
    /// Event from map: Area (or point) selected in device coordinates
    ///
    OnMapAreaSelected: function(LLX, LLY, URX, URY, bMultiSelect)
    {
        //debugger
        if ( this._SelectionEnabled == true && this._currMapMode == this.EnumMapMode().MAP_MODE_SELECT && this._mapDataMngr != null){
            var mapElementData = null;
            //Do not send zero sized rect to search for objects, add a margin
            if ((LLX==URX) && (LLY==URY)){
                var bSelectableOnly = true;
                var bSearchNetworkElements = false;
                //Search selected network elements in point
                mapElementData = this._mapDataMngr.findMapElement(LLX, LLY, this._EnumObjectHitMode.OBJECT_HIT_SELECTABLE, bSearchNetworkElements);
                if ( mapElementData== null){
                    //Search selected area elements in point
                    var bSearchAreaElements = true;
                    var areaElementData = this._mapDataMngr.findMapElement(LLX, LLY, this._EnumObjectHitMode.OBJECT_HIT_SELECTABLE, bSearchAreaElements );
                    if ( areaElementData != null ){
                        //Broadcast areaElement clicked
                        //areaElements[0] == AreaLementList, [1]=PropertyList
                        var firstAreaElement = areaElementData[0][0];
                        Global.EventController().fireThisEvent("evtAreaElementSelected", this, firstAreaElement); 
                    }
                }
            } else {
                mapElementData = this._mapDataMngr.findMapElementsInArea(LLX, LLY, URX, URY);
            }
            //Add list of elements to seelction list, if null clear list
            //If list of elements selected is larger than max we send rectangle
            var aRect=null;;
            if ( this._maxSymSelect != -1 && mapElementData && mapElementData[1].length > this._maxSymSelect){
                aRect = new CV.mBOSS.DAL.Rectangle();
                aRect.LLX=LLX; aRect.LLY=LLY; aRect.URX=URX; aRect.URY=URY;
            }
            this.addToSelectionList( mapElementData,  bMultiSelect, aRect);
            
        } 
        else if (this._currMapMode == this.EnumMapMode().MAP_MODE_DIGITIZE_RECT )
        {
            //LLX, LLY, URX, URY
            //Check if it was a rect or a point
            var aArea = new Array();
            var worldPoint= new Array(2)
            if ( (URX-LLX)<this._minDigitizeRectSize || (LLY-URY)<this._minDigitizeRectSize)
            {
                this.devPointToWorldPoint( (LLX+URX)/2, (LLY+URY)/2, worldPoint);
                aArea[0] = worldPoint[0];//X
                aArea[1] = worldPoint[1];//Y
            } else {
                this.devPointToWorldPoint( LLX, LLY, worldPoint);
                aArea[0] = worldPoint[0];//LLX
                aArea[1] = worldPoint[1];//LLY
                this.devPointToWorldPoint( URX, URY, worldPoint);
                aArea[2] = worldPoint[0];//URX
                aArea[3] = worldPoint[1];//URY
            }
            //Set back the map mode as before digitize session
            this.setMapMode(this._suspendedMapMode);
            this._suspendedMapMode = null;
            
            // Fire event about digitize finished
            Global.EventController().fireThisEvent("evtDigitizedRect", this, aArea); 
        } 
        else if (this._currMapMode == this.EnumMapMode().MAP_MODE_DIGITIZE_POINT)
        {
            //A little slack here to avoid faults if mouse moves a little
            if ( (URX-LLX)<this._minDigitizeRectSize || (LLY-URY)<this._minDigitizeRectSize ){
                var aPoint = new Array();
                var worldPoint= new Array(2)
                this.devPointToWorldPoint( LLX, LLY, worldPoint);
                aPoint[0] = worldPoint[0];
                aPoint[1] = worldPoint[1];
                
                this.setMapMode(this._suspendedMapMode);
                this._suspendedMapMode = null;
                // Fire event about digitize finished
                Global.EventController().fireThisEvent("evtDigitizedPoint", this, aPoint); 
            }
        }
        else if (this._currMapMode == this.EnumMapMode().MAP_MODE_DIGITIZE_POLYGON)
        {
            
        } 
       
    },
    
    ///
    ///
    /// Event from map: Device coordinates x and y clicked
    ///
    OnMapClicked: function(x, y, dblClick, bMultiSelect)
    {
        if ( this._currMapMode == this.EnumMapMode().MAP_MODE_MEASUREMENT_RULER )
        {
            var mouseMode = (dblClick == true) ? this.EnumMouseMode().MOUSE_MODE_DBL_CLICK :  this.EnumMouseMode().MOUSE_MODE_CLICK;
            this.measurementRulerHandler(x, y, mouseMode);   
        } 
        else if ( this._currMapMode == this.EnumMapMode().MAP_MODE_SELECT_BY_POLYGON )
        {
            this.selectByPolygonHandler(x, y, dblClick, bMultiSelect);
        } 
        else if (this.EnumMapMode().MAP_MODE_SELECT && this._SelectionEnabled == true)
        {
            var mapElementData = null;
            var bSelectableOnly = true;
            var bSearchNetworkElements = false;//true== Area elements, false=Network elements only
              
             if ( this._mapDataMngr != null && dblClick == true)
             {
               mapElementData = this._mapDataMngr.findMapElement(x, y, this._EnumObjectHitMode.OBJECT_HIT_SELECTABLE, bSearchNetworkElements);
               if ( mapElementData != null ){
                    var ElementList = mapElementData[0];
                    if (ElementList.length > 0 ){
                        Global.EventController().fireThisEvent("evtMapDoubleClick", this, ElementList[0]);
                    }
                }
             }
        }
    },
    
    OnMapResize: function(width, height)
    {
        this.loadMap();
    },
    
    OnMapMouseMove: function(x, y, bStopped)
    {
        //not implemented
        if ( this._mapDataMngr != null )
        {
            switch ( this._currMapMode ){
                case this.EnumMapMode().MAP_MODE_MEASUREMENT_RULER :
                    var mouseMode = bStopped == true ? this.EnumMouseMode().MOUSE_MODE_STOPPED : this.EnumMouseMode().MOUSE_MODE_MOVE;
                    this.measurementRulerHandler(x, y, mouseMode);
                break;
                default:
                {
                   var bMouseInfoAlways = this._mapLayerMngr.getMouseInfoInMapNavigationModes();
                   if ( bMouseInfoAlways == true || this._currMapMode == this.EnumMapMode().MAP_MODE_SELECT){
                        this.mouseMoveSelectHandler(x, y, bStopped);
                   }
                }
                break;
            }
        }
    },
    
    OnMapContextDataRequest: function(x, y)
    {
        //not implemented
        if ( this._mapDataMngr != null  && this._ContextMenuEnabled == true)
        {
           var mapElementArray = this._mapDataMngr.findMapElement(x, y, this._EnumObjectHitMode.OBJECT_HIT_ANY );
           if ( mapElementArray != null )
           {
             //Return array [0] ==NetworkElement list, [1] = DeviceProperty list
             return   mapElementArray[0];
           } 
        }
        return null;
    },
    
    OnRequestSetMapMode: function( requestedMapMode )
    {
        //Call MapApi to excecute the ModeChange
        var mapModeEnum = this.getMapModeEnumFromString( requestedMapMode );
        this.setMapMode(  mapModeEnum);
        //Since this was aqn internal request, we broadcast it
        Global.EventController().fireThisEvent("evtMapModeChanged", this, mapModeEnum); 
    },
    
    //*************************************************************************
    // Functions 
    //*************************************************************************
    
    
    ///
    /// Actions when MapMode is SEELCT_BY_POLYGON
    /// 
    selectByPolygonHandler: function(x, y, dblClick, bMultiSelect)
    {
        if ( this._drawPolIgnorePoint == true ){
            this._drawPolIgnorePoint = false;
            return;
            
        }
        var currPolygon = this._mapDataMngr.getSelectPolygon();
        var point1 = new CV.mBOSS.DAL.Point();
        var point2 = new CV.mBOSS.DAL.Point();
        if ( dblClick == false )
        {   //Node in polygon
            point1 = currPolygon.getLastPoint();
            currPolygon.appendXY(x,y);
            
            //Set start marker
            if ( currPolygon.getNumVertices() == 1 ){
                
                this._mapObject.drawShape(this._shapeCanvas, x, y, 'CIRCLE', 3, 'red');
            } else {
                point2.x = x;
                point2.y = y;
                this._mapObject.drawShape(this._shapeCanvas, point1, point2, 'LINE', 2, 'red');
            }
        } else {
            //Terminate polygon bly adding last vertice and select
            var polyPoints  = currPolygon.getPolyPoints();
            point1 = currPolygon.getLastPoint();
            currPolygon.appendXY(polyPoints[0].x, polyPoints[0].y)
            currPolygon.finish();
            this._mapObject.drawShape(this._shapeCanvas, point1, polyPoints[0], 'LINE', 2, 'red');
           //Select anything map symbols inside
           
           //1.Get List inside bounding box
           var BB = currPolygon.getBoundingBox();
           var mapElementData = this._mapDataMngr.findMapElementsInArea(BB.LLX, BB.LLY, BB.URX, BB.URY);
           //2. Select those inside polygon 
           if ( mapElementData ){
                var mapElements = mapElementData[0];//Array of NetworkElements
                var mapElementProps = mapElementData[1]; //Array of DeviceProperties
                var mapElemListLength = mapElements.length;
                var point = new CV.mBOSS.DAL.Point();
                var mapRect = null;
                var clientWidth  = this._mapObject.getClientWidth();
                var clientHeight = this._mapObject.getClientHeight();
                for(var i=0; i<mapElemListLength; i++){
                    if ( mapElementProps[i] != null ){
                        point.x = mapElementProps[i].Pnt.x;
                        point.y = mapElementProps[i].Pnt.y;
                    } else {
                        if ( mapRect == null ){
                            mapRect = this.getMapRect();
                        }
                        point.x = parseInt(((mapElements[i].Easting - mapRect.LLX)/(mapRect.URX - mapRect.LLX))*clientWidth);
                        point.y = parseInt(((mapRect.URY - mapElements[i].Northing)/(mapRect.URY - mapRect.LLY))*clientHeight-1);
                    }
                    if ( currPolygon.insidePolygon(point) == false ){
                        mapElements[i] = null;
                        mapElementProps[i] = null;
                    }
                }
           }
           this.addToSelectionList( mapElementData, bMultiSelect);
           this.setMapMode( this._suspendedMapMode );
           //Since this was aqn internal request, we broadcast it
           Global.EventController().fireThisEvent("evtMapModeChanged", this, this._suspendedMapMode); 
           this._suspendedMapMode = null;
        }
    },
    
   
    measurementRulerHandler: function(x, y, mouseMode)
    {
        if ( this._drawPolIgnorePoint == true ){
            if ( mouseMode == this.EnumMouseMode().MOUSE_MODE_CLICK || mouseMode == this.EnumMouseMode().MOUSE_MODE_DBL_CLICK){
                this._drawPolIgnorePoint = false; //First click received
            }
            return;
        }
      
       var currPolygon = this._mapDataMngr.getSelectPolygon();
        if ( mouseMode == this.EnumMouseMode().MOUSE_MODE_CLICK )
        {   //Node in polyline
           if ( currPolygon.getNumVertices() == 0){
                currPolygon.appendXY(x, y, 0);
           } else {
                var point1 = currPolygon.getLastPoint();
                var point2 = new CV.mBOSS.DAL.Point();
                point2.x = x;
                point2.y = y;
                var dist = this.getDistanceBetweenDevPoints(point1, point2);
                currPolygon.appendXY(x, y, dist);
           }
           //this.drawPolyline( currPolygon );
           this.drawRulerLastLine( currPolygon );
       
         }  else if (mouseMode == this.EnumMouseMode().MOUSE_MODE_DBL_CLICK) {
         
           this._mapObject.clearCanvas(this._shapeCanvas);
           this._mapObject.clearCanvas(this._selectCanvas);
           this.setMapMode( this._suspendedMapMode );
           //Since this was aqn internal request, we broadcast it
           Global.EventController().fireThisEvent("evtMapModeChanged", this, this._suspendedMapMode); 
           this._suspendedMapMode = null;
           
        } else if (mouseMode == this.EnumMouseMode().MOUSE_MODE_MOVE) {

            var point1 = currPolygon.getLastPoint();
            var point2 = new CV.mBOSS.DAL.Point();
            if ( point1 != null && point2 != null ){
                point2.x = x;
                point2.y = y;
                var dist = this.getDistanceBetweenDevPoints(point1, point2);
                this._mapObject.clearCanvas(this._selectCanvas);
                this._mapObject.drawShape(this._selectCanvas, point2.x, point2.y, 'CIRCLE', 3, 'red');
                this._mapObject.drawShape(this._selectCanvas, point1, point2, 'LINE', 2, 'black');
                
                dist /= 1000.0;
                var totDist = currPolygon.getTotalDistance()/1000.0 + dist;
                var tooltipDist = "Distance:&nbsp"+dist.toFixed(2) + "(Km)";
                var tooltipTotal = "Total:&nbsp"+totDist.toFixed(2) + "(Km)";
                var tooltip = tooltipDist + "<br/>" + tooltipTotal;
                this._mapObject.setTooltipSize(140, null);
                this._mapObject.setTooltip(tooltip, x+10, y);
            }
            //this.drawPolyline( currPolygon );
        } else if (mouseMode == this.EnumMouseMode().MOUSE_MODE_STOPPED) {  
            var point1 = currPolygon.getLastPoint();
            var point2 = new CV.mBOSS.DAL.Point();
            if ( point1 != null && point2 != null ){
                point2.x = x;
                point2.y = y;
                var dist = this.getDistanceBetweenDevPoints(point1, point2)/1000.0;
                var totDist = currPolygon.getTotalDistance()/1000.0 + dist;
                
                var tooltipDist = "Distance:&nbsp"+dist.toFixed(2) + "(Km)";
                var tooltipTotal = "Total:&nbsp"+totDist.toFixed(2) + "(Km)";
                var tooltip = tooltipDist + "<br/>" + tooltipTotal;
                this._mapObject.setTooltipSize(140, null);
                this._mapObject.setTooltip(tooltip, x+10, y);
            }
           
        }
    }, 
  
    ///
    /// This function handles mouse move events in selection mode
    ///
    mouseMoveSelectHandler: function(x, y, bStopped)
    {
        if ( bStopped == false ){
            var mapElemTT = this._mapDataMngr.findMapElementTooltip(x, y , false);//NO AJX
            this._mapObject.setTooltip(mapElemTT, x, y);
            
            var mapElementData = this._mapDataMngr.findMapElement(x, y, this._EnumObjectHitMode.OBJECT_HIT_MOUSEOVER);
            if ( mapElementData != null && mapElementData[0].length > 0){
                var ElementList = mapElementData[0];
                if ( this._mouseOverElement == null || this._mouseOverElement.Id != ElementList[0].Id){
                    Global.EventController().fireThisEvent("evtMapMouseOver", this, ElementList[0]);
                }
                this._mouseOverElement = ElementList[0];
            } else if (this._mouseOverElement != null){
                Global.EventController().fireThisEvent("evtMapMouseOver", this, null);
                this._mouseOverElement = null;
            }
        } else {
            var groupList = null;
            if ( this._ajaxTooltipEnabled == true ){
                var groupList = this._mapDataMngr.findMapElementTooltip(x, y , true);//Use AJAX
            }
            if ( groupList != null){
                
                var dataRequest = this._mapLayerMngr.getLayersRequest();
                //WE DONT Send the GroupList itself
                dataRequest.ActiveLayerGroupList = groupList;
                var bckGroupList = dataRequest.LayerGroups;
                dataRequest.LayerGroups = null;
                this._tooltipRequestCoord = x+","+y;
                
              if ( this.devPointToWorldPoint(x, y, this._worldPoint) == true ){
                    CV.mBOSS.DAL.MapLayerWebService.GetTooltip(
                            dataRequest,            //params
                            this._worldPoint[0], this._worldPoint[1],
                            Global.getConfigId(),
                            this._delTooltipRetured,         //Complete event
                            this._delWebServiceError,   //Timeout event
                            this._tooltipRequestCoord
                    );
                }
                //Restore GroupList
                dataRequest.LayerGroups = bckGroupList;
            } else if (this._coordTracking == true){
                if ( this.devPointToWorldPoint(x, y, this._worldPoint) == true ){
                    var msg="N="+this._worldPoint[1].toFixed(2)+" E="+this._worldPoint[0].toFixed(2);
                    //window.status = msg;
                    this._mapObject.setTooltip(msg, x, y);
                }
            }
        }
    },
    
    ///
    /// Apply new data from server
    /// Special check/validation of selection list
    ///
    setNewLayerData: function(dataLayer)
    {
        this._mapDataMngr.setData( dataLayer.LayerGroups );
        var selList = Global.DataController().getData("evtSelectionListChanged");
        if ( selList){
            this.validateAndPlotSelectionList( selList );
        }
        if ( dataLayer.HasAreaLayerData== true ){
            var areaMap = this._mapDataMngr.getAreaLayerMap();//Properties[i].AreaXY_dev;
            this._mapObject.setAreaLayerMap( areaMap );
        }
    },
    
    ///
    /// Avaluate if the current selection list is valid (elements still loaded)
    /// Plot selection list and broadcast new list if some elements valid
    ///
    validateAndPlotSelectionList: function( currSelList )
    {
        //For now we plot it as is, no automatic update of selection list from mapApi
        //
        var propList = this._mapDataMngr.getDevicePropertyList(currSelList);
        this.drawOutlineSymbols(newSelList, newPropList );
        return;
        
        var bInvalid = false;
        for(var i=0; i<propList.length; i++){
            if ( propList[i] == null ){
                bInvalid = true;
                break;
            }
        }
        if( bInvalid == false){
            this.drawOutlineSymbols(currSelList, propList );
        } else {
            var newSelList = new Array();
            var newPropList = new Array();
            for(var i=0; i<propList.length; i++){
                if ( propList[i] != null ){
                    newSelList[newSelList.length] = currSelList[i];
                    newPropList[newPropList.length] = propList[i];
                }
            }
            //Clear the old one
            currSelList.length = 0;
            this.drawOutlineSymbols(newSelList, newPropList );
            //Update selection list
            Global.EventController().fireThisEvent("evtSelectionListChanged", this, newSelList);
        }
    },
    
    ///
    /// Traverse list and add to selectionList
    ///
    addToSelectionList: function( mapElementData,  bMultiSelect, selectionRect)
    {
        if ( mapElementData )
        {
            var aGlobalStatus = Global.DataController().getData("evtSelectionListChanged");
            if ( aGlobalStatus != null ){
                //Only delete current selection if not in multiselect modus
                var bTruncateList = bMultiSelect ? (bMultiSelect==false) : true;
                if ( bTruncateList == true){
                    aGlobalStatus.length = 0;
                    aPropertyStatus.length = 0;
                } else {
                    //A global list existed, and we need to find the device properties before plotting
                    var aPropList = this._mapDataMngr.getDevicePropertyList( aGlobalStatus )
                    if ( aPropList != null ){
                        //Copy into local array
                        for(var pl=0; pl<aPropList.length; pl++){
                            aPropertyStatus[pl] = aPropList[pl];
                        }
                    }
                }
            } else {
                aGlobalStatus = new Array();
                aPropertyStatus = new Array();
            }
            
            //Add network Elements to the global store
            //debugger
            var globLen = 0, FoundCount=0;
            var bFound;
            var mapElements = mapElementData[0];//Array of NetworkElements
            var mapElementProps = mapElementData[1]; //Array of DeviceProperties
            var mapElemListLength = mapElements.length;
            var checkGlobal =  aGlobalStatus.length  > 0 ? true : false;
            
            for(var i=0; i<mapElemListLength; i++){
                if ( mapElements[i] != null ){
                    //then  check if the "Sector" already exists. Remove diplicate ID's
                    globLen = aGlobalStatus.length;
                    bFound = false;
                    if ( checkGlobal == true ){
                        var mapElemId = mapElements[i].Id;
                        var mapElemType = mapElements[i].ElementType;
                        for(var j=0; j<globLen; j++)
                        {
                            if ( aGlobalStatus[j].Id == mapElemId && aGlobalStatus[j].ElementType == mapElemType){
                                bFound = true;
                                FoundCount++;
                                break;
                            }
                        }
                    }
                    //Add it if not already in the list
                    if ( bFound == false )
                    {
                        var newIdx = aGlobalStatus.length;
                        aGlobalStatus[newIdx]   = mapElements[i];
                        aPropertyStatus[newIdx] = mapElementProps[i];
                    }
                }
            } 
            //Broadcast event
            Global.EventController().fireThisEvent("evtSelectionListChanged", this, aGlobalStatus);
            //Call the actual draw function
            this.drawOutlineSymbols(aGlobalStatus, aPropertyStatus, selectionRect);
        } else {
            //No data found truncate selection list of no multiselect
             var bTruncateList = bMultiSelect ? (bMultiSelect==false) : true;
             if ( bTruncateList == true){
                this._mapObject.clearCanvas( this._selectCanvas );
                 var aGlobalStatus = Global.DataController().getData("evtSelectionListChanged");
                 if ( aGlobalStatus != null) { aGlobalStatus.length  = 0; }
                 Global.EventController().fireThisEvent("evtSelectionListChanged", this, aGlobalStatus); 
             }
         }      
    },
    
    ///
    /// Draw outline symbols for the network list provided (neList == []NetworkElement)
    ///
    drawOutlineSymbols: function( neList, propList, selectionRect )
    { 
       //First clear previous symbols
        this._mapObject.clearCanvas(this._selectCanvas);
        if ( !neList ){
            return;
        }
        //If number of elements to draw exceeds the max, we draw s the selection rectangle instead
        if ( this._maxSymSelect != -1 && neList.length > this._maxSymSelect){
            if ( selectionRect ){
                var rectSize = new Array(2);
                rectSize[0] = selectionRect.URX -selectionRect.LLX;
                rectSize[1] = selectionRect.LLY -selectionRect.URY;
                var xCenter = (selectionRect.URX + selectionRect.LLX)/2;
                var yCenter = (selectionRect.URY +selectionRect.LLY)/2;
                this._mapObject.drawShape(this._selectCanvas, xCenter, yCenter, 
                                        'RECTANGLE', rectSize, 'black', 'white', 'black');
            }
            return;
        }
        
        
        //First convert from World coordinates to Device coordinates
        var mapRect = this.getMapRect();
        
        //then draw all pending shapes
        var clientWidth  = this._mapObject.getClientWidth();
        var clientHeight = this._mapObject.getClientHeight();
        var x_dev, y_dev;
        var prevX=-999,prevY=-999;
        var prevCount=0;
        var bSuspendPaint = true;
        var numSymbols = neList.length;
        var shadowColor=null;
        var fillColor=null;
        var pos1=null;
        var pos2=null;
        for(var i=0; i<numSymbols; i++){
            //Wait util the last shape to paint
            bSuspendPaint = (i < numSymbols-1);
            //Check if devoce properties already exists, else we calculate devoce coordinates
            if ( propList && propList[i] != null ){
                var propItem = propList[i];
                if ( propItem.SelProp.Shape != 'NONE'){
                var bLine = (propItem.SelProp.Shape == 'LINE');
                    if ( bLine == true || bSuspendPaint==false || (prevX != propItem.Pnt.x && prevX != propItem.Pnt.y)){
                        pos1 = (bLine == true) ? propItem.Pnt : propItem.Pnt.x;
                        pos2 = (bLine == true) ? propItem.Pnt2 : propItem.Pnt.y;
                        if ( propItem.SelProp.ShadowColor != null && propItem.SelProp.ShadowColor.length > 0){
                            this._mapObject.drawShape(this._selectCanvas, pos1, pos2, propItem.SelProp.Shape, 
                                                  propItem.SelProp.Size+2, propItem.SelProp.ShadowColor, shadowColor,shadowColor,fillColor,true);
                        }
                        
                        this._mapObject.drawShape(this._selectCanvas, pos1, pos2, propItem.SelProp.Shape, 
                                              propItem.SelProp.Size, propItem.SelProp.Color, shadowColor, shadowColor,fillColor,bSuspendPaint);
                        prevX = propItem.Pnt.x;
                        prevY = propItem.Pnt.y;
                    } 
                }
                
            } else {
                // Calculate device coordinates
                x_dev = parseInt(((neList[i].Easting - mapRect.LLX)/(mapRect.URX - mapRect.LLX))*clientWidth);
                y_dev = parseInt(((mapRect.URY - neList[i].Northing)/(mapRect.URY - mapRect.LLY))*clientHeight-1);
                //Then draw shape outline
                this._mapObject.drawShape(this._selectCanvas, x_dev, y_dev, 'CIRCLE', 10, 'white', shadowColor, shadowColor,fillColor,bSuspendPaint);
            }
        }
//        if ( prevCount > 0){
//            alert("Compresssion = "+prevCount+"  p="+(prevCount/numSymbols)*100+"%");
//        }
    },
    

    drawPolyline: function( currPolygon )
    {
        //Set start marker
        this._mapObject.clearCanvas(this._shapeCanvas);
        var points = currPolygon.getPolyPoints();
        for(var i=0; i<points.length; i++){
            var point  = points[i];
            if ( i == 0 ){
                this._mapObject.drawShape(this._shapeCanvas, point.x, point.y, 'CIRCLE', 3, 'black');
            } else {
                var point1 = points[i-1];
                var point2 = points[i];
                var endColor = (i== points.length-1)? "red" : "black";
                this._mapObject.drawShape(this._shapeCanvas, point2.x, point2.y, 'CIRCLE', 3, endColor);
                this._mapObject.drawShape(this._shapeCanvas, point1, point2, 'LINE', 2, 'black');
            }
        }
       
    },
    
    //Draw the last line, including marker
    drawRulerLastLine: function( currPolygon )
    {
        var points = currPolygon.getPolyPoints();
        if ( points.length >= 2){
            var point1 = points[points.length- 2];
            var point2 = points[points.length - 1];
            this._mapObject.drawShape(this._shapeCanvas, point2.x, point2.y, 'CIRCLE', 3, 'black');
            this._mapObject.drawShape(this._shapeCanvas, point1, point2, 'LINE', 2, 'black');
        } else if (points.length == 1){
            var point = points[0];
            this._mapObject.drawShape(this._shapeCanvas, point.x, point.y, 'CIRCLE', 3, 'black');
        }
    },
    // ******************************************************************
    // Internal utility functions
    // *****************************************************************
    addXmlNode: function(key, value)
    {
        var xml_tag = "<"+key+">"+value +'</'+key+'>';
        return xml_tag;
    },
    
    ///
    /// Calculate the distance between two device points in meter
    ///
    getDistanceBetweenDevPoints: function(i_point1, i_point2)
    {
        if ( i_point1 != null && i_point2 != null ){
            var x1,y1,x2,y2;
            this.devPointToWorldPoint(i_point1.x, i_point1.y, this._worldPoint);
            x1=this._worldPoint[0];
            y1=this._worldPoint[1];
            this.devPointToWorldPoint(i_point2.x, i_point2.y, this._worldPoint);
            x2=this._worldPoint[0];
            y2=this._worldPoint[1];
            var dX = x1 - x2;
            var dY = y1 - y2;
            return ( Math.sqrt(dX*dX + dY*dY) );
        }
        return 0;
    },
    ///
    /// Map device coordinates X,Y to world coordinates 
    /// Input: i_devX device coordinate X 0=LowerLeft, i_devY dev coord Y, 0=UpperLeft
    /// Return Values: o_worldPoint[0]=Easting, o_worldPoint[1]Northing
    ///
    devPointToWorldPoint: function( i_devX, i_devY, o_worldPoint)
    {
        if ( i_devX && i_devY && o_worldPoint)
        {
            var mapRect = this.getMapRect();
            var clientWidth  = this._mapObject.getClientWidth();
            var clientHeight = this._mapObject.getClientHeight();
            
            //devPointToWorldPoint( (LLX+URX)/2, (LLX+URX)/2, o_Easting, o_Northing);
            o_worldPoint[0]  = mapRect.LLX + (i_devX/clientWidth)*(mapRect.URX - mapRect.LLX);
            o_worldPoint[1] = mapRect.URY - (i_devY/clientHeight)*(mapRect.URY - mapRect.LLY);
            return true;
        }
        return false;
    },
    
    // Convert a world coordinate to devoce coordinates
    worldToDevPoint: function(easting, northing)
    {
        var mapRect = this.getMapRect();
        var clientWidth  = this._mapObject.getClientWidth();
        var clientHeight = this._mapObject.getClientHeight();
        var pnt = new CV.mBOSS.DAL.Point();
        pnt.x = parseInt(((easting - mapRect.LLX)/(mapRect.URX - mapRect.LLX))*clientWidth);
        pnt.y = parseInt(((mapRect.URY - northing)/(mapRect.URY - mapRect.LLY))*clientHeight);
        return pnt;
    }
}
MapApiClient.MapApiSGE.registerClass('MapApiClient.MapApiSGE', MapApiClient.MapApi);

