﻿// JScript File

MapApiClient.MapApiMG = function (rootObj) 
{
    MapApiClient.MapApiMG.initializeBase(this, [rootObj]);

    //MapApiClient.MapApiMG.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._mapContainer = rootObj;
    this._mapObject = null;
    this._mapExtent = null; //CV.mBOSS.DAL.Rect class, extent of curtrent mapview
    this._currMapMode;   // Enum keeping track of current map mode
    this._currZoomFactor=0.5;  //To be sett by callser for zoom iSFn/out
    this._requestedMapScale=0;
    this._mapLayerMngr = null;
    this._mapDataMngr = null;
    this._sDefaultMapLayers = null; //Defaults map layers to load
    this._sDefaultMapFilters = null;//Default filters to apply
    this._pendingDefaultSettings = false;
    this._shapeDrawn = false;
    this._mapCenterXworld = null;
    this._mapCenterYworld = null;
    this._mapWidthWorld = null;
    
    //Some class scope delegates
    this._delMapConfig = null;
    this._delPregenData = null;
    this._delMapRetured = null;
    this._delLegendReturned = null;
    this._delWeServiceError = null;
    
    this._loadingFlag = false;
    this._drawShapeRequest = null; //Pending SHAPE draw reguest
    this._SelectionEnabled = false; //Activate MapSelection
    this._firstTimeResize  = false; //Resize ActiveX when first resize evebt received
    this._appCoordMetrical = true;
    this._dbCoordMetrical = false;
    this._alertedFlag = false;
 }
 
 MapApiClient.MapApiMG.prototype={
    
    
    initialize: function( i_config ) {
        // register the global mapApi
        // Initialize the mapObject and hook up callbacks from the mapObject to the MapApi
         this._mapContainer.initialize( Function.createDelegate(this, this.OnMapSelectionChanged),
                                        Function.createDelegate(this, this.OnMapDigitizedPoint),
                                        Function.createDelegate(this, this.OnMapDigitizedArea), 
                                        Function.createDelegate(this, this.OnMapDigitizedPolygon), 
                                        Function.createDelegate(this, this.OnMapDoubleClickObject), 
                                        Function.createDelegate(this, this.OnMapViewChanging),      
                                        Function.createDelegate(this, this.OnMapViewChanged), 
                                        Function.createDelegate(this, this.OnMapBusyStateChanged),
                                        null /*Function.createDelegate(this, this.OnMapAddMapLayer)*/  ); 
         this._mapObject = this._mapContainer.getMapObject();

         //Connecting to application events
         Global.EventController().subscribe("evtSystemChanged", Function.createDelegate(this, this.onSystemChanged));               
         //Global.EventController().subscribe("evtModuleChanged", Function.createDelegate(this, this.onModuleChanged));
         Global.EventController().subscribe("evtStatusChanged", Function.createDelegate(this, this.onStatusChanged));
         Global.EventController().subscribe("evtServiceChanged", Function.createDelegate(this, this.onServiceChanged));
         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("evtMccChanged", Function.createDelegate(this, this.onMccChanged));
         Global.EventController().subscribe("evtMncChanged", Function.createDelegate(this, this.onMncChanged));
          
         Global.EventController().subscribe("evtSelectionListChanged", Function.createDelegate(this, this.onSelectionListChanged));
         Global.EventController().subscribe("evtResizeEnd", Function.createDelegate(this, this.onResizeEnd));
        //Create mapLayer manager
        this._mapLayerMngr = new MapApiClient.MapLayerMngr();
        this._mapDataMngr = new MapApiClient.MapDataMngr();
        this._mapExtent  = new CV.mBOSS.DAL.Rectangle();
        
        //Create mapData manager (map overlays)
        //this._mapDataMngr  = new MapApiClient.MapDataMngr();
                                
        //Set current map mode, and also set this in map object
        this._currMapMode = this.EnumMapMode().MAP_MODE_SELECT;
        //SHO this._mapObject.setAction(this._mapObject.MAP_ACTION_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);
        }
        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;
                }
            }    
        }
        
        this._mapCenterXworld = i_config.mapCenterXworld;
        this._mapCenterYworld = i_config.mapCenterYworld;
        this._mapWidthWorld = i_config.mapWidthWorld;
        
        //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._delWebServiceError = Function.createDelegate(this, this.OnMapServiceError);
        
        //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
    // *****************************************************************
    getClientWidth: function()
    {
        if ( this._mapContainer.frameElement){
            return this._mapContainer.frameElement.clientWidth;
        }
        return 0;
    },
    getClientHeight: function()
    {
        if ( this._mapContainer.frameElement){
            return this._mapContainer.frameElement.clientHeight;
        }
        return 0;
    }, 
     
    setLayerGroupVisibilityByFilterId: function(i_filterId, i_layerVisibility, i_reloadMap)
    {
        var layerFilterMap = this._mapLayerMngr.getLayerGroupsForFilterType(i_filterId);
        if ( layerFilterMap )
        {
            var layerGroup;
            for( var i=0; i<layerFilterMap.LayerGroupList.length; i++){
                var layerGroupId = layerFilterMap.LayerGroupList[i];
                var reload = (i == layerFilterMap.LayerGroupList.length-1) ? i_reloadMap : false;
                this.setLayerGroupVisibility(layerGroupId, i_layerVisibility, reload);
            }
        }
    },
    
    //MGE
    setLayerGroupVisibility: function( i_layerGroup, i_layerVisibility, i_reloadMap)
    {
        var bVisibilityChanged = false;
        //First we update the client datastructure which keeps the current state
        //Used to "roll back" when we change module
        this._mapLayerMngr.setLayerGroupVisibility(i_layerGroup, i_layerVisibility);
        
        
        
        //Then we update the mapguide layers
        var layerGroup = this._mapLayerMngr.getLayerGroup( i_layerGroup );
        if ( layerGroup != null && this._mapObject != null)
        {
            // If map busy we can't set any properties so we stop ongoing map draw
            if( this._mapObject.isBusy() == true )
            {
                this._mapObject.stop();
            }
            for (idx=0; idx < layerGroup.Layers.length; idx++)
            {
               var layer = layerGroup.Layers[idx];
               var mgLayer = this._mapObject.getMapLayer( layer.LayerId );
               if ( mgLayer != null )
               {
                    var prevVisibility = mgLayer.getVisibility();
                    var newVisibility  = i_layerVisibility;
                    if ( prevVisibility != newVisibility)
                    {
                        mgLayer.setVisibility( newVisibility);
                        bVisibilityChanged = true;
                    }
               }
            }
            // Apply filter
            this.mgSetLayerGroupFilter( layerGroup );
            
            if ( bVisibilityChanged == true )
            {
                //Here we can send an visibilityChanged event
            }
            if ( i_reloadMap == true )
            {
                this.loadMap();
            }
            return true;
        }
        // layerGroup or map not found
        return false;
    },
    
    //MGE
    clearLayerGroupFilter: function(i_layerGroup,  i_filterMapType, i_reloadMap)
    {
        this.setLayerGroupFilter(i_layerGroup, i_filterMapType, null, null, i_reloadMap)
    },
    //MGE
    setLayerGroupFilter: function(i_layerGroupId, i_filterType, i_filerLogic, i_filterData, i_reloadMap)
    {
       //debugger
       if ( i_layerGroupId != null )
       {
            this.setLayerFilterOrPregendata(i_layerGroupId, i_filterType, i_filerLogic, i_filterData, i_reloadMap);
       } 
       else if (i_filterType != null) {
            //layerGroup was null, we look up if ant FilterLayerGroup exists for filterType
            //And apply filter to all LayerGroup in list
            var layerFilterMap = this._mapLayerMngr.getLayerGroupsForFilterType(i_filterType);
            if ( layerFilterMap )
            {
                var filterType = layerFilterMap.FilterType != null ? layerFilterMap.FilterType : i_filterType;
                var layerGroup;
                for( var i=0; i<layerFilterMap.LayerGroupList.length; i++){
                    var layerGroupId = layerFilterMap.LayerGroupList[i];
                    var reload = (i == layerFilterMap.LayerGroupList.length-1) ? i_reloadMap : false;
                    this.setLayerFilterOrPregendata(layerGroupId, filterType, i_filerLogic, i_filterData, reload);
                }
            }
        }
    },
    //MGE
    // Return value: true if pregen layer, false of not
    setLayerFilterOrPregendata: function(i_layerGroupId, i_filterType, i_filerLogic, i_filterData, i_reloadMap)
    {
        var layerIdx=this._mapLayerMngr.getLayerGroupDataPregenStatus( i_layerGroupId );
        if ( layerIdx == null ){
            var layerGroup = this._mapLayerMngr.setLayerGroupFilter(i_layerGroupId, i_filterType, i_filerLogic, i_filterData);
            this.mgSetLayerGroupFilter( layerGroup );
            if (i_reloadMap == true ){
                this.loadMap();
            }
            return false;
        } 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 = i_layerGroupId;
            //Create the Ne(Network Element) filter for this layer
            dataRequest.dataFilter = this._mapLayerMngr.createNeQueryFilter(i_filterType, i_filterData);
            
            //Send an AJAX call to generate data
            requestResponse = CV.mBOSS.DAL.MapLayerWebService.PregenFileDataLayer( 
                            dataRequest,
                            Global.getConfigId(),
                            this._delPregenData, 
                            this._delWebServiceError, 
                            true);
           return true;
        }
    },
    // Check ./js/MapApi.js for parameter spesifications
    getLayerGroupNeFilters: function(filterIds)
    {
        return this._mapLayerMngr.getLayerGroupNeFilters(filterIds);
        
    },
    
    // Check ./js/MapApi.js for parameter spesifications
    setLayerGroupKpiFilter: function(i_layerGroupId, i_filterMapKey, i_kpiFilter, i_bFilterSelection, i_reloadMap)
    {
        //STIAN
        if ( i_layerGroupId != null )
       {
            var layerGroup = this._mapLayerMngr.setLayerGroupKpiFilter(i_layerGroupId, i_kpiFilter);
            this.mgSetLayerGroupFilter( layerGroup );
            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 )
            {
                //Get a possible ne filter if requested
                var neFilterArr = null;
                if ( i_bFilterSelection && i_bFilterSelection == true ){
                    neFilterArr = this.getNeListFromMapSelection(layerFilterMap.FilterType);
                    if ( neFilterArr == null ){
                        //i_bFilterSelection == true, then we require som e selected cells to do anything
                        return null;
                    }
                }
                var bAllPregen = true;
                //Assigne a type or name to the filter (can be several filters)
                var layerGroup;
                var layerGroupList = layerFilterMap.LayerGroupList;
                for( var i=0; i<layerGroupList.length; i++){
                    layerGroup = this._mapLayerMngr.setLayerGroupKpiFilter(layerGroupList[i], i_kpiFilter);
                    if ( i_bFilterSelection && i_bFilterSelection == true && neFilterArr != null){
                        //Stian
                       var pregen = this.setLayerFilterOrPregendata(layerGroupList[i], layerFilterMap.FilterType, 'INCLUDE', neFilterArr.join(), false);
                       if ( pregen == false ){
                            bAllPregen = false;
                       }
                        //this._mapLayerMngr.setLayerGroupFilter(layerGroupList[i], layerFilterMap.FilterType, 'INCLUDE', neFilterArr.join());
                    }
                    this.mgSetLayerGroupFilter( layerGroup );
                }
                if (i_reloadMap == true && bAllPregen == false){
                    this.loadMap();
                }
            }
        }   
        if ( neFilterArr ){
            return neFilterArr.length;
        } 
        return null;
    },
    
    // 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);
            this.mgSetLayerGroupFilter( layerGroup );
            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 )
            {
                //Assigne a type or name to the filter (can be several filters)
                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);
                    this.mgSetLayerGroupFilter( layerGroup );
                }
                if (i_reloadMap == true ){
                    this.loadMap();
                }
            }
        }
    },
    clearLayerGroupColumnFilter: function(i_layerGroup, i_filterMapKey, i_reloadMap)
    {
        this.setLayerGroupColumnFilter(i_layerGroup, i_filterMapKey, null, i_reloadMap )
    },
    
    setPlotOverWaterVisibility: function( bVisibility, i_reloadMap )
    {
        //Set visibility
        this._mapLayerMngr.setPlotOverWaterVisibility(bVisibility);
        var water_mark = this._mapLayerMngr.getPlotOverWaterMarks();
        
        this.mgSetWaterMark(water_mark);
        //Redraw map
        if (i_reloadMap != false)
            this.loadMap();
    },
    
    getPlotOverWaterVisibility: function( )
    {
        //Get visibility
        return this._mapLayerMngr.getPlotOverWaterVisibility();
    },
    
    /// Return the current MapScale e.g 1:100K returning 100000
    /// MGE
    getMapScale: function()
    {
        if ( this._mapObject != null )
        {
            return this._mapObject.getScale();
        }
        return 0;
    },
    
    /// Returning the map rectangle in World(application) coordinates
    /// MGE
    getMapRect: function() 
    { 
        //this._mapExtent updated in mgGetMaprect called when busy state changed
        return this._mapExtent;
    },
    ///
    /// Check if any of the layers in the group is Active (Visible)
    ///
    /// MGE
    getLayerGroupVisibility: function( i_layerGroup )
    {
        var bVisibility = false;
        var layerGroup = this._mapLayerMngr.getLayerGroup(i_layerGroup);
        if ( layerGroup != null )
        {
            var checkScale = this._mapObject.getScale();
            for (idx=0; idx < layerGroup.Layers.length; idx++)
            {
               var mgLayer = this._mapObject.getMapLayer( layerGroup.Layers[idx].LayerId );
               if ( mgLayer != null )
               {
                  if ( mgLayer.getVisibility() == true )
                  {
                    // Found at least one layer, then return true for the group
                      return true;
                  }
               }
            }
            
        }
        return bVisibility;
    },
    
    ///
    /// Check if any of the layers in the group is potentially visible
    ///
    /// MGE
    getLayerGroupPotVisibility: function( i_layerGroup )
    {
        //return this._mapLayerMngr.getLayerGroupPotVisibility( i_layerGroup );
        var potVisibility = false;
        var layerGroup = this._mapLayerMngr.getLayerGroup(i_layerGroup);
        if ( layerGroup != null )
        {
            var checkScale = this._mapObject.getScale();
            for (idx=0; idx < layerGroup.Layers.length && potVisibility == false; idx++)
            {
               var mgLayer = this._mapObject.getMapLayer( layerGroup.Layers[idx].LayerId );
               if ( mgLayer != null )
               {
                  var mgLayerStyles = mgLayer.getMapLayerStyles();
                  for(lStyleIdx=0; lStyleIdx<mgLayerStyles.count; lStyleIdx++)
                  {
                     var mgLayerStyle= mgLayerStyles.item( lStyleIdx );
                     
                     if ( checkScale <= mgLayerStyle.getMaxDisplayRange() &&
                          checkScale >= mgLayerStyle.getMinDisplayRange() )
                     {
                          potVisibility = true;
                          break;
                     }
                  }
               }
            }
            
        }
        return potVisibility;
    },
    
    ///
    /// 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;
    },
    
    /// MGE
    loadMap: function()
    {
        if ( this._mapClientLoaded == false)
        {
            this._loadPending = true;
            return;    
        }
        if ( this._bSuspendMapLoad == false )
        {
            Global.setLoading(true);
            
            this.mgSetLayerRebuild();
            this._mapObject.refresh();

            Global.setLoading(false);
        }
        return;
    },
    /// MGE
    mapRebuild: function()
    {
        this.mgSetLayerRebuild();
        return;
    },
    /// ****************************************************************
    /// API functions
    //  ****************************************************************
    
    // Zoom to initial zoomlevel an map centre
    // MGE
    zoomStart: function()
    {
        if ( this._appCoordMetrical == true ) {
            var mgPoint =  this._mapObject.mcsToLonLat(Number(this._mapCenterXworld), Number(this._mapCenterYworld));
            this._mapObject.zoomWidth(mgPoint.Y, mgPoint.X, this._mapWidthWorld, "m");
        } else {
            this._mapObject.zoomWidth(Number(this._mapCenterYworld), Number(this._mapCenterXworld), this._mapWidthWorld, "m");
        }
    },
    
    // Zoom to the specified point in world coordinates
    // MGE
    zoomToWorldPoint: function( i_easting, i_northing, i_scale)
    {   
        //debugger
        if( this._mapObject.isBusy() == true )
        {
           this._mapObject.stop();
        }
        var newScale = i_scale;
        if ( i_scale )
        {
            newScale = i_scale
        } else {
            newScale = this._mapObject.getScale();
        }
        if ( this._appCoordMetrical == true )
        {
            var mgPoint =  this._mapObject.mcsToLonLat(i_easting, i_northing);
        
            this._mapObject.zoomScale(mgPoint.Y, mgPoint.X, i_scale);
        } else {
            //Coordinates already in lat/lon, no convertion needed
            this._mapObject.zoomScale(i_northing, i_easting, i_scale);
        }     
        //this.loadMap( );
        
    },
    
    // MGE
    zoomToWorldRect:  function(LLX, LLY, URX, URY, i_minscale, i_extendPercent)
    {
        // DO a zero size test first
        if( (LLY-LLX) == 0 || (URY-LLY)==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(LLX, LLY, minScale);
        }   
    
        var mscLLX = LLX;
        var mscLLY = LLY;
        var mscURX = URX;
        var mscURY = URY;
        
        if ( this._appCoordMetrical == false )
        {
            // do a metrical conversion, if we received lat-lon as input
            var mscPointLL =  this._mapObject.lonLatToMcs(LLX, LLY);
            mscLLX = mscPointLL.X;
            mscLLY = mscPointLL.Y;
            var mscPointUR =  this._mapObject.lonLatToMcs(URX, URY);
            mscURX = mscPointUR.X;
            mscURY = mscPointUR.Y;            
        }

        var rect = new CV.mBOSS.DAL.Rectangle();
        /*
        if ( i_extendPercent )
        {
            //debugger
            //We extend the area with the percentage given
            var eastExtend = (mscURX - mscLLX)*(i_extendPercent/100)/2;
            var northExtend = (mscURY - mscLLY)*(i_extendPercent/100)/2;
            rect.LLX = mscLLX - eastExtend;
            rect.LLY = mscLLY - northExtend;
            rect.URX = mscURX + eastExtend;
            rect.URY = mscURY + northExtend;
        } else 
        */
        {
            rect.LLX = mscLLX;
            rect.LLY = mscLLY;
            rect.URX = mscURX;
            rect.URY = mscURY;
        }
        
        var centerLat = (rect.LLY+rect.URY)/2.0;
        var centerLon = (rect.LLX+rect.URX)/2.0;

        var mgPoint =  this._mapObject.mcsToLonLat(centerLon, centerLat);
        
        var screenAspect = this._mapObject.getWidth('M')/this._mapObject.getHeight('M');
        var minWidthByBBHeight = (mscURY-mscLLY)*screenAspect;
        var minWidthByBBWidth = (mscURX-mscLLX);
        var width = Math.max(minWidthByBBHeight, minWidthByBBWidth);
        if ( i_extendPercent )
            width = width * (1.0 + (i_extendPercent/100.0)/2.0);
        
        //var width = Math.max((mscURX-mscLLX), (mscURY-mscLLY));
        this._mapObject.zoomWidth(mgPoint.Y, mgPoint.X, width, "m");
     },
     
     // MGE
     setMapScale: function( i_scale ) 
     { 
        this._mapObject.setScale(i_scale);
     },
    
    // MGE
    setCurrMapMode: function()
    {
        this.setMapMode(this._currMapMode);
    },
    setMapMode: function( enumMapMode )
    {
       
        //debugger
        if (  this._mapObject.isBusy() == true ){
            this._mapObject.stop();
        }
        switch ( enumMapMode ){
            case this.EnumMapMode().MAP_MODE_MOVE:
                //this._mapObject.setAction(this._mapObject.MAP_ACTION_MOVE);
                this._mapObject.panMode();
                this._currMapMode = enumMapMode;
            break;
            case this.EnumMapMode().MAP_MODE_SELECT:
                //this._mapObject.setAction(this._mapObject.MAP_ACTION_SELECT);
                this._mapObject.selectMode();
                this._currMapMode = enumMapMode;
            break;
            case this.EnumMapMode().MAP_MODE_ZOOM_RECT:
                this._currZoomFactor = 0.5;
                //this._mapObject.setAction(this._mapObject.MAP_ACTION_ZOOM);
                this._mapObject.zoomInMode();
                this._currMapMode = enumMapMode;
            break;
            case this.EnumMapMode().MAP_MODE_ZOOM_OUT:
                this._currZoomFactor = 1.5;
                //this._mapObject.setAction(this._mapObject.MAP_ACTION_ZOOM);
                this._mapObject.zoomOutMode();
                this._currMapMode = enumMapMode;
            break;
            case this.EnumMapMode().MAP_MODE_ZOOM_START:
            {
                
                //This is actually not a "Mode", but we use it for convinience as map action
                this.zoomStart();
            }
            break;
        }
    },
    
    getMapMode: function()
    {
        return this._currMapMode;
    },
    getLegendData: function()
    {
        return this._mapLayerMngr.getLegendData( this._mapDataMngr  );
    },
    
    //Return a container bove the map which can contain a floating legend
    getLegendContainer: function()
    { 
        return this._mapContainer.getLegendContainer();
    },
    
    //
    //See arg definitions in MapApi.js
    //
    drawShape: function(Easting, Northing, shapeType, shapeParam, lineColor, shadowColor, innerColor, fillColor, bAppendToCanvas, bZoomIfOutside)
    { 
        //Check if this is a clear call
        if ( Easting == null){
            this.mgDrawShape(null);
            this.loadMap( );
            return;
        }
    
        //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++] = innerColor;
                this._drawShapeRequest[idx++] = fillColor;
                
                // If one position or current scale is large enough 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;
            }
        }
        
        //then draw all pending shapes
        var Easting, Northing;
        var Easting_prev  = -999999;
        var Northing_prev = -999999;
        for(var i=0; i<posList.length; i++)
        {
            // Calculate device coordinates
            //Use temp variables for radability
            Easting  = posList[i][0];
            Northing = posList[i][1];
            //Then draw shape, but incase someone draw on large scales we accumulate equal points
            //Cells on same site
            if ( Easting != Easting_prev && Northing != Northing_prev)
            {
                this.mgDrawShape(Easting, Northing, shapeType, shapeParam, lineColor, shadowColor, innerColor, fillColor);
            }
            Easting_prev = Easting ;
            Northing_prev = Northing;
        }
        //this.loadMap( );
        this._shapeDrawn = true;
    },

    
    
    ///
    /// 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++],  // shape_type;
                               this._drawShapeRequest[idx++],  // shape_param;
                               this._drawShapeRequest[idx++],  // lineColor;
                               this._drawShapeRequest[idx++],  // shadowColor;
                               this._drawShapeRequest[idx++],  // innerColor;
                               this._drawShapeRequest[idx++]);   //fillColor;);
        
        }
    },
    
    ///
    /// Draw outline symbols for the network list provided (neList == []NetworkElement)
    ///
    drawOutlineSymbols: function( neList )
    { 
        return; //Have to implement selection in mapGuide;
    
        //First clear previous symbols
        this._mapObject.clearCanvas();
        if ( !neList ){
            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;
        for(var i=0; i<neList.length; i++){
            // Calculate device coordinates
            //Use temp variables for radability
            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);
            //debugger
            //Then draw shape outline
            this._mapObject.drawShape(x_dev, y_dev, 'CIRCLE', 6, 'white');
        }
    },
    
    ///
    /// MapApi function
    ///
    digitizePoint: function()
    {   
        this._mapObject.digitizePoint();
        return true;
    },
    digitizeRect: function()
    {   
        this._mapObject.digitizeRectangle();
        return true;
    },
    
    digitizePolygon: function()
    { 
        this._mapObject.digitizePolygon();
        return true;
    },
    
    
    ///
    ///MapApi changeModule
    ///
    changeModule: function( contextModuleName )
    {
        if ( this._mapLayerMngr != null)
        {
            //MGMapObject can't be busy, doesn't accept property changes, have to stop ongoing functions!
            if ( this._mapObject.isBusy() == true )
            {
                    this._mapObject.stop();
            }
            var oldModule = this._mapLayerMngr.getModuleName();
            if ( oldModule != contextModuleName)
            {
                //First we need to de-activate all current module layers in MapGuide
                this.mgClearCurrModuleVisibility();
                //Then we activate new module 
                this._mapLayerMngr.setModule( contextModuleName )
                //and update with stored visibility settings in new module
                this.mgSetCurrModuleVisibility();
                
                //Set where caluses etc according to new layers
                this.mgApplyAllLayersWhere();
                
                //Clear selection list
                Global.EventController().fireThisEvent("evtSelectionListChanged", this, null);
                
                //Then we draw the buty
                this.loadMap();
                
            }
        }
    },
    ///
    /// Class Event function delegates
    ///
    
    onSystemChanged: function( sender, newSystem )
    {
        if ( this._mapLayerMngr != null)
        {
            this._mapLayerMngr.setSystype( newSystem )
            this.mgApplyAllLayersWhere( );
            this.loadMap();
        }
    },
    
    onStatusChanged: function( sender, newStatus )
    {
        if ( this._mapLayerMngr != null)
        {
           this._mapLayerMngr.setStatus( newStatus )
           this.mgApplyAllLayersWhere( );
           this.loadMap();
        }
    },
    
    onMccChanged: function( sender, context )
    {
        if ( this._mapLayerMngr != null)
        {
           this._mapLayerMngr.setNetworkFilter('MCC', context)
           this.mgApplyAllLayersWhere( );
           this.loadMap();
        }
    },
    
    onMncChanged: function( sender, context )
    {
        if ( this._mapLayerMngr != null)
        {
           this._mapLayerMngr.setNetworkFilter('MNC', context)
           this.mgApplyAllLayersWhere( );
           this.loadMap();
        }
    },
    
   onServiceChanged: function( sender, newService)
    {
        if ( this._mapLayerMngr != null)
        {
           this._mapLayerMngr.setService( newService )
           this.mgApplyAllLayersWhere( );
           this.loadMap();
        }
    },
    
    onSeverityChanged: function( sender, newSeverity)
    {
        if ( this._mapLayerMngr != null)
        {
           this._mapLayerMngr.setSeverity( newSeverity )
           this.mgApplyAllLayersWhere( );
           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.mgApplyAllLayersWhere( );
           this.loadMap();
        }
    },
    onSelectionListChanged: function( sender, contextSelectionList )
    {
        if ( sender != this ){
            this.drawOutlineSymbols(contextSelectionList);
            //alert("some sendt");
        
        } else {
            //alert("I sendt:"+context);
        }
    },
    onResizeEnd: function( sender )
    {
       //alert("onResizeEnd");
       if ( this._firstTimeResize == false ){
            this._mapContainer.resize();
       }
       this._firstTimeResize = true;
    },
    ///***********************************************
    /// Callbacks fro Ajax web services
    ///***********************************************
    
     ///
     /// 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;
        
        //Initialize some map coordinate info
        this._appCoordMetrical = retObject.AppCoordMetrical;
        this._dbCoordMetrical = retObject.DbCoordMetrical;
        
        // 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' );
        }
        //If map is busy we have to wait with the initialization, or if no defaults
        this._mapObject = this._mapContainer.getMapObject();
        //if ( this._mapObject.isBusy() == false || this._sDefaultMapLayers == null)
        if ( this._mapObject != null)
        {
            if ( this._mapObject.isBusy() == true){
                this._mapObject.stop();
                setTimeout(Function.createDelegate(this, this.OnSetInitialStates), 500)
            } else  {
                this.OnSetInitialStates();
            }
           this._mapObject.setErrorTarget("mgError");
        } else {
            this._pendingDefaultSettings = true;
        }
     },
     
     OnSetInitialStates: function()
     {
            this.mgSetInitialStates();

            // Fire evtMapWindowChanged event
            Global.EventController().fireThisEvent("evtMapWindowChanged", this, null); 
            if ( this._loadPending == true){
                this.loadMap();
            }
     },
     
     /// 
     /// 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");
        }
    },
    
    ///
    /// Ajax response from server. Response to PregenLayerData request
    ///
    OnPregenDataReturned: function( pregenResponse, bRedraw )
     {
        //Turn off loading indicator
        Global.setLoading(false);
        
        if ( pregenResponse )
        {
            //Check return status, maybe we should check DataOK, DataEmpty
            if ( pregenResponse.bDataOK == true )
            {
                //Then we set the new generated file as layer attribute in mapguide
                this.mgSetLayerGroupSdfFile( pregenResponse );
                 //And redraw map I quess
                if ( bRedraw == true ){
                    this.loadMap();
                }
            } else {
                alert(pregenResponse.sErrMsg);
            }
        }
     
     },
    
    OnLegendDataReturned:function (legendData)
    {
        if ( legendData ){
            this._mapDataMngr.setData(legendData);
            Global.EventController().fireThisEvent("evtDynamicLegendChanged", this, true); 
            
        }
    },
    
    // *********************************************************************************
    // 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){
        //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 = CV.mBOSS.DAL.MAP_API_ACTION.MAP_API_ACTION_ZOOM_POINT;
        this.loadMap( action,  point);
    },
    
    /* 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 {
            //No action, we reset map cursor
           this._mapObject.setCurrCursor();
       }
    },
    
    ///
    /// Event from map: View has changed, som ehas zoomed etc
    ///
    OnMapViewChanged: function( )
    {
        //Ensure we reset cursor after a zoom/pan operation
        this.setCurrMapMode(); 
        
        var mapLocation = new CV.mBOSS.DAL.MapLocation();
        mapLocation.MapScale = this.getMapScale();
		mapLocation.MapWidthMeter = 0;
		mapLocation.WorldRect = this.getMapRect();
        this._mapLayerMngr.setMapLocation( mapLocation );

    },
    OnMapViewChanging: function( )
    {
        //Remove temporary redline layers when starting a map change
        if ( this._shapeDrawn == true){
            this.mgDrawShape(null);
        } 
        //About to change map, but we don't know why (layers or only map zoom/pan etc)
        Global.EventController().fireThisEvent("evtLoadingMap", this, true); 
    },
    ///
    /// Event from map: Area selected in device coordinates
    ///
    OnMapSelectionChanged: function()
    {
        //debugger
        if( this._mapObject.isBusy() )
        { 
            this._mapObject.stop();
        }
        
        if ( this._currMapMode == this.EnumMapMode().MAP_MODE_SELECT )
        {
            //Get the map selection from MapGuide
            var selection = this._mapObject.getSelection();
            var layerGroupList = this._mapLayerMngr.getLayerGroupList();
			var mapLayers = this._mapObject.getMapLayersEx();
			
            if ( selection != null && layerGroupList != null){
                //Prepare global data
                var aGlobalStatus = Global.DataController().getData("evtSelectionListChanged");
                if ( aGlobalStatus != null ){
                    aGlobalStatus.length = 0; //Clear list
                } else {
                    aGlobalStatus = new Array();
                }
                
                var objExtent, objInfo, objInfoArr;
                var globLen = 0, globIdx = 0, FoundCount=0;
                var bFound;
                
                //Traverse all LayerGroups and check selection for each layer
                var numGroups = layerGroupList.length;
                for(var grpIdx=0; grpIdx<numGroups; grpIdx++)
                {
                    var layerGroup = layerGroupList[grpIdx];
                    if ( layerGroup.Property.bSelectable == false){
                        continue; //Skip none selectable layers
                    }
                    var numLayers =  layerGroup.Layers.length;
                    
                    for(var layerIdx=0; layerIdx<numLayers; layerIdx++)
                    {
                        
                        var layer = layerGroup.Layers[layerIdx];
                        var mgLayer = this._mapObject.getMapLayer( layer.LayerId );
                        if ( mgLayer )
                        {
                           var selectedInLayer = selection.getMapObjectsEx( mgLayer );
                           for(var selIdx=0; selIdx<selectedInLayer.size(); selIdx++)
                           {
                                var mapItem = selectedInLayer.item(selIdx);
                                var neId = mapItem.getKey(); //Ne_id 
                                
                                //Then we check if this id already in list (remove duplicates)
                                globLen = aGlobalStatus.length;
                                bFound = false;
                                // NOTE (lla) do not remove duplicates ? temporally ?
                                //
//                                for(var j=0; j<globLen; j++)
//                                {
//                                    if ( aGlobalStatus[j].Id == neId ){
//                                        bFound = true;
//                                        FoundCount++;
//                                        break;
//                                    }
//                                }
                                //Add it if not already in the list
                                if ( bFound == false )
                                {
                                    
                                    objInfo = mapItem.getLink();
                                    if (objInfo.charAt(0) == '@')
                                    {
                                        var elementType;
                                        if ( layer.ElementType != null){
                                            elementType = layer.ElementType;
                                        } else if ( layerGroup.LayerType != null){
                                            elementType = layerGroup.LayerType;
                                        } else {
                                            alert("Please add tag layerType for group:"+layerGroup.LayerGroupId);
                                        }
                                        
                                        aGlobalStatus[globIdx]=this.ExtractNeObjectInfo(objInfo, layer.LayerId, neId, mapItem.getName(), elementType);
                                    }
                                    else
                                    {
                                        aGlobalStatus[globIdx] = new CV.mBOSS.DAL.NetworkElement();
                                        
                                        //Fill in the data
                                        aGlobalStatus[globIdx].Id = neId;
                                        aGlobalStatus[globIdx].TT = mapItem.getName();
                                        objInfoArr = objInfo.split(";"); //Infofield "77799;37681;STR168_01;30.12.1899;GSM900;OPR"
                                        //0=NeId,1=Code, 3=Name
                                        aGlobalStatus[globIdx].NeCode = objInfoArr[1];
                                        aGlobalStatus[globIdx].Name = objInfoArr[2];
                                        
                                        
                                        if ( layer.ElementType != null){
                                            aGlobalStatus[globIdx].ElementType = layer.ElementType;
                                        } else if ( layerGroup.LayerType != null){
                                            aGlobalStatus[globIdx].ElementType = layerGroup.LayerType;
                                        } else {
                                            alert("Please add tag layerType for group:"+layerGroup.LayerGroupId);
                                        }
                                        
                                        var objExtent = null;
                                        if ( this._appCoordMetrical == true )
                                        {
                                            objExtent = mapItem.getExtentEx(true);
                                        } else {
                                            objExtent = mapItem.getExtentEx(false);
                                        }
                                        aGlobalStatus[globIdx].Northing = (objExtent.MaxY + objExtent.MinY)/2.0;
                                        aGlobalStatus[globIdx].Easting  = (objExtent.MaxX + objExtent.MinX)/2.0;
                                    }
                                    
                                    globIdx++;
                                }
                           }
                        }
                    }
                }
                Global.EventController().fireThisEvent("evtSelectionListChanged", this, aGlobalStatus);
                
            } else {
                //No data selected
                
            }
        }
    },
    
    ExtractNeObjectInfo: function(i_objInfo, i_layerName, i_neId, i_name, i_elementType)
    {
        var neObj = new CV.mBOSS.DAL.NetworkElement();
        neObj.Id = i_neId;
        neObj.TT = i_name;    
        neObj.ElementType = i_elementType;
        var objInfoArr = i_objInfo.split("|");
        var arrPar;
        for (var i=1; i<objInfoArr.length; i++)
        {
            arrPar = objInfoArr[i].split("=");
            if (arrPar && arrPar.length >= 2 && arrPar[0] && arrPar[1])
            {
                switch (arrPar[0].toLowerCase())
                {
                    case "id":
                       neObj.Id = arrPar[1];
                        break;
                    case "parentid":
                       neObj.ParentId = arrPar[1];
                        break;
                    case "propid":
                       neObj.PropId = arrPar[1];
                        break;
                    case "externalid":
                       neObj.ExternalId = arrPar[1];
                        break;
                    case "locationid":
                       neObj.LocationId = arrPar[1];
                        break;
                    case "name":
                       neObj.Name = arrPar[1];
                        break;
                    case "necode":
                       neObj.NeCode = arrPar[1];
                        break;
                    case "systype":
                       neObj.Systype = arrPar[1];
                        break;
                    case "elementtype":
                       neObj.ElementType = arrPar[1];
                        break;
                    case "lon_pos":
                       neObj.Easting = arrPar[1];
                        break;
                    case "lat_pos":
                       neObj.Northing = arrPar[1];
                        break;
                    case "tooltip":
                       neObj.Tooltip = arrPar[1];
                        break;
                }
            }
        }
        // Check Northing/Easting
        if (neObj.Northing && neObj.Easting)
        {
            if ( this._appCoordMetrical == true )
            {
                var mapPt = this._mapObject.lonLatToMcs(Number(neObj.Easting), Number(neObj.Northing));
               neObj.Easting = mapPt.X;
               neObj.Northing = mapPt.Y;
            }
        }
        else
        {
            CV.mBOSS.DAL.MapLayerWebService.ClientLog( "LAT_POS/LON_POS missing OnMapSelectionChanged() Layer:" +  i_layerName); 
        }
        return neObj;
    },
    
    ///
    ///  Map object double clicked
    ///
    OnMapDoubleClickObject: function( mapItem )
    {
        var netElem;
        var elementType = null;
        var mgMapLayer = mapItem.getMapLayer();
        if ( mgMapLayer != null ){
            var layerGroup = this._mapLayerMngr.getLayerGroupForLayer( mgMapLayer.Name );
            if ( layerGroup != null ){
                if ( layerGroup.ElementType != null){
                    elementType = layerGroup.ElementType;
                } else if ( layerGroup.LayerType != null){
                    elementType =layerGroup.LayerType;
                } else {
                    alert("Please add tag layerType for Group containing Layer:"+ mgMapLayer.getName());
                }
            }
        }
        
        var objInfo = mapItem.getLink();
        if (objInfo.charAt(0) == '@')
        {
            netElem=this.ExtractNeObjectInfo(objInfo, mgMapLayer.Name, mapItem.getKey(), mapItem.getName(), elementType);
        }
        else
        {
            netElem = new CV.mBOSS.DAL.NetworkElement();                        
            //Fill in the data
            netElem.Id = mapItem.getKey(); //Ne_id 
            netElem.TT = mapItem.getName();

            objInfoArr = objInfo.split(";"); //Infofield "77799;37681;STR168_01;30.12.1899;GSM900;OPR"
            //0=NeId,1=Code, 3=Name
            netElem.NeCode = objInfoArr[1];
            netElem.Name = objInfoArr[2];
            
            //Find the element type
            netElem.ElementType = elementType;
            
            var objExtent = null;
            if ( this._appCoordMetrical == true )
            {
                objExtent = mapItem.getExtentEx(true);
            } else {
                objExtent = mapItem.getExtentEx(false);
            }
            netElem.Northing = (objExtent.MaxY + objExtent.MinY)/2.0;
            netElem.Easting  = (objExtent.MaxX + objExtent.MinX)/2.0;
        }
        Global.EventController().fireThisEvent("evtMapDoubleClick", this, netElem);
    },
    ///
    ///
    /// Event from map: Device coordinates x and y clicked
    ///
    OnMapClicked: function(x, y){
        //not implemented
        //alert("OnMapClicked X="+x+" Y="+y);
    },
    ///
    /// Event from Map(ActiveX)
    /// Point digitized
    OnMapDigitizedPoint: function(pointArr)
    {
        if ( this._appCoordMetrical == true )
        {
            var aArea = new Array();
            var mcsPoint = this._mapObject.lonLatToMcs(pointArr[0], pointArr[1]);
            
            aArea[0] = mcsPoint.X;
            aArea[1] = mcsPoint.Y;
            // Fire event about digitize finished
            Global.EventController().fireThisEvent("evtDigitizedPoint", this, aArea); 
        } else {
            //returning MapGuide lat/lon coordinates
            Global.EventController().fireThisEvent("evtDigitizedPoint", this, pointArr); 
        }
    },
    ///
    ///Event from Map(ActiveX)
    ///point or Rect digitized
    OnMapDigitizedArea: function(rectArr)
    {
        var aArea = new Array();
        //Check for point or rect
        if ( rectArr[0] == rectArr[2] && rectArr[1] == rectArr[3]){
            if ( this._appCoordMetrical == true )
            {
                var mcsPoint = this._mapObject.lonLatToMcs( rectArr[0], rectArr[1]);
                aArea[0] = mcsPoint.X;
                aArea[1] = mcsPoint.Y;
            } else {
                aArea[0] = rectArr[0];//mcsPoint.X;
                aArea[1] = rectArr[1];//mcsPoint.Y;
            }
            
            // Fire event about digitize finished
            Global.EventController().fireThisEvent("evtDigitizedRect", this, aArea); 
        } else {
            if ( this._appCoordMetrical == true )
            {
                var mcsPoint = this._mapObject.lonLatToMcs(rectArr[0], rectArr[1]);
                aArea[0] = mcsPoint.X;
                aArea[1] = mcsPoint.Y;
                mcsPoint = this._mapObject.lonLatToMcs(rectArr[2], rectArr[3]);
                aArea[2] = mcsPoint.X;
                aArea[3] = mcsPoint.Y;
                // Fire event about digitize finished
                Global.EventController().fireThisEvent("evtDigitizedRect", this, aArea); 
            } else {
                Global.EventController().fireThisEvent("evtDigitizedRect", this, rectArr); 
            }
        }
    },
    OnMapDigitizedPolygon: function(numPoints, mgPontArr)
    {
        var polyPoint = new Array();
        //Check for point or rect
        var Area = 0;
       for(var i=0; i<numPoints; i++){
            polyPoint[i] = new CV.mBOSS.DAL.Point();
            if ( this._appCoordMetrical == true )
            {
                var mcsPoint = this._mapObject.lonLatToMcs(mgPontArr.item(i).X, mgPontArr.item(i).Y);
                polyPoint[i].x = mcsPoint.X;
                polyPoint[i].y = mcsPoint.Y;
            } else {
                polyPoint[i].x = mgPontArr.item(i).X;
                polyPoint[i].y = mgPontArr.item(i).Y;
            }
       }
       // Calculate the area of the polygon tio find rotation direction
       // Area > 0 == Counter clockwise
       // Area < 0 == Clockwise
       for(i=0; i<numPoints-1; i++){
            Area += (polyPoint[i].x*polyPoint[i+1].y - polyPoint[i+1].x*polyPoint[i].y);
       }
       var polygon = new Array(2);
       polygon[0] = polyPoint;
       polygon[1] = Area < 0 ? true : false; //true=clockwise
            // Fire event about digitize finished
       Global.EventController().fireThisEvent("evtDigitizedPolygon", this, polygon); 
       
    },
    ///
    /// Callback from MapGuide when Busy state changes
    /// bBusy == true, means leaving busy state
    /// bBusy == false, meand entering busy state
    ///
    OnMapBusyStateChanged: function( bBusy )
    {
        // Since the setVisibility calls doesn't work in busy state
        // We have to check in pending initialization, and do it when busy state releases
        
        if ( bBusy == false && this._pendingDefaultSettings == true)
        {
            this.mgSetInitialStates();
            this._pendingDefaultSettings = false;
            // Read the new map rect and fire evtMapWindowChanged event
            this.mgGetMapRect();
            this.getDynamicLegend();
            Global.EventController().fireThisEvent("evtMapWindowChanged", this, null); 
        } else if ( bBusy == true ){
            this.mgGetMapRect();
            this.getDynamicLegend();
            Global.EventController().fireThisEvent("evtMapWindowChanged", this, null); 
        }
    },
    
    OnMapResize: function(width, height)
    {
        this.loadMap();
    },
    
    OnMapMouseMove: function(x, y){
        //not implemented
        if ( this._mapDataMngr != null )
        {
           var mapElem = this._mapDataMngr.findMapElementTooltip(x, y );
           this._mapObject.setTooltip(mapElem, x, y);
        }
    },
    
    OnMapContextDataRequest: function(x, y)
    {
        //not implemented
        if ( this._mapDataMngr != null )
        {
           return this._mapDataMngr.findMapElement(x, y );
        }
        return null;
    },
    
    OnRequestSetMapMode: function( requestedMapMode )
    {
        //Call MapApi to excecute the ModeChange
        this.setMapMode( requestedMapMode );
        //Since this was aqn internal request, we broadcast it
        Global.EventController().fireThisEvent("evtMapModeChanged", this, requestedMapMode); 
    },
    
    /// *************************************************
    /// **   MapGuide Interface functions
    /// *************************************************
    
    mgSetInitialStates: function()
    {
        // Read mapGuide set-up and add to internal Layer config
        this.mgReadInitialLayerSettings();
        // Set default filters
        this.mgApplyAllLayersWhere();

        // Set water layers priority
        var water_mark = this._mapLayerMngr.getPlotOverWaterMarks();
        this.mgSetWaterMark(water_mark);
        
        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._sDefaultMapLayers != null && this._sDefaultMapLayers.length > 0){
            //Default map layers
            if (this._sDefaultMapLayers[0] instanceof Array){
                // Not current module, just set active flag
                for (var i=0; i<this._sDefaultMapLayers.length; i++){
                    if (this._sDefaultMapLayers[i][0] == this._mapLayerMngr.getModuleName()) {
                        for (var j=1; j<this._sDefaultMapLayers[i].length; j++) {
                            this.setLayerGroupVisibility(this._sDefaultMapLayers[i][j], true, false);
                        }
                    }
                    else {
                        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.setLayerGroupVisibility(this._sDefaultMapLayers[i], true, false);
                }
            }
        }
    },
    ///
    /// Read initial settings in active Mapguide layers and store in LayerConfig
    /// NB! traverse all modules initially
    ///
    mgSetLayerRebuild: function()
    {
        var moduleList = this._mapLayerMngr.getModuleList();
        if ( moduleList )
        {
            var currModuleIdx = this._mapLayerMngr.getModuleIdx();
            for(mIdx=0; mIdx<moduleList.length; mIdx++)
            {
                var layerGroupList = moduleList[mIdx].LayerGroups;
                var numGroups = layerGroupList.length;
                for(var grpIdx=0; grpIdx<numGroups; grpIdx++)
                {
                    var numLayers =  layerGroupList[grpIdx].Layers.length;
                    var oldWhere, newWhere;
                    for(var layerIdx=0; layerIdx<numLayers; layerIdx++)
                    {
                        //First we read the old filter
                        var mgLayer = this._mapObject.getMapLayer( layerGroupList[grpIdx].Layers[layerIdx].LayerId );
                        if ( mgLayer )
                        {
                            if ( layerGroupList[grpIdx].Property.bRebuild == true ){
                                mgLayer.setRebuild(true);
                            }
                        }
                    }
                }
            }
        }
    },
    
    mgReadInitialLayerSettings: function()
    {
        var moduleList = this._mapLayerMngr.getModuleList();
        if ( moduleList )
        {
            var currModuleIdx = this._mapLayerMngr.getModuleIdx();
            for(mIdx=0; mIdx<moduleList.length; mIdx++)
            {
                var layerGroupList = moduleList[mIdx].LayerGroups;
                var numGroups = layerGroupList.length;
                for(var grpIdx=0; grpIdx<numGroups; grpIdx++)
                {
                    var layerGroup = layerGroupList[grpIdx];
                    var numLayers =  layerGroup.Layers.length;
                    var oldWhere, newWhere;
                    for(var layerIdx=0; layerIdx<numLayers; layerIdx++)
                    {
                        var layer = layerGroup.Layers[layerIdx];
                        
                        //First we read the old filter
                        var mgLayer = this._mapObject.getMapLayer( layer.LayerId );
                        if ( mgLayer )
                        {
                            baseWhere = mgLayer.getSQLWhere();
                            layer.LayerQuery.BaseWhere = baseWhere;
                            if ( currModuleIdx == mIdx ){
                                //Set selectability for "current" module as initial state
                                mgLayer.setSelectability( layerGroup.Property.bSelectable );
                            }
                            if ( layerGroup.Property.bRebuild == true ){
                                mgLayer.setRebuild(true);
                            }
                        }
                    }
                }
            }
        }
    },
    
    
    
    ///
    /// Traverse all layers in current module and clear visibility
    ///
    mgClearCurrModuleVisibility: function( )
    {
        var layerGroupList = this._mapLayerMngr.getLayerGroupList();
        if ( layerGroupList )
        {
            //Can't change any properties if map busy, have to stop it
            if ( this._mapObject.isBusy() == true )
            {
                this._mapObject.stop();
            }
            //Traverse all groups and turn visibility off
            var numGroups = layerGroupList.length;
            for(var grpIdx=0; grpIdx<numGroups; grpIdx++)
            {
                var numLayers =  layerGroupList[grpIdx].Layers.length;
                for(var layerIdx=0; layerIdx<numLayers; layerIdx++)
                {
                    var mgLayer = this._mapObject.getMapLayer( layerGroupList[grpIdx].Layers[layerIdx].LayerId );
                    if ( mgLayer )
                    {
                        mgLayer.setVisibility( false );
                    }
                }
            }
        }
        return true;
    },
    
    ///
    /// Traverse the current module layers and set corresponding visibility and selectability in MapGuide
    ///
    mgSetCurrModuleVisibility: function( )
    {
        var layerGroupList = this._mapLayerMngr.getLayerGroupList();
        if ( layerGroupList )
        {
            //Can't change any properties if map busy, have to stop it
            if ( this._mapObject.isBusy() == true )
            {
                this._mapObject.stop();
            }
            //Traverse all groups and turn visibility off
            var numGroups = layerGroupList.length;
            for(var grpIdx=0; grpIdx<numGroups; grpIdx++)
            {
                var numLayers =  layerGroupList[grpIdx].Layers.length;
                for(var layerIdx=0; layerIdx<numLayers; layerIdx++)
                {
                    var mgLayer = this._mapObject.getMapLayer( layerGroupList[grpIdx].Layers[layerIdx].LayerId );
                    if ( mgLayer )
                    {
                        mgLayer.setVisibility( layerGroupList[grpIdx].Property.Active );
                        mgLayer.setSelectability( layerGroupList[grpIdx].Property.bSelectable );
                    }
                }
            }
        }
        return true;
    },
    
    ///
    /// Traverse all layers and apply where clauses to all datasets, according to global filters (Systype, Status etc)
    ///
    mgApplyAllLayersWhere: function( )
    {
        bFilterChanged = false;
        var layerGroupList = this._mapLayerMngr.getLayerGroupList();
        if ( layerGroupList )
        {
            //Traverse all layer groups and apply filter
            var numGroups = layerGroupList.length;
            for(var grpIdx=0; grpIdx<numGroups; grpIdx++)
            {
                //Set filter for group
                bFilterChanged = this.mgSetLayerGroupFilter( layerGroupList[grpIdx] );
            }
        }
        return bFilterChanged;
    },
    
    ///
    ///
    ///
    mgSetWaterMark: function(i_waterMarks)
    {
        if ( i_waterMarks == null ){
            return;
        }
        if ( this._mapObject.isBusy() == true )
        {
                this._mapObject.stop();
        }
        var marks = i_waterMarks.split('|');
        var topMarkGrp      = marks[0];
        var waterGroup      = marks[1];
        var bottomMarkGrp   = marks[2];
        
        var mgTopLayers = this._mapObject.getMapLayerGroup(topMarkGrp);
        var mgWaterLayers = this._mapObject.getMapLayerGroup(waterGroup);
        var mgBottomLayers = this._mapObject.getMapLayerGroup(bottomMarkGrp);
        
        //For now we need all 3 layers
        if ( mgTopLayers == null || mgWaterLayers == null || mgBottomLayers == null){
            alert("mapApiMg::mgSetWaterMark layer groups not found in template:" +i_waterMarks);
            return;
        }
        
        //Find lowest index of top marker
        var i=0;
        var numLayers = mgTopLayers.MapLayers.Count;
        var topPri = 999;
        for (i=0; i<numLayers; i++){
            var layerPri = mgTopLayers.MapLayers.item(i).getPriority();
            topPri = layerPri < topPri ? layerPri : topPri;
        }
        //Find highest pri of lower marker
        numLayers = mgBottomLayers.MapLayers.Count;
        var bottomPri = 0;
        for (i=0; i<numLayers; i++){
            var layerPri = mgBottomLayers.MapLayers.item(i).getPriority();
            bottomPri = layerPri > bottomPri ? layerPri : bottomPri;
        }
        
        //Then we put the water layers between these two
        var step = 0.0001;
        var waterStartPri = bottomPri + step;
        var mapLayers = mgWaterLayers.getMapLayers();
        numLayers = mapLayers.size();
        var waterNames= "";
        for (i=0; i<numLayers; i++){
            var layer = mapLayers.item(i);
            layer.setPriority( waterStartPri );
            waterNames += (layer.getName() + ",");
            waterStartPri += step;
        }
    },
    ///
    /// i_layerGroup = class object containing all data for LayerGroup (List of layers etc)
    /// Apply Global filter (Systype and Status) then LayerGroupFilter if any
    ///
    mgSetLayerGroupFilter: function( i_layerGroup )
    {
        //Here we read the global filter data (Systype, Status etc)
        if ( i_layerGroup == null || i_layerGroup.Property.Active == false){
            return;
        }
        this._alertedFlag = false;
        //We add single quotes if not already added
        var currSystype = Global.Utils().addSingleQuotes( this._mapLayerMngr.getSystype() );
        var currStatus  = Global.Utils().addSingleQuotes( this._mapLayerMngr.getStatus() );
        var currServiceText= this._mapLayerMngr.getService();
        var currService = this.getServiceCode( currServiceText);
        var currHistoryFilter = this._mapLayerMngr.getHistoryFilter();
        var currMcc = Global.DataController().getData("evtMccChanged");
        var currMnc = Global.DataController().getData("evtMncChanged");
        var currMccText = currMcc ? Global.Utils().addSingleQuotes(currMcc.toString()) : "";
        var currMncText = currMnc ? Global.Utils().addSingleQuotes(currMnc.toString()) : "";        
        
        //MGMapObject can't be busy, doesn't accept property changes, have to stop ongoing functions!
        if ( this._mapObject.isBusy() == true )
        {
                this._mapObject.stop();
        }
        
        //Traverse all Layers in group apply filter
        var numLayers =  i_layerGroup.Layers.length;
        var layerType =  i_layerGroup.LayerType; //Type of layer CELL, SITE, etc
        var baseWhere, newWhere, layerQuery;
        var layerDisabled=false;
        for(var layerIdx=0; layerIdx<numLayers; layerIdx++)
        {
            var layer = i_layerGroup.Layers[layerIdx];
            var mgLayer = this._mapObject.getMapLayer( layer.LayerId );
            if ( mgLayer )
            {
                //First we check if this Layer is active due to filters
                if ( this.checkFilterMatch(layer.Systypes, currSystype) == false ||
                     this.checkFilterMatch(layer.LayerStatus, currStatus) == false ||
                     this.checkFilterMatch(layer.Services, currServiceText) == false ||
                     this.checkFilterMatch(layer.MNC, currMncText) == false
                     )
                {
                    // Layer not active due to filters, we  dissable by setting visibility and continue to next
                     if ( mgLayer.getVisibility( ) == true ){
                        mgLayer.setVisibility( false );
                    }
                    continue;
                }
                //Then we simply build up the new where (Without the "where" keyword)
                //baseWhere = mgLayer.getSQLWhere();
                newWhere = layer.LayerQuery.BaseWhere;
                orgWhere = mgLayer.getSQLWhere( );
                if ( newWhere == null ){ newWhere = "";}
                
                //Check if there is a separate Where statement
                if ( layer.LayerQuery.Where != null ){
                    if ( newWhere.length > 0) { newWhere += " and "; }
                    
                    newWhere += layer.LayerQuery.Where;
                }
                
                //Resolve the Table configured
                var mgTable = layer.LayerQuery.Table;
                if ( layer.LayerQuery.Table ){
                    mgTable = this.resolveTableName(i_layerGroup,layer);
                }
                //Check if a style/theme column is specified and/or if a table is defined
                var themeColumn = null;
                if ( layer.LayerQuery.ThemeTable && layer.LayerQuery.ThemeColumn ){
                     themeColumn=layer.LayerQuery.ThemeTable + "."+layer.LayerQuery.ThemeColumn;
                     //Need Table defined to connect data source with theme column
                     if ( mgTable != null ){
                         if ( newWhere.length > 0) { newWhere += " and "; }
                         newWhere += mgTable+"."+layer.LayerQuery.ThemeColumn+ "=" +themeColumn
                     }
                }
                
                //Apply global Systype filter
                if ( this.isLayerFilterActive(layer, 'systype') == true && 
                     layer.Systypes != null && layer.Systypes != "ignore"  )
                {
                    if ( newWhere.length > 0) { newWhere += " and "; }
                    
                    if ( currSystype != null && currSystype.length > 0)
                    {
                        newWhere += "SYSTYPE in ("+currSystype+")";
                    } else {
                        newWhere += "SYSTYPE in ('EMPTY')";
                    }
                    if ( layer.Systypes != "global" ){
                        newWhere += " and "; 
                        var layerSystype = Global.Utils().addSingleQuotes( layer.Systypes );
                        newWhere += "SYSTYPE in ("+layerSystype+")";
                    }
                }
                
                //Apply global Status filter
                if ( this.isLayerFilterActive(layer, 'status') == true &&
                     layer.LayerStatus != null && layer.LayerStatus != "ignore" &&
                     currStatus != null && currStatus.length > 0)
                {
                    if ( newWhere.length > 0 ) { newWhere += " and "; }
                    newWhere += "CELL_STATUS in ("+currStatus+")";
                    if ( layer.LayerStatus !=  null && layer.LayerStatus != "global" ){
                        newWhere += " and "; 
                        var layerStatus = Global.Utils().addSingleQuotes( layer.LayerStatus );
                        newWhere += "CELL_STATUS in ("+layerStatus+")";
                    }
                }
                //Apply global Service  filter
                if ( this.isLayerFilterActive(layer, 'service') == true &&
                     layer.Services != null && layer.Services != "ignore" &&
                     currService != null && currService != null && !isNaN(currService))
                {

                    if ( newWhere.length > 0 ) { newWhere += " and "; }
                    newWhere += " bitand(SERVICE,"+currService+") > 0" ;
                    if ( layer.Services != 'global'){
                        newWhere += " and ";
                        var layerService =  this.getServiceCode( layer.Services );
                        newWhere += " bitand(SERVICE, "+layerService+") > 0" ;
                    }
                }
                //Apply global Severity filter
                var currSeverity = this._mapLayerMngr.getSeverity();
                if ( this.isLayerFilterActive(layer, 'severity') == true &&
                     layer.Severity && layer.Severity != "ignore" &&
                     currSeverity != null && currSeverity.length > 0)
                {
                    if ( newWhere.length > 0 ) { newWhere += " and "; }
                    newWhere += "SEVERITY in ("+currSeverity+")";
                }
                if ( this.isLayerFilterActive(layer, 'history') == true ){
                    filterWhere = this.applyHistoryFilter(i_layerGroup, layer, currHistoryFilter, newWhere.length > 0);
                    if ( filterWhere != null ){
                         newWhere += filterWhere;
                    }
                }

                //Apply global MNC filter
                if ( this.isLayerFilterActive(layer, 'mnc') == true &&
                     layer.MNC && layer.MNC != "ignore" &&
                     currMnc != null && currMnc.length > 0)
                {
                    if ( newWhere.length > 0 ) { newWhere += " and "; }
                    newWhere += "MNC in ("+currMnc+")";
                }

                //Apply global MCC filter
                if ( this.isLayerFilterActive(layer, 'mcc') == true &&
                     layer.MCC && layer.MCC != "ignore" &&
                     currMcc != null && currMcc.length > 0)
                {
                    if ( newWhere.length > 0 ) { newWhere += " and "; }
                    newWhere += "MCC in ("+currMcc+")";
                }


                //If there are a dataLayerId, we apply this as n inlude or exclude filter
                filterWhere = this.applyDataLayerFilter(i_layerGroup, layer, currSystype, currStatus, currServiceText, currHistoryFilter, newWhere.length > 0);
                if ( filterWhere != null ){
                     newWhere += filterWhere;
                }
                //Apply Layer filter 
                var tablePrefix = (themeColumn != null ? mgTable : null);
                filterWhere = this.applyNeFilter(i_layerGroup, layer, tablePrefix, newWhere.length > 0);
                if ( filterWhere != null ){
                     newWhere += filterWhere;
                }
                
                filterWhere = this.applyColumnFilter(i_layerGroup, layer, newWhere.length > 0);
                if ( filterWhere != null ){
                     newWhere += filterWhere;
                }
                
                filterWhere = this.applyKpiReport(i_layerGroup, layer, newWhere.length > 0);
                if ( filterWhere != null ){
                     newWhere += filterWhere;
                }
                
                if ( mgTable != null ){
                    //Update the Table property, Note we can never the use the Where property again when the table property is customized
                        mgLayer.getLayerSetup().getDatabaseSetup().Table = mgTable;
                        Sys.Debug.trace(i_layerGroup.LayerGroupId+"::"+layer.LayerId+" Table:"+ mgTable);
                        if ( orgWhere != newWhere)
                        {
                           mgLayer.setSQLWhere( newWhere );
                           Sys.Debug.trace(i_layerGroup.LayerGroupId+"::"+layer.LayerId+" Where:"+newWhere);
                           bFilterChanged = true;    
                        }
                } else if ( layerType != null && layer.LayerQuery != null && (layerType == "SITE" || layerType == "MSC" )){
                    //Special case if SITE Layer, have to add correct Query
                    var sWhere = layer.LayerQuery.HasWhere == false? (newWhere == ""? "":" where "):" and ";
                    layerQuery = "("+layer.LayerQuery.Query+ sWhere + newWhere+")";

                    if ( layerQuery !=  mgLayer.getLayerSetup().getDatabaseSetup().Table )
                    {
                        //Update the Table property, Note we can never the use the Where property again when the table property is customized
                        mgLayer.getLayerSetup().getDatabaseSetup().Table = layerQuery;
                        Sys.Debug.trace(i_layerGroup.LayerGroupId+"::"+layer.LayerId+" Query:"+ layerQuery);
                    }
                } else if ( orgWhere != newWhere)
                {
                   mgLayer.setSQLWhere( newWhere );
                   Sys.Debug.trace(i_layerGroup.LayerGroupId+"::"+layer.LayerId+" Where:"+newWhere);
                   bFilterChanged = true;    
                }
                mgLayer.setVisibility( true );
            } // if mgLayer
        } //for LayerList

    },
       
    ///
    /// Return the table name if specified
    /// Check for tokens in brackets {TOKEN}, and replace with value
    /// Legal tokens: SYSTYPE, STATUS, SERVICE, 
    /// 
    resolveTableName: function(i_layerGroup, i_layer)
    {
        if ( i_layer.LayerQuery.Table ){
            var mgTable = i_layer.LayerQuery.Table;
            if ( i_layer.LayerQuery.Table.indexOf('{') != -1 ){
                //Check the different legal replacement keys
                if ( i_layer.Systype && i_layer.LayerQuery.Table.indexOf('{SYSTYPE}') != -1 ){
                    mgTable = mgTable.replace('{SYSTYPE}', i_layer.Systype);
                } else if (i_layer.Status && i_layer.LayerQuery.Table.indexOf('{STATUS}') != -1 ){
                    mgTable = mgTable.replace('{STATUS}', i_layer.Status);
                } else if (i_layerGroup.LayerFilter.KpiReport){
                    if ( i_layerGroup.LayerFilter.KpiReport.Kpi && i_layer.LayerQuery.Table.indexOf('{KPI_ID}') != -1 ){
                        mgTable = mgTable.replace('{KPI_ID}', i_layerGroup.LayerFilter.KpiReport.Kpi);
                    }
                    if ( i_layerGroup.LayerFilter.KpiReport.Period && i_layer.LayerQuery.Table.indexOf('{KPI_PERIOD}') != -1 ){
                        mgTable = mgTable.replace('{KPI_PERIOD}', i_layerGroup.LayerFilter.KpiReport.Period);
                    }
                }
                return mgTable;
            } else {
                return layer.LayerQuery.Table;
            }
        }
        return null;
    },   
    
    getServiceCode: function( service )
    {
        var serviceCode=0;
        
        if ( service == null || service.length == 0){
            return serviceCode;
        }
        
        var serviceList = service.split(',');
        for(var i=0; i<serviceList.length; i++){
            switch(serviceList[i].toLowerCase()){
                    case 'voice':
                    serviceCode+= 1;
                    break;
                    case 'gprs':
                    serviceCode+= 2;
                    break;
                    case 'edge':
                    serviceCode+= 4;
                    break;
                    case '3gdata':
                    serviceCode+= 8;
                    break;
                    case 'hsdpa':
                    serviceCode+= 16;
                    break;
                    case 'hsdpa2':
                    serviceCode+= 32;
                    break;
                    case 'hsdpa3':
                    serviceCode+= 64;
                    break;
                    case 'hsdpa4':
                    serviceCode+= 128;
                    break;
                    case 'hsdpa5':
                    serviceCode+= 256;
                    break;
                    case 'hsupa':
                    serviceCode+= 512;
                    break;
                    
            }
        }
        return serviceCode;
    },
    
    
    ///
    /// i_tablePrefix. Use this name as table prefix is given: tablePrefix.column
    applyNeFilter: function(i_layerGroup, i_layer, i_tablePrefix, i_bWhere)
    {
        var neWhere = null;
        var layerFilterList = null;
        var numFilters = 0;
        var tablePrefix = i_tablePrefix == null ? "" : i_tablePrefix+".";
        
        if ( i_layerGroup.LayerFilter.NeFilters != null ){
            //If some filters active, we filter on this list
            var activeFilters = 0;
            var filters = i_layerGroup.LayerFilter.NeFilters;
            for (var i=0; i<filters.length; i++){
                if ( filters[i].bFilterActive == true ){
                    activeFilters++; break;
                }
            }
            if ( activeFilters > 0 ){
                layerFilterList = i_layerGroup.LayerFilter.NeFilters;
            }
        } 
        if (layerFilterList == null && i_layerGroup.DefaultFilter != null && i_layerGroup.DefaultFilter.bFilterActive == true){
            layerFilterList = new Array(1);
            layerFilterList[0] = i_layerGroup.DefaultFilter;
        }
        
        if ( layerFilterList != null )
        {
            for(var idx=0; idx<layerFilterList.length; idx++){
                var neFilter = layerFilterList[idx];
                //Apply NE filter if provided
                if ( neFilter.bFilterActive == true &&  neFilter.NeFilterType != null && neFilter.NeIdFilter != null){
                    var filterLogic, filterWhere = "";
                    if ( numFilters == 0){
                        //First filter
                        if (i_bWhere == true) { filterWhere = " and (";} else { filterWhere = " (";}
                        numFilters++;
                    } else {
                        filterWhere = " or "; //next filter
                    }
                    if ( i_layerGroup.FilterMethod != null && i_layerGroup.FilterMethod == "EXCLUDE" )
                    {
                        filterLogic = " not in";
                    } else {
                        filterLogic= " in";
                    }
                    //Check if a specific filter query exists for filter type
                    if ( i_layer.LayerFilterQuery != null &&
                         i_layer.LayerFilterQuery.NeType.toUpperCase() == neFilter.NeFilterType.toUpperCase()){
                         
                        var where_and = i_layer.LayerFilterQuery.HasWhere ? " and ":" where ";
                        filterWhere +=  ( tablePrefix+"ne_"+i_layer.LayerType+"_id "+filterLogic+ "( " + i_layer.LayerFilterQuery.Query +
			                              where_and + " ne_" + neFilter.NeFilterType + "_id in (" + neFilter.NeIdFilter + " )) ");
                    } else {
                        //Then apply standard ne_"TYPE"_id filter
                        filterWhere +=  tablePrefix+"NE_"+neFilter.NeFilterType.toUpperCase()+"_ID" + filterLogic +"(" +neFilter.NeIdFilter+ ")";
                    }
                    if ( neWhere != null ){ 
                        neWhere += filterWhere;
                    } else {
                        neWhere = filterWhere;
                    }
                } 
            }
        }
        if ( numFilters > 0){
            neWhere += ")";
        }
        return neWhere;
    },
    
    //Apply History
    applyHistoryFilter: function(i_layerGroup, i_layer, i_historyFilter, bWhere)
	{
	    var filterWhere = "";
		if (i_layer.History != null && i_layer.History != "ignore")
		{
			var filter = i_historyFilter == null ? null : i_historyFilter.split('|');
			switch (i_layer.History)
			{
				case "global":
					if (filter != null)
					{
						var history = filter[0] == "true" ? 1 : 0;
						filterWhere += (bWhere == true) ? " and " : "";
						if (history == 1)
						{
							filterWhere += (" isHistory=" + history + " AND ");
							filterWhere += (" startDate  <= TO_DATE(\'" + filter[2] + "\',\'YYYY-MM-DD-HH24-MI\')");
							filterWhere += (" and endDate  >= TO_DATE(\'" + filter[1] + "\',\'YYYY-MM-DD-HH24-MI\')");
						}
						else
						{
							filterWhere += (" isHistory=0 ");
						}
					}
					else
					{
						filterWhere += (bWhere) ? " and " : "";
						filterWhere += (" isHistory=0 ");
					}
					break;
				case "true":
					if (filter != null && filter[0] == "true")
					{
						filterWhere += (bWhere) ? " and " : "";
						filterWhere += (" isHistory=1 ");
						if ( filter.length > 1 ){
						    
						    filterWhere += (" AND startDate  <= TO_DATE(\'" + filter[2] + "\',\'YYYY-MM-DD-HH24-MI\')");
							filterWhere += (" and endDate  >= TO_DATE(\'" + filter[1] + "\',\'YYYY-MM-DD-HH24-MI\')");
						}
					} else {
					    filterWhere += (bWhere) ? " and " : "";
					    filterWhere += (" 1=0 ");
					}
					break;
				case "false":
					if (filter == null || filter[0] == "false")
					{
						filterWhere += (bWhere) ? " and " : "";
						filterWhere += (" isHistory=0 ");
					} else {
					    filterWhere += (bWhere) ? " and " : "";
					    filterWhere += (" 1=0 ");
					}
					break;
			}
		}
	     if ( filterWhere.length > 0){
            return filterWhere;
         } else {
            return null;
         }
	},
	
    //STIAN (Search Tag !!)
    applyDataLayerFilter: function(i_layerGroup, i_layer, i_systype, i_status, i_service, i_historyFilter, i_bWhere)
    {
        //Do not add dataLayerFilter in mg for PreGenData layers which create datafiles not updated queries
        
        var dataLayerGroup = (i_layerGroup.PreGenData == true) ? null :  this._mapLayerMngr.getLayerGroup( i_layerGroup.DataLayerId );
        if ( dataLayerGroup != null ){
            var dataLayer = this.getDataLayerByFilters(dataLayerGroup, i_layer, i_systype, i_status, i_service, i_historyFilter);
            if ( dataLayer != null ){
                var dataFilter = (i_bWhere == false) ? "" : " and ";
                var filterLogic = i_layerGroup.FilterMethod == "INCLUDE" ? "in" : "not in";
                dataFilter += "ne_"+dataLayerGroup.LayerType+"_id "+filterLogic+" ("+dataLayer.LayerQuery.Query;
                //Then add the "internal" filters for the data layer
                var bDataWhere = dataLayer.LayerQuery.HasWhere;
                //Systype
                if ( i_systype != null && dataLayer.Systypes != null && dataLayer.Systypes != "ignore"){
                    dataFilter += (bDataWhere == false) ? " where " : " and ";
                    var systypeFilter = dataLayer.Systypes =="global" ? i_systype : Global.Utils().addSingleQuotes( dataLayer.Systypes );
                    dataFilter += " systype in ("+ systypeFilter + ")";
                    bDataWhere = true;
                }
                //Status
                if ( i_status != null && dataLayer.LayerStatus != null && dataLayer.LayerStatus != "ignore"){
                    dataFilter += (bDataWhere == false) ? " where " : " and ";
                    var statusFilter = dataLayer.LayerStatus =="global" ? i_status : Global.Utils().addSingleQuotes( dataLayer.LayerStatus );
                    dataFilter += " status in ("+ statusFilter + ")";
                    bDataWhere = true;
                }
                //Service
                if ( i_service != null && !isNaN(i_service) && dataLayer.Services != null && dataLayer.Services != "ignore"  )
                {
                    dataFilter += (bDataWhere == false) ? " where " : " and ";
                    dataFilter += " bitand(SERVICE,"+i_service+") > 0" ;
                    if ( i_layer.Services != 'global'){
                        dataFilter += " and ";
                        dataFilter += " bitand(SERVICE, "+this.getServiceCode( dataLayer.Services )+") > 0" ;
                    }
                    bDataWhere = true;
                }
                //History
                var historyFilter =  this.applyHistoryFilter(dataLayerGroup, dataLayer, i_historyFilter, bDataWhere);
                if ( historyFilter != null ){
                    dataFilter += historyFilter;
                }
                //close up
                dataFilter += ")";
                return dataFilter;
            } else {
                //No dataLayers match, should not happen
                if ( this._alertedFlag  == false ){
                    var errMsg = this.getRequiredDataLayerConfig(i_layer);
                    this._alertedFlag = true;
                    alert("LayerGroup: "+i_layerGroup.LayerGroupId+" No matching dataLayer for :"+i_layer.LayerId+"  DataLayergGroup = "+dataLayerGroup.LayerGroupId+"\n"+ errMsg);
                }
            }
            
        }
        return null;
    },
    
    ///
    /// Check if the LayerQuery has the WhereColumns tag set 
    /// if not set WhereColumns == null, filters allowed
    /// if != null, WhereColumns tag must contain the provided filterName to be allowed
    ///
    isLayerFilterActive: function(i_layer, i_filterName)
    {
       var whereColumns  = (i_layer.LayerQuery != null && i_layer.LayerQuery.WhereColumns != null) ? i_layer.LayerQuery.WhereColumns : null;
       return (whereColumns != null && whereColumns.match(i_filterName) == null) ? false : true;    
    },
    
    ///
    ///
    ///
    checkFilterMatch:function (i_LayerFilter, i_globalFilter)
    {
        if ( i_LayerFilter == null ||  i_LayerFilter == "ignore" || i_LayerFilter == "global"){
            return true;
        }
        if ( i_globalFilter == null || i_globalFilter.length==0){
            return false;
        }
        var filterList = i_LayerFilter.split(',');
        var globalList = i_globalFilter.split(',');
        for(var l=0; l<filterList.length; l++){
            
            for(var d=0; d<globalList.length; d++){
                var filter = filterList[l].indexOf("'") == -1 ? "\'"+filterList[l]+"\'" : filterList[l];
                var global = globalList[d].indexOf("'") == -1 ? "\'"+globalList[d]+"\'" : globalList[d];
                if ( filter == global ){
                    return true; //one found, then we accepts
                }
            }
        }
        return false;
        
    },
    
    ///
    /// Used for Map Layers with DataLayers, check if the provided filter match the corresponding dataLayer fiter
    /// Special case if they are not matching but the layer filter is "global", then we chack with the global filter.
    /// return : true if match, else false
    checkLayerFilterMatch: function(i_layerFilter, i_dataFilter, i_globalFilter)
    {
        //First translate null and ignore as null
        var layerFilter = (i_layerFilter == null || i_layerFilter == "ignore") ? null : i_layerFilter;
        var dataFilter  = (i_dataFilter  == null || i_dataFilter  == "ignore") ? null : i_dataFilter;

         //Then check for match
        if ( layerFilter != dataFilter){
            if ( (layerFilter == "global" && dataFilter != null )|| (dataFilter == "global" && layerFilter != null) ){ 
                //We now accept all global combinations
                return true;  
            } else if (dataFilter == null || layerFilter == null) {
                return false;
            } else {
                var dataList = dataFilter.split(',');
                var layerList = layerFilter.split(',');
                for(var l=0; l<layerList.length; l++){
                    var found = false;
                    for(var d=0; d<dataList.length; d++){
                        if ( layerList[l] == dataList[d] ){
                            found = true;
                            break;
                        }
                    }
                    if ( found == false ){
                        return false;
                    }
                }
                return true;
            }
        }
        return true; //Match OK
    },
    ///
    /// Scan all layers in dataLayerGroup and find if any layer match the filters in layer
    /// Return the first and best matching layer
    getDataLayerByFilters: function(i_dataLayerGroup, i_layer, i_systype, i_status, i_service, i_historyFilter)
    {
        var numDataLayers = i_dataLayerGroup.Layers.length;
        for(var i=0;i<numDataLayers; i++){
            var dataLayer = i_dataLayerGroup.Layers[i];
            //Only Layers with a Query defined is an MG datalayer
            if ( dataLayer.LayerQuery == null || dataLayer.LayerQuery.Query == null ){
                continue;
            }
            //Check systypes
            if ( this.checkLayerFilterMatch(i_layer.Systypes, dataLayer.Systypes, i_systype) == false ){
                continue;
            }
            //Check status
            if ( this.checkLayerFilterMatch(i_layer.LayerStatus, dataLayer.LayerStatus, i_status) == false ){
                continue;
            }
            //Check Services
            if ( this.checkLayerFilterMatch(i_layer.Services, dataLayer.Services, i_service) == false ){
                continue;
            }
            //Check Quality
            if ( this.checkLayerFilterMatch(i_layer.Quality, dataLayer.Quality, null) == false ){
                continue;
            }
            //Check Severity
            if ( this.checkLayerFilterMatch(i_layer.Severity, dataLayer.Severity, null) == false ){
                continue;
            }
            //Check History, Equal filters is always first pri OK
            if ( i_layer.History != dataLayer.History ){
                if ( i_layer.History != "global" ){
                    continue; //Anything but "global" is no match
                } 
                // For a "global" filter, check if the dataLayer has the matching filter status
                var filter = i_historyFilter == null ? null : i_historyFilter.split('|');
                if ( (filter == null || filter[0] == "false") && dataLayer.History != "false" ){
                    continue;
                }
                if ( (filter != null && filter[0] == "true") && dataLayer.History != "true" ){
                    continue;
                }
            }
            // if we got so far, we use this layer
            return dataLayer;
        }
        return null;
    },
    
    ///
    /// Check which columns need
    getRequiredDataLayerConfig: function(i_layer)
    {
        var reqFields="Required dataLayer config: LayerQuery";

        if ( i_layer.Systypes != null && i_layer.Systypes != "ignore" ){
            reqFields += ", systype ["+ i_layer.Systypes+"]";
        } else {
            reqFields += ", systype [ NULL ]";
        }
        if ( i_layer.LayerStatus != null && i_layer.LayerStatus != "ignore" ){
            reqFields += ", status ["+ i_layer.LayerStatus +"]";
        } else {
            reqFields += ", status [ NULL ]";
        }
        if ( i_layer.Services != null && i_layer.Services != "ignore" ){
            reqFields += ", services ["+ i_layer.Services +"]";
        } else {
            reqFields += ", services [ NULL ]";
        }
        if ( i_layer.Quality != null && i_layer.Quality!= "ignore" ){
            reqFields += ", quality ["+ i_layer.Quality+"]";
        } else {
            reqFields += ", quality [ NULL ]";
        }
        if ( i_layer.Severity != null && i_layer.Severity!= "ignore" ){
            reqFields += ", severity ["+ i_layer.Severity +"]";
        } else {
            reqFields += ", severity [ NULL ]";
        }
        if ( i_layer.History != null  && i_layer.History!= "ignore"){
            reqFields += ", history";
        } else {
            reqFields += ", history [ NULL ]";
        }
        return reqFields;
    },
    
    applyColumnFilter: function(i_layerGroup, i_layer, bWhere)
    {
        var filterWhere = "";
        var colFilterList = i_layerGroup.LayerFilter.ColumnFilters;
        if ( colFilterList == null || colFilterList.length == 0){
            return null;
        }
        for(var idx=0; idx <colFilterList.length; idx++){
            var colFilter = colFilterList[idx];
            if( colFilter.bFilterActive == true){
                var numFilter = colFilter.Filter.length;
                for(var i=0; i<numFilter; i++){
                    var filterSpec = colFilter.Filter[i].split("|");
                    if ( bWhere == true || filterWhere.length > 0) { filterWhere += " and ";}
                    var filter="";
                    var filterOperator=null;
                    var filterColumn   = "UPPER(" + filterSpec[0] + ") ";
                    var filterData     = filterSpec[2].toUpperCase();
                    var filterOperator = filterSpec[1].toUpperCase();
                    //Note we add sincle brackets "'" if not provided
                    switch( filterOperator ){
                        case 'INCLUDE':
                        case 'IN':
                            filterOperator = " in";
                            //NB!! falling through
                        case 'EXCLUDE':
                        case 'NOT IN':
                            if ( filterOperator == null) {filterOperator =" not in"};
                            // Common in/not in functionality: 
                            if ( filterData.indexOf("'") == -1 ){
                                filter = filterOperator + "(\'"+ filterData.replace(/,/g,"\',\'") +"\')" ;
                            } else {
                                filter = filterOperator + "("+ filterData +")" ;
                            }
                        break;
                        case 'LIKE':
                            if ( filterData.indexOf("'") == -1 ){
                                filter = " like \'"+ filterData + "\'";;
                            } else {
                                filter = " like "+ filterData;
                            }
                        break;
                        default:
                            filter = filterOperator + filterData;//>  < etc
                        break;
                    }
                    filterWhere += (filterColumn +  filter);
                }
             }
         }
         if ( filterWhere.length > 0){
            return filterWhere;
         } else {
            return null;
         }
    },
    
    applyKpiReport: function(i_layerGroup, i_layer, bWhere)
    {
        var filterWhere = "";
        if ( i_layerGroup.LayerFilter.KpiReport == null || i_layerGroup.LayerFilter.KpiReport.Date == null){
            return null;
        }

        if ( bWhere == true || filterWhere.length > 0) { filterWhere += " and ";}
       
        var dateFormat = null;
        switch (i_layerGroup.LayerFilter.KpiReport.Period){
        case 'YEAR':
            dateFormat = "YYYY";
        break;
        case 'MONTH':
            dateFormat = "YYYYMM";
        break;
        case 'WEEK':
            dateFormat = "YYYYIW";
        break;
        case 'DAY':
            dateFormat = "YYYYDDD";
        break;
        
        }
       
       if ( i_layerGroup.LayerFilter.KpiReport.Date ){
            
            var strDate;
            //if date object, convert to date string
            if(i_layerGroup.LayerFilter.KpiReport.Date.formatDate){
               //format date
               strDate = i_layerGroup.LayerFilter.KpiReport.Date.formatDate("MM/dd/yyyy");
            }
            else {
                strDate = i_layerGroup.LayerFilter.KpiReport.Date;
            }
       
            // Add KPI DATE FIlter
            filterWhere += " to_char(KPI_TIME, \'"+ dateFormat + "\') = "+
                       "to_char(to_date(\'"+strDate+"\', 'MM/DD/YYYY'), \'"+dateFormat+"\') ";
       }
       if ( i_layerGroup.LayerFilter.KpiReport.TrxType ){
        
       }
       //Add KPI filter
       if ( i_layerGroup.LayerFilter.KpiReport.KpiFilter ){
            var filters = i_layerGroup.LayerFilter.KpiReport.KpiFilter.Filters;
            filterWhere += " and (";
            for(var i=0; i<filters.length; i++){
                filterWhere += filters[i].Kpi+" between "+filters[i].MinValue+" and "+filters[i].MaxValue;
                if ( i<filters.length-1){
                    filterWhere += " "+filters[i].Operator+" ";
                }
            }
            filterWhere += ")";
       }
       
        if ( filterWhere.length > 0){
            return filterWhere;
        } else {
            return null;
        }
    },
    
    
    ///
    /// 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); 
    },
    
    ///
    /// Set Sdf files for a layerGroup
    ///
    mgSetLayerGroupSdfFile: function( i_pregenResponse )
    {
        if ( i_pregenResponse == null )
        {
            return false;
        }
		if( this._mapObject.isBusy() )
		{
			this._mapObject.stop();
		}
    
        var layerGroup = this._mapLayerMngr.getLayerGroup(i_pregenResponse.LayerGroupId);
        var sdfFileName, prevFile;
        var bChanged = false;
        if ( layerGroup != null )
        {
            for (idx=0; idx < layerGroup.Layers.length; idx++)
            {
               var mgLayer = this._mapObject.getMapLayer( layerGroup.Layers[idx].LayerId );
               if ( mgLayer != null )
               {
                    sdfFileName = i_pregenResponse.SessionId + layerGroup.Layers[idx].LayerId +"."+i_pregenResponse.FileFormat;
                    prevFile = mgLayer.getLayerSetup().DataFile;
                    if ( sdfFileName != prevFile )
                    {
                        mgLayer.getLayerSetup().setDataFile( sdfFileName );
                        bChanged = true;
                    }
               }
            }
            
        }
        return bChanged;
    },
    
    //
    // Draw an object of type "shape_type"
    //
    mgDrawShape: function(i_easting, i_northing, i_shapeType, i_shapeParam, i_lineColor, i_shadowColor, i_innerColor, i_fillColor)
    {
		if( this._mapObject.isBusy() )
		{
			this._mapObject.stop();
		}
		if(i_shapeType && i_easting && i_northing)
		{
			var RedLineSetup = this._mapObject.getRedlineSetup();
			var point = this._mapObject.createObject("MGPoint");
			//Need radius in meter not device pixels
			var radius_m = this.distanceDeviceToMeter( i_shapeParam );
			var FillAttr = RedLineSetup.getFillAttr();
			var EdgeAttr = RedLineSetup.getEdgeAttr();
			// Copy current values
			var oldBkMode       = FillAttr.getBackMode();
			var oldFillColor    = FillAttr.getColor();
			var oldStyle        = FillAttr.getStyle();
			var oldLineColor    = EdgeAttr.getColor();
			var oldLineThickness = EdgeAttr.getThickness();
			//FillAttr.setBackMode("Transparent");
			//FillAttr.setStyle("None");
			//LineAttr.setColor(4); // Black
			var lineColorIdx = this.mgGetColorIndexFromName(i_lineColor);
			var fillColorIdx = this.mgGetColorIndexFromName(i_fillColor);
			var shadowColorIdx = null;
			var innerColorIdx  = null;
			if ( i_shadowColor ){
			    shadowColorIdx = this.mgGetColorIndexFromName(i_shadowColor);
			}
			if ( i_innerColor ){
			    innerColorIdx = this.mgGetColorIndexFromName(i_innerColor);
			}
			
			if ( fillColorIdx != -1 )
			{
			    FillAttr.setBackMode("Transparent");
			    FillAttr.setStyle("Solid");
			    FillAttr.setColor(fillColorIdx);
			}
			else
			{
			    FillAttr.setBackMode("Transparent");
			    FillAttr.setStyle("None");
			}
			//FillAttr.setColor(4);
			EdgeAttr.setStyle("Solid"); 
			EdgeAttr.setColor(lineColorIdx); 
			//EdgeAttr.setThickness(lineWidth);
			EdgeAttr.setThickness( 2 );
			
			point.setY(i_northing);
			point.setX(i_easting);

			zoomCircleRedlineLayer = this._mapObject.getMapLayer("CircleRedline");
			if (zoomCircleRedlineLayer == null)
			{
			    zoomCircleRedlineLayer = this._mapObject.createLayer("redline", "CircleRedline");
			    zoomCircleRedlineLayer.setShowInLegend(false);
			}
			else
			{
				zoomCircleRedlineLayer.removeAllObjects();
			}
			zoomCircleRedlineLayer.setSelectability(false);
			zoomCircleRedlineLayer.setVisibility(true);
			//var priority=map.getMapLayer("Cells GSM900").getPriority();// "MSCLocations2" (Changed 05.04.06)
			//zoomCircleRedlineLayer.setPriority(priority-0.0001);
			zoomCircleRedlineLayer.setPriority(99.99999);
			
			//myObject = zoomCircleRedlineLayer.createMapObject("","ZoomCircle","");
			myObject = zoomCircleRedlineLayer.createMapObject("","","");
			// zoomCircleVisibilityCounter=2;
			// zoomCircleVisibilityCounter=visibilityCounter;

            if ( this._appCoordMetrical == true )
            {
                point.setY(i_northing);
			    point.setX(i_easting);
			} else {
			    //Convert from lat/lon to msc
                var mcsPoint = this._mapObject.lonLatToMcs(i_easting, i_northing);
                point.setY( mcsPoint.Y );
                point.setX( mcsPoint.X );
			}

			var valid = myObject.addCirclePrimitive(point,true,radius_m,"M",100);
			
			if ( shadowColorIdx ){
			    radius_m = this.distanceDeviceToMeter( i_shapeParam-2 );
			    EdgeAttr.setColor(shadowColorIdx); 
			    myObject.addCirclePrimitive(point,true,radius_m,"M",100);
			}
			if ( innerColorIdx ){
			    radius_m = this.distanceDeviceToMeter( i_shapeParam-4 );
			    EdgeAttr.setColor(innerColorIdx); 
			    myObject.addCirclePrimitive(point,true,radius_m,"M",100);
			}
			
			// Restore values
			EdgeAttr.setThickness(oldLineThickness);
			EdgeAttr.setColor(oldLineColor);
			FillAttr.setStyle(oldStyle);
			FillAttr.setColor(oldFillColor);
			FillAttr.setBackMode(oldBkMode);
			
			
		} else {
		    //ShapeType, Easting, Northing is null
		    zoomCircleRedlineLayer = this._mapObject.getMapLayer("CircleRedline");
			if (zoomCircleRedlineLayer != null)
			{
				zoomCircleRedlineLayer.removeAllObjects();
			}
			this._shapeDrawn = false;
		}
    },
    //
    // Mapping between a color name and an mg color index
    //
    mgGetColorIndexFromName: function(i_lineColor)
    {
        if ( i_lineColor )
        {
            switch( i_lineColor.toLowerCase() )
            {
                case 'red':
                    return 5;
                case 'black':
                    return 4;
                case 'blue':
                    return 9;
                case 'green':
                    return 7;
                case 'yellow':
                    return 6;
                case 'orange':
                    return 38;
                default:
                    return -1;
            }
        }
        return -1;
    },
    
    mgGetMapRect: function() 
    { 
        //Lookup Map extent from MG Active X, arg1=true{current view, else template initial view} ar2=true=Projected coord, else lat/lon
        if ( this._mapObject.isBusy() == true )
        {
                this._mapObject.stop();
        }
        var extent = null;
        if ( this._appCoordMetrical == true  )
        {
            extent = this._mapObject.getMapExtent(true, true);
        } else {
            extent = this._mapObject.getMapExtent(true, false);
        }
        if (extent != null)
        {
            this._mapExtent.LLX = extent.MinX;
            this._mapExtent.LLY = extent.MinY;
            this._mapExtent.URX = extent.MaxX;
            this._mapExtent.URY = extent.MaxY;
        }
    },
    // ******************************************************************
    // Internal utility functions
    // *****************************************************************
    
    //
    //Calculate length in device coordinates to meter distance
    //
    distanceDeviceToMeter: function( i_deviceLength )
    {
        var height_meter = this._mapObject.getHeight("m"); //Get the height og the map in meter
        var height_dev = this._mapContainer.getClientHeight(); //Get the height of the map in device coordinates
        
        var meterPrPixel = height_meter / height_dev;
        var meterDistance = i_deviceLength * meterPrPixel;
        
        return meterDistance;
    },
    
    addXmlNode: function(key, value)
    {
        var xml_tag = "<"+key+">"+value +'</'+key+'>';
        return xml_tag;
    }
    
    
}
MapApiClient.MapApiMG.registerClass('MapApiClient.MapApiMG', MapApiClient.MapApi);

