﻿// JScript File

///
/// Container for Map Layer definistions
/// keeps status of all map layers (Active/Visible etc)
///
MapApiClient.MapLayerMngr = function( ) 
{
    var _bIsInitialized = false;//Flagg is initialized
    var _layerConfig = null;    //Config object from server
    var _moduleLayers = null;   //DataRequest objects 
    var _currModule  = 0;       //Current active module
    var _systypeList = null;    // List of active systypes, no default
    var _statusList  = null;    // List of active status,
    var _serviceList = null;    // List of active service layers SPEECH, GPRS, 3GDATA etc
    var _qualityList = null;    // List of active quality layers INDOOR, OUTDOOR etc
    var _severityList= null;    // List of active severity layers: 1,2,3 or OUT,DISTURBANCE etc
    var _timeLevelList=null;    // List of active time leveld: HISTORY, CURRENT, FUTURE
    var _historyFilter=null;    // Global history filter syntax: startdDate|endDate
    var _mncFilter   = null;    // Mobile Newtork Code
    var _mccFilter   = null;    // Mobile Colour Code
    var _networkFilter=null;    // NetworkFilter (used for subnet/logical net when more operators chare one net)
    var _mapLocation = null;    // Loaction of map: MapRect and MapScale etc
    var _plotOverWaterVisibility = false; //Flag true=water is always plotted on top
    var _symbolLabelVisibility = false; //Flag turn symbol labels on/off
    var _activeThemeList = null;


    // Initialization method
    this.initialize = function(i_layerConfig) 
    {
        _bIsInitialized = true;
        
        //Config sent from server
        _layerConfig = i_layerConfig;
        
        if ( _layerConfig == null){
            return;
        }
        
        //Create Array of modules
        _moduleLayers = new Array();

        //Create array of layerThemes, used as temporary container for each groupLegend
        _activeThemeList = new Array();

        //Traverse the modules
        for(var mIdx=0; mIdx<_layerConfig.ModuleLayers.length; mIdx++){
            //Allocate space for a list of layer groups
            _moduleLayers[mIdx] = new CV.mBOSS.DAL.LayerDataRequest();
            
            //Create filter object
            _moduleLayers[mIdx].DataFilter = new CV.mBOSS.DAL.QueryFilter();
            //Assign system list
            _moduleLayers[mIdx].DataFilter.SystypeFilter  = _systypeList;
            
            //Add layer group transparency
            _moduleLayers[mIdx].AreaGroupTransparency = _layerConfig.ModuleLayers[mIdx].AreaGroupTransparency;
            
            //Create an LayerGroup list
            _moduleLayers[mIdx].LayerGroups = new Array();
            
            var numGroups = _layerConfig.ModuleLayers[mIdx].LayerGroups.length;
            for(var groupIdx=0; groupIdx < numGroups; groupIdx++){
                //Assign the layer groups from (xml) config to the (map)request object
                _moduleLayers[mIdx].LayerGroups[groupIdx] = _layerConfig.ModuleLayers[mIdx].LayerGroups[groupIdx];
            }
         }
 
    }

    ///
    /// Property Accsess methods
    ///
    this.isInitialized = function()
    {
        return _bIsInitialized;
    }
    
    
    this.setSystype = function( i_systypeArr)
    {
        _systypeList="";
        
        for (var i=0; i<i_systypeArr.length; i++){
            if ( _systypeList.length > 0){
                _systypeList += ',';
            }
            _systypeList += i_systypeArr[i];
        }
    }
    this.getSystype = function()
    {
        return _systypeList;
    }
    this.setStatus = function( i_status )
    {
        _statusList = "";
        for (var i=0; i<i_status.length; i++){
            if ( _statusList.length > 0){
                _statusList += ',';
            }
            _statusList += i_status[i];
        }
    }
    this.getStatus = function()
    {
        return _statusList;
    }
    this.setService = function( i_service )
    {
        if ( i_service == null){
            i_service = null;
            return;
        }
        _serviceList = "";
        for (var i=0; i<i_service.length; i++){
            if ( _serviceList.length > 0){
                _serviceList += ',';
            }
            _serviceList += i_service[i];
        }
    }
    this.getService = function()
    {
        return _serviceList;
    }
    
    this.setQuality = function( i_quality )
    {
        if ( i_quality == null){
            _qualityList = null;
            return;
        }
        _qualityList = "";
        for (var i=0; i<i_quality.length; i++){
            if ( _qualityList.length > 0){
                _qualityList += ',';
            }
            _qualityList += i_quality[i];
        }
    }
    this.getQuality = function()
    {
        return _qualityList;
    }
    
    this.setSeverity = function( i_severity)
    {
        if ( i_severity == null ){
            _severityList = null;
            return;
        }
        _severityList = "";
        for (var i=0; i<i_severity.length; i++){
            if ( _severityList.length > 0){
                _severityList += ',';
            }
            _severityList += i_severity[i];
        }
    }
    this.getSeverity = function()
    {
        return _severityList;
    }
    
    this.setTimeLevel = function( i_timeLevel)
    {
        if ( i_timeLevel == null ){
            _timeLevelList = null;
            return;
        }
        _timeLevelList = "";
        for (var i=0; i<i_timeLevel.length; i++){
            if ( _timeLevelList.length > 0){
                _timeLevelList += ',';
            }
            _timeLevelList += i_timeLevel[i];
        }
    }
    this.getTimeLevel = function()
    {
        return _timeLevelList;
    }
    
    this.setHistoryFilter = function( i_historyFilter)
    {
        if ( i_historyFilter == null ){
            _historyFilter = null;
            return;
        }
        _historyFilter = i_historyFilter;
        
    }
    this.getHistoryFilter= function()
    {
        return _historyFilter;
    }
    
    this.setNetworkFilter = function (i_filterType, i_filter)
    {
        var newFilter = null;
        if ( i_filter != null && i_filter.length > 0){
            newFilter = "";
            for (var i=0; i<i_filter.length; i++){
                 if ( newFilter.length > 0){
                    newFilter += ',';
                 }
                newFilter += i_filter[i];
            }
       }
       switch (i_filterType.toLowerCase()){
            case 'mcc':
                _mccFilter = newFilter;
            break;
            case 'mnc':
                _mncFilter = newFilter;
            break;
            case 'networkid':
                _networkFilter = newFilter;
            break;
        }
    }
    
    this.setMapLocation = function(i_mapLocation)
    {
        _mapLocation = i_mapLocation;
    }
    
    this.getModuleIdx = function()
    {
        return _currModule;
    }
    this.getModuleName = function()
    {
        if ( _layerConfig != null ){
            return _layerConfig.ModuleLayers[_currModule].ClassName
        }
        return null;
    }
    this.getModuleList = function()
    {
        if ( _layerConfig != null ){
            return _layerConfig.ModuleLayers;
        }
        return null;
    }
    
    //Get the current map scale e.h 50000 is 1:50k scale
    this.getMapScale = function()
    {
        if (_mapLocation != null)
        {
            return _mapLocation.MapScale;
        }
        return 0;
    }
    //Return the map width in meter
    this.getMapWidthMeter = function()
    {
        if (_mapLocation != null)
        {
            return _mapLocation.MapWidthMeter;
        }
        return 0;
    }
    // Return the Map rectangle in world coordinates
    this.getMapRect = function()
    {
        if (_mapLocation != null)
        {
            return _mapLocation.WorldRect;
        }
        return null;
    }
    ///
    ///
    ///
    this.setModule = function(i_module)
    {
        //debugger
        for(var idx=0; idx<_layerConfig.ModuleLayers.length; idx++){
            if(_layerConfig.ModuleLayers[idx].ClassName == i_module){
                _currModule = idx;
            }
        }
    }
    
    this.getSymbolLabelVisibility = function()
    {
        return _symbolLabelVisibility;
    }
    
    this.setSymbolLabelVisibility = function( bVisibility)
    {
        _symbolLabelVisibility = bVisibility;
    }
    
    this.getPlotOverWaterVisibility = function()
    {
        return _plotOverWaterVisibility;
    }
    
    this.setPlotOverWaterVisibility = function( bVisibility)
    {
        _plotOverWaterVisibility = bVisibility;
    }
    
    this.getPlotOverWaterMarks = function()
    {
        if ( _layerConfig != null){
            if ( _plotOverWaterVisibility == false ){
                return _layerConfig.Settings.mgWaterMarkAbove;
            } else {
                return _layerConfig.Settings.mgWaterMarkBelow;
            }
        } 
        return null;
    }
    
    this.getMouseInfoInMapNavigationModes = function()
    {
        if ( _layerConfig != null){
           return _layerConfig.Settings.bMouseInfoInMapNavigationModes;
        } 
        return false;
    }
    
    this.getMapContextMenuEnabled = function()
    {
        if ( _layerConfig != null){
            return _layerConfig.Settings.bMapContextMenuEnabled;
        }
        return false;
    }
    this.getMapAjaxTooltipEnabled = function()
    {
         if ( _layerConfig != null){
            return _layerConfig.Settings.bMapAjaxTooltipEnabled;
        }
        return false;
    }
    
    this.getMapSelectionEnabled= function()
    {
        if ( _layerConfig != null){
            return _layerConfig.Settings.bMapSelectionEnabled;
        }
        return false;
    }
		
    

    
    this.setLayerStatus = function(i_layerGroup, i_status) 
    {
        i_layerGroup.Property.Active = i_status;
    }
    /// *********************************************************
    ///  Functional Methods
    /// *********************************************************
    
    ///
    ///Search The filterMap for the provided filter type, return tke LayerGroupList
    ///
    this.getLayerGroupsForFilterType = function(i_filterId)
    {
        var module = _layerConfig.ModuleLayers[_currModule];
        if ( module.FilterMap != null )
        {
            var numMappings = module.FilterMap.length;
            for(var i=0; i<numMappings; i++)
            {
                if ( module.FilterMap[i].FilterId.toUpperCase() == i_filterId.toUpperCase())
                {
                    //return _layerConfig.ModuleLayers[_currModule].FilterMap[i].LayerGroupList;
                    return module.FilterMap[i];
                }
            }
        }
        return null;
    }
    
    //
    // Return the configured list of layerGroups for the current module
    //
    this.getLayersRequest = function( bGetActiveLayers ) 
    {
        if ( _moduleLayers != null )
        {
            //debugger
            //Assign current Systype filter
            var currModule = _moduleLayers[_currModule];
             currModule.DataFilter.SystypeFilter  = _systypeList;
             currModule.DataFilter.StatusFilter   = _statusList;
             currModule.DataFilter.ServiceFilter  = _serviceList;
             currModule.DataFilter.QualityFilter  = _qualityList;
             currModule.DataFilter.SeverityFilter = _severityList;
             currModule.DataFilter.TimeLevelFilter= _timeLevelList;
             currModule.DataFilter.HistoryFilter  = _historyFilter;
             currModule.DataFilter.MccFilter      = _mccFilter;
             currModule.DataFilter.MncFilter      = _mncFilter;
             currModule.DataFilter.NetworkFilter  = _networkFilter;
             
             //register current module:
             currModule.ModuleId = this.getModuleName();
             if ( bGetActiveLayers == undefined || bGetActiveLayers == true ){
                var activeLayerArr = this.getListOfActiveLayerGroups();
                currModule.ActiveLayerGroupList = activeLayerArr[0];
                currModule.ActiveDataLayerGroupList = activeLayerArr[1];
             }
             
             currModule.GroupFilter = this.getLayerGroupFilter();
             
            return currModule;
        }
        return null;
    }
    
    ///
    /// Return a list of all active layerGroups which needs dynamic legend
    ///
    this.getDynamicLegendGroups = function()
    {
        var layerList = null;
        if ( _moduleLayers != null )
        {
            // Traverse the groups
            var numGroups = _moduleLayers[_currModule].LayerGroups.length;
            for(var grpIdx=0; grpIdx<numGroups; grpIdx++)
            {
                var layerGroup = _moduleLayers[_currModule].LayerGroups[grpIdx];
                if ( layerGroup.Property.Active == true && layerGroup.Property.bDynamicLegend == true){
                    if ( layerList == null){
                        layerList = layerGroup.LayerGroupId;
                    } else {
                        layerList += '|' + layerGroup.LayerGroupId;
                    }
                }
            }
        }
        return layerList;
    }
    
    //
    // Create lists of active LayerGroups and active dataLayers
    // Return array[2]  [0] = Active Layer Groups, [1]=Active data Layers
    this.getListOfActiveLayerGroups = function()
    {
        var layerList = null;
        var dataLayerList = null;
        if ( _moduleLayers != null )
        {
            // Traverse the groups
            var numGroups = _moduleLayers[_currModule].LayerGroups.length;
            for(var grpIdx=0; grpIdx<numGroups; grpIdx++)
            {
                var layerGroup = _moduleLayers[_currModule].LayerGroups[grpIdx];
                if ( layerGroup.Property.Active == true ){
                    if ( layerList == null){
                        layerList = layerGroup.LayerGroupId;
                    } else {
                        layerList += '|' + layerGroup.LayerGroupId;
                    }
                    //Check if this active layer has a dataLayer
                    if ( layerGroup.DataLayerId && layerGroup.DataLayerId != null ){
                        if ( dataLayerList == null){
                            dataLayerList = layerGroup.DataLayerId;
                        } else {
                            dataLayerList += '|' + layerGroup.DataLayerId;
                        }
                    }
                }
            }
        }
        var listArray = new Array(2);
        listArray[0] = layerList;
        listArray[1] = dataLayerList;
        return listArray;
    }
    this.getLayerGroupFilter = function()
    {
        var FilterList = null;
        var numFilters=0;
        if ( _moduleLayers != null )
        {
            // Traverse the groups
            var numGroups = _moduleLayers[_currModule].LayerGroups.length;
            for(var grpIdx=0; grpIdx<numGroups; grpIdx++)
            {
                var layerGroup = _moduleLayers[_currModule].LayerGroups[grpIdx];
                //Check if layer is active and has a filter
                if ( layerGroup.Property.Active == true ){
                    var bFilter   = (layerGroup.LayerFilter && layerGroup.LayerFilter.bFilterActive == true); 
                    var bDynScale =  layerGroup.DynamicMapScale != null;
                    if (  bFilter == true || bDynScale == true ){
                        if ( FilterList == null ){
                            FilterList = new Array();
                        }
                        FilterList[numFilters] = new CV.mBOSS.DAL.LayerGroupFilter();
                        FilterList[numFilters].LayerFilter         = layerGroup.LayerFilter;
                        FilterList[numFilters].SetDataFilterSource = layerGroup.SetDataFilterSource;
                        FilterList[numFilters].FilterMethod        = layerGroup.FilterMethod;
                        FilterList[numFilters].DynamicMapScale     = layerGroup.DynamicMapScale;
                        FilterList[numFilters].LayerGroupId        = layerGroup.LayerGroupId;
                        numFilters++;
                    }
                }
            }
         }
         return FilterList;
    }
    //
    this.getLayerGroupNeFilters = function( filterIds )
    {
        if ( _layerConfig == null ){
            return null;
        }
        var module = _layerConfig.ModuleLayers[_currModule];
        var retFilterList = new Array;
        //Traverse all filterMaps and extract filter
        var bReadAll = (filterIds == null || filterIds == undefined);
        var numMappings = module.FilterMap.length;
        var filterMap = null
        for(var i=0; i<numMappings; i++) {
            //Check if this filter is requested
            filterMap = module.FilterMap[i];
            if (  (bReadAll == true || filterIds.match(filterMap.FilterId)) && filterMap.LayerGroupList.length > 0 ){
                
                //Then read the filter value for the first group(same for all)
                var layerGroup = this.getLayerGroup(filterMap.LayerGroupList[0]);
                if ( layerGroup.LayerFilter != null && layerGroup.LayerFilter.NeFilters != null ){
                    //Find this filter
                    for(f=0; f<layerGroup.LayerFilter.NeFilters.length; f++){
                        var neFilter = layerGroup.LayerFilter.NeFilters[f];
                        if ( neFilter.NeFilterType ==  filterMap.FilterType &&
                             neFilter.bFilterActive == true && neFilter.NeIdFilter != null )
                        {
                            retFilterList[retFilterList.length] = {filterId:filterMap.FilterId ,
                                                                   filterType:filterMap.FilterType, 
                                                                   filterMethod:layerGroup.FilterMethod,
                                                                   filterData:neFilter.NeIdFilter};
                            break;//found what we were looking for, we break iteration   
                        }
                    }
                }
            }
        }
        return retFilterList.length==0 ? null : retFilterList;
    }
    
    this.setLayerGroupVisibility = function( i_layerGroupId, i_layerVisible, i_module)
    {
        // If i_Module is set, set state for this module
        var _module = _currModule;
        if (i_module)
        {
            for(var idx=0; idx<_layerConfig.ModuleLayers.length; idx++){
                if(_layerConfig.ModuleLayers[idx].ClassName == i_module){
                    _module = idx;
                }
            }
        }
        //Search for the Layer and set status
        if ( _moduleLayers != null )
        {
            // Traverse the groups
            var numGroups = _moduleLayers[_module].LayerGroups.length;
            for(var grpIdx=0; grpIdx<numGroups; grpIdx++)
            {
                var layerGrpId = _moduleLayers[_module].LayerGroups[grpIdx].LayerGroupId;
                if(  layerGrpId == i_layerGroupId)
                {
                    //Set layer status for this group
                    _moduleLayers[_module].LayerGroups[grpIdx].Property.Active = i_layerVisible;
                    var state = i_layerVisible ? "visible" : "hidden";
                    Sys.Debug.trace("Setting layer group '" + i_layerGroupId + "' " + state);
                    break; //break out of iteration
                }
            }
        }
    }
    //
    // Scan through the layerFilters and check if any filters active
    this.setLayerGroupFilterStatus = function( i_layerGroupObj )
    { 
        if ( i_layerGroupObj == null || i_layerGroupObj.LayerFilter == null){
            return;
        }
        var layerFilter = i_layerGroupObj.LayerFilter;
        
        //NE filters
        if ( layerFilter.NeFilters != null )
        {
            var numNeFilters = layerFilter.NeFilters.length;
            var neFilters = layerFilter.NeFilters;
            for(var i=0; i<numNeFilters; i++){
                if (  neFilters[i].bFilterActive  == true ){
                    layerFilter.bFilterActive = true;
                    return;
                }
            }
        }
        //Column filters
        if( layerFilter.ColumnFilters != null )
        {
            var numColFilters = layerFilter.ColumnFilters.length;
            var colFilters = layerFilter.ColumnFilters;
            for(var i=0; i<numColFilters; i++){
                if (  colFilters[i].bFilterActive  == true ){
                    layerFilter.bFilterActive = true;
                    return;
                }
            }
        }
        //Kpi Filter
        if( layerFilter.KpiReport != null )
        {
            if (  layerFilter.KpiReport.bFilterActive  == true ){
                layerFilter.bFilterActive = true;
                return;
            }
        }
        
        //If here, then no filter
        layerFilter.bFilterActive = false;
    }
    
    this.setLayerGroupKpiFilter = function(i_layerGroupId, i_kpiReport )
    {
        //Search for the Layer and set filter
        //debugger
        if ( _moduleLayers != null )
        {
            // Traverse the groups, and find the ID
            var numGroups = _moduleLayers[_currModule].LayerGroups.length;
            var grpIdx=-1;
            if ( numGroups > 0 ){
                var module = _moduleLayers[_currModule];
                var i=0;
                do {
                    if ( i_layerGroupId == module.LayerGroups[i].LayerGroupId ){
                        grpIdx = i;
                        break;
                    }
                    i++;
                } while (i<numGroups)
            }
            if ( grpIdx > -1 ){
                var groupLayer = _moduleLayers[_currModule].LayerGroups[grpIdx];
                if ( i_kpiReport == null ){
                    groupLayer.LayerFilter.KpiReport = null;
                } else {
                    if ( ! groupLayer.LayerFilter.KpiReport ){
                        groupLayer.LayerFilter.KpiReport= new CV.mBOSS.DAL.KpiReport();
                    }
                    var kpiReport = groupLayer.LayerFilter.KpiReport;
                    this.copyKpiReport(kpiReport, i_kpiReport);
                    kpiReport.bFilterActive = true;
                }
                this.setLayerGroupFilterStatus( groupLayer );
                return groupLayer;
            }
        }
        return null;
    }
    
    ///
    /// Copying the KpiReport object from Performix.js to the C# class KpiReport
    ///
    this.copyKpiReport = function( o_kpiReport, i_kpiReport)
    {
        if ( o_kpiReport && i_kpiReport){
            o_kpiReport.Kpi     = i_kpiReport.Kpi;
            o_kpiReport.Period  = i_kpiReport.Period;
            o_kpiReport.Date    = i_kpiReport.Date;
            if ( i_kpiReport.TrxType ){
                o_kpiReport.TrxType = i_kpiReport.TrxType.join(',');
            } else {
                o_kpiReport.TrxType = null;
            }
            if ( i_kpiReport.KpiFilter ){
                if ( ! o_kpiReport.KpiFilter ){
                    o_kpiReport.KpiFilter        = new CV.mBOSS.DAL.KpiFilter();
                }
                o_kpiReport.KpiFilter.Id     = i_kpiReport.KpiFilter.id;
                o_kpiReport.KpiFilter.System = i_kpiReport.KpiFilter.system;
                o_kpiReport.KpiFilter.Name   = i_kpiReport.KpiFilter.name;
                o_kpiReport.KpiFilter.Filters = new Array();
                var filters = o_kpiReport.KpiFilter.Filters;
                for(var f=0; f<i_kpiReport.KpiFilter.filters.length; f++){
                    filters[f] = new CV.mBOSS.DAL.KpiFilterItem();
                    filters[f].Kpi = i_kpiReport.KpiFilter.filters[f].kpi;
                    filters[f].Operator = i_kpiReport.KpiFilter.filters[f].operator;
                    filters[f].MaxValue = i_kpiReport.KpiFilter.filters[f].maxValue;
                    filters[f].MinValue = i_kpiReport.KpiFilter.filters[f].minValue;
                }
            } else {
                o_kpiReport.KpiFilter = null;
            }
        }
    }
    
    ///
    /// Purpose: Find the layerGroup and set the layer column filter
    /// args:   i_layerGroupId -   Group name for which to set filter
    ///         i_filterType   -   Type or name of filter (can be more than one set of colFilters)
    ///         i_filterList   -   String list of format: Column|Operator|Data
    this.setLayerGroupColumnFilter = function(i_layerGroupId, i_filterType, i_columnFilterList )
    {
        //Search for the Layer and set filter
        //debugger
        if ( _moduleLayers != null )
        {
            // Traverse the groups, and find the ID
            var numGroups = _moduleLayers[_currModule].LayerGroups.length;
            var grpIdx=-1;
            if ( numGroups > 0 ){
                var module = _moduleLayers[_currModule];
                var i=0;
                do {
                    if ( i_layerGroupId == module.LayerGroups[i].LayerGroupId ){
                        grpIdx = i;
                        break;
                    }
                    i++;
                } while (i<numGroups)
            }
            if ( grpIdx > -1 ){
                var groupLayer = _moduleLayers[_currModule].LayerGroups[grpIdx];
                if ( groupLayer.LayerFilter.ColumnFilters == null ){
                    groupLayer.LayerFilter.ColumnFilters = new Array();
                }
                var colFilterList = groupLayer.LayerFilter.ColumnFilters;
                var colFilter = null;
                //First search to find the correct filter by name
                var filterName = i_filterType != null ? i_filterType : "NA";
                for(var idx=0; idx<colFilterList.length; idx++){
                    if ( colFilterList[idx].FilterType == filterName){
                        colFilter = colFilterList[idx];
                        break;
                    }
                }
                
                if ( i_columnFilterList == null ){
                    //Clear call 
                    if ( colFilter != null)
                    {
                        colFilter.Filter = null;
                        colFilter.bFilterActive = false;
                    }
                } else {
                    //Check if filter already exists, if not allocate filter
                    if( colFilter== null)
                    {
                        colFilter  = new CV.mBOSS.DAL.ColumnFilter();
                        colFilterList[colFilterList.length] = colFilter;
                    } 
                    //Then apply filter data
                    colFilter.Filter = i_columnFilterList;
                    colFilter.FilterType = filterName;
                    colFilter.bFilterActive = true;
                }
                this.setLayerGroupFilterStatus( groupLayer );
                return groupLayer;
            }
        }
        return null;
    }
    
    ///
    /// Create a QueryFilter object
    /// configured with a NeFilter with type and data provided
    ///
    this.createNeQueryFilter = function(i_filterType, i_filterData)
    {
            
        var queryFilter  =  new CV.mBOSS.DAL.QueryFilter();
        
        queryFilter.NeFilters = new Array();
        
        var neFilter  = new CV.mBOSS.DAL.NeFilter();
        //Then apply filter data
        neFilter.NeFilterType = i_filterType;
        neFilter.NeIdFilter = i_filterData;
        neFilter.bFilterActive = true;
        queryFilter.NeFilters[queryFilter.NeFilters.length] = neFilter;
        
        return queryFilter;
    }
    ///
    /// Purpose: Find the layerGroup and set the layer filter
    /// args:   i_layerGroup  -   Group name for which to set filter
    ///         i_filterType  -   CELL,SITE,BSC, etc
    ///         i_filterMethod -  Exclude, include
    ///         i_filterData  -   Filter itself to be used according to filterType
    this.setLayerGroupFilter = function(i_layerGroup, i_filterType, i_filerMethod, i_filterData)
    {
        //Search for the Layer and set filter
        //debugger
        if ( _moduleLayers != null )
        {
            // Traverse the groups
            var numGroups = _moduleLayers[_currModule].LayerGroups.length;
            for(var grpIdx=0; grpIdx<numGroups; grpIdx++)
            {
                var layerGroup = _moduleLayers[_currModule].LayerGroups[grpIdx];
                var layerGrpId = layerGroup.LayerGroupId;
                if(  layerGrpId == i_layerGroup)
                {
                    
                    if ( layerGroup.LayerFilter.NeFilters == null ){
                        layerGroup.LayerFilter.NeFilters = new Array();
                    }
                    var neFilterList = layerGroup.LayerFilter.NeFilters;
                    var neFilter = null;
                    //First we look up the filter of type i_filterType
                    for(var idx=0; idx<neFilterList.length; idx++){
                        if ( neFilterList[idx].NeFilterType == i_filterType){
                            neFilter = neFilterList[idx];
                            break;
                        }
                    }
                
                    if ( i_filterData == null ){
                        //Clear call 
                        if ( neFilter != null)
                        {
                            //neFilter.NeFilterType = null;
                            neFilter.NeIdFilter = null;
                            neFilter.bFilterActive = false;
                            layerGroup.SetDataFilterSource = null;
                        }
                    } else {
                        //Check if filter already exists, if not allocate filter
                        
                        var queryFilter = null;
                        if( neFilter == null)
                        {
                            neFilter  = new CV.mBOSS.DAL.NeFilter();
                            neFilterList[neFilterList.length] = neFilter;
                        } 
                        //Then apply filter data
                        neFilter.NeFilterType = i_filterType;
                        
               
                        if ( i_filterData instanceof Array ){ //Array.isInstanceOf(i_filterData);
                            neFilter.NeObjFilter = i_filterData;
                        } else {
                            neFilter.NeIdFilter = i_filterData;
                        }
                        neFilter.bFilterActive = true;
                        //For filters wee need the the property LayerType defined
                        //Else we dont know how ti implement the profived filter type
                        if ( layerGroup.LayerType == null )
                        {
                            alert("the Layer property: LayerType not configured for LayerGroup:"+layerGrpId);
                            break;
                        }
                        //Set Layer filter properties
                        layerGroup.FilterMethod = i_filerMethod;
                        //Dependent of layer type, set filter source type
                        //E.g for a SITE layer a SITE filter is straight forward, but CELL filter needs a query etc.
                        if ( layerGroup.LayerType == i_filterType.toUpperCase() )
                        {
                            layerGroup.SetDataFilterSource = "LAYER_FILTER";
                        } 
                        else 
                        {
                           layerGroup.SetDataFilterSource = "DATA_LAYER";
                        }
                    }
                    //Found Group and we have applied filter, then we return the group
                    this.setLayerGroupFilterStatus( layerGroup );
                    return layerGroup;
                }
            }
        }
        return null;
    }
    
    this.setLayerGroupDynamicMapScale = function(i_layerGroupId, i_maxScale, i_minScale)
    {
        if ( i_layerGroupId && _moduleLayers != null ){
            var numGroups = _moduleLayers[_currModule].LayerGroups.length;
            var grpIdx=-1;
            if ( numGroups > 0 ){
                var module = _moduleLayers[_currModule];
                var i=0;
                do {
                    if ( i_layerGroupId == module.LayerGroups[i].LayerGroupId ){
                        grpIdx = i;
                        break;
                    }
                    i++;
                } while (i<numGroups)
            }
            if ( grpIdx > -1 ){
                var layerGroup = _moduleLayers[_currModule].LayerGroups[grpIdx];
                if ( layerGroup.DynamicMapScale == null){
                    layerGroup.DynamicMapScale = new CV.mBOSS.DAL.MapLayerScale();
                } 
                if ( i_maxScale != null ){
                    layerGroup.DynamicMapScale.MaxScale = i_maxScale;
                }
                if ( i_minScale != null ){
                    layerGroup.DynamicMapScale.MinScale = i_minScale;
                }
                return layerGroup;
            }
        }
        return null;
    }
    
    this.clearLayerGroupDynamicMapScale = function(i_layerGroupId)
    {
         this.setLayerGroupDynamicMapScale(i_layerGroupId, -1, -1);
    }
    
    // Search the list for the given group (i_layerGroup)
    // Return the whole group structure. e.g properties and list of layers
    this.getLayerGroup= function( i_layerGroup )
    {
        //Search for the Layer and set status
        if ( _moduleLayers != null && i_layerGroup != null)
        {
            // Traverse the groups
            var numGroups = _moduleLayers[_currModule].LayerGroups.length;
            for(var grpIdx=0; grpIdx<numGroups; grpIdx++)
            {
                var layerGrpId = _moduleLayers[_currModule].LayerGroups[grpIdx].LayerGroupId;
                if(  layerGrpId == i_layerGroup)
                {
                    //We found it, return the whole group
                    return _moduleLayers[_currModule].LayerGroups[grpIdx];
                }
            }
        }
        return null;
    }
    
    //
    // Search for the LayerGroup with the name "layerGroup" and return array of layers
    //
    this.getLayersForGroup = function( layerGroup )
    {
        if ( _layerConfig != null ){
            var numGroups = _layerConfig.LayerGroups.length;
            for ( var i=0; i<numGroups; i++){
                if ( _layerConfig.LayerGroups[i].LayerGroup == layerGroup ){
                    return _layerConfig.LayerGroups[i].Layers;           
                }
            }
        
        }
        return null;
    }
    //
    //Serach for the Layer with id = i_layerId and return the group
    this.getLayerGroupForLayer = function( i_layerId )
    {
         if ( _moduleLayers != null  ){
            var numGroups = _moduleLayers[_currModule].LayerGroups.length;
            for ( var i=0; i<numGroups; i++){
                var layerGroup = _moduleLayers[_currModule].LayerGroups[i];
                var numLayers = layerGroup.Layers.length;
                for(var layerIdx=0; layerIdx<numLayers; layerIdx++){
                    var layer = layerGroup.Layers[layerIdx];
                    if ( layer.LayerId == i_layerId ){
                        return  layerGroup;
                    }
                }
            }
        }
        return null;
    }
    // 
    // Return the whole list of groups
    this.getLayerGroupList = function(  )
    {
        if ( _moduleLayers != null )
        {
            return  _moduleLayers[_currModule].LayerGroups;
        }
        return null;
    }
   
    ///
    /// Find the Layer group and check if this is  a datapregen layer (Supposed to pregenerate data)
    /// If so the layerGroupIdx is returned else null
    ///
    this.getLayerGroupDataPregenStatus = function( i_layerGroup )
    {
        //Search for the Layer and set status
        if ( _moduleLayers != null )
        {
            // Traverse the groups
            var numGroups = _moduleLayers[_currModule].LayerGroups.length;
            for(var grpIdx=0; grpIdx<numGroups; grpIdx++)
            {
                var layerGrpId = _moduleLayers[_currModule].LayerGroups[grpIdx].LayerGroupId;
                if(  layerGrpId == i_layerGroup)
                {
                     //Get layer pregen status
                    if ( _moduleLayers[_currModule].LayerGroups[grpIdx].PreGenData == true ){
                        return grpIdx;
                    } else {
                        return null;
                    }
                }
            }
        }
        return null;
    }
    
    this.getLayerGroupVisibility = function( i_layerGroup )
    {
        //Search for the Layer and set status
        if ( _moduleLayers != null)
        { 
            
            //Traverse the layers
            var numGroups = _moduleLayers[_currModule].LayerGroups.length;
            for(var grpIdx=0; grpIdx<numGroups; grpIdx++)
            {
                var layerGrpId = _moduleLayers[_currModule].LayerGroups[grpIdx].LayerGroupId;
                if(  layerGrpId == i_layerGroup)
                {
                    //Get layer status for this group
                    return _moduleLayers[_currModule].LayerGroups[grpIdx].Property.Active;
                }
            }
        }
        return false;
    }
    this.getLayerGroupPotVisibility = function( i_layerGroup )
    {
        //debugger
        //Search for the Layer and set status
        if ( (_moduleLayers != null)   && (_mapLocation != null))
        { 
            //Traverse the layers
            var numGroups = _moduleLayers[_currModule].LayerGroups.length;
            for(var grpIdx=0; grpIdx<numGroups; grpIdx++)
            {
                
                var layerGroup = _moduleLayers[_currModule].LayerGroups[grpIdx];
                var layerGrpId = layerGroup.LayerGroupId;
                if(  layerGrpId == i_layerGroup)
                {
                    //Get layer status for this group
                    //Return true if at least one layer is potentially visible
                    var numLayers = layerGroup.Layers.length;
                    for(var layerIdx=0; layerIdx<numLayers; layerIdx++){
                        var layerMaxScale = layerGroup.Layers[layerIdx].MaxScale;
                        var layerMinScale = layerGroup.Layers[layerIdx].MinScale;
                        //Then we check possible layerGroup dynamic scale
                        if ( layerGroup.DynamicMapScale != null){
                            layerMaxScale = layerGroup.DynamicMapScale.MaxScale != -1 ? layerGroup.DynamicMapScale.MaxScale: layerMaxScale;
                            layerMinScale = layerGroup.DynamicMapScale.MinScale != -1 ? layerGroup.DynamicMapScale.MinScale: layerMinScale;
                        }
                        if( (_mapLocation.MapScale >= layerMinScale) && (_mapLocation.MapScale <= layerMaxScale)){
                            return true
                        }
                    }
                    //We didn't find it
                    return false;
                }
            }
        }
        return false;
    }
    
    this.getLegendData = function(i_mapDataMngr)
    {
        var legendArr = new Array();
        //debugger
        //Search for legend
        if ( (_moduleLayers != null)   && (_mapLocation != null))
        { 
            //Traverse the layers
            var numGroups = _moduleLayers[_currModule].LayerGroups.length;
            for(var grpIdx=0; grpIdx<numGroups; grpIdx++)
            {
                if(  _moduleLayers[_currModule].LayerGroups[grpIdx].Property.bLegend == true)
                {
                    var lg = _moduleLayers[_currModule].LayerGroups[grpIdx];
                
                    if ( lg.Property.Active == false){
                        continue;
                    }
                    if ( lg.Property.bDynamicLegend == true ){
                        this.getDynamicLegend(lg, i_mapDataMngr, legendArr);
                    } else {
                        this.getStaticLegend (lg, legendArr);
                    }
                }
            }
        }
        if (legendArr.length > 0){
            return legendArr;
        } else {
            return null;
        }
    }
    
    ///
    /// Called if bDynamicLegend==true
    /// Populate dynamic legend
    ///
    this.getDynamicLegend = function(i_layerGroup, i_mapDataMngr, i_legendArr)
    {
        if ( i_layerGroup != null && i_mapDataMngr != null && i_legendArr != null ){
            var groupData = i_mapDataMngr.getData();
            if ( groupData != null ){
                var legendItem;
                for(var i=0; i<groupData.LayerGroups.length; i++){
                    if ( i_layerGroup.LayerGroupId == groupData.LayerGroups[i].LayerGroupId){
                        if ( i_layerGroup.Property.FrendlyName != null ){
                            //Make the header first
                            legendItem = this.createLegendItem(null, i_layerGroup.Property.FrendlyName, 
                                                                i_layerGroup.Property.Hint, null, true);
                            if (legendItem != null && legendItem.length > 0)
                                i_legendArr[i_legendArr.length] = legendItem;
                            //Found it, then we traverse the Layers
                            var layerList = groupData.LayerGroups[i].LayerList;
                            for( var l=0;l<layerList.length; l++){
                                if ( layerList[l].LegendList != null ){
                                    if ( layerList[l].LayerSpec.FrendlyName > null ){
                                        legendItem = this.createLegendItem(null, layerList[l].LayerSpec.FrendlyName, 
                                                                            layerList[l].LayerSpec.Hint, null, false);
                                        if (legendItem != null && legendItem.length > 0)
                                            i_legendArr[i_legendArr.length] = legendItem;
                                                                                            
                                    }
                                    var legendList = layerList[l].LegendList;
                                    for( var legIdx=0; legIdx<legendList.length; legIdx++){
                                        legendItem = this.createLegendItem(legendList[legIdx].Color, legendList[ legIdx].Text, 
                                                                            null, null, false);
                                        if (legendItem != null && legendItem.length > 0)
                                            i_legendArr[i_legendArr.length] = legendItem;
                                    }
                                } 
                            }
                        }
                        return;
                    } //end if LayerGroupId
                
                } //Loop lg
            } //if groupData
        }
    }
    
    ///
    /// Get legend basen on Theme/Symbol settings for a layer
    ///
   this.getStaticLegend = function(lg, legendArr)
   {
        var groupTheme = lg.LayerTheme;
        //Clear list of active Themes for group
        _activeThemeList.length = 0;
        
        var numLayers = lg.Layers.length;
        var bGroupActive = false;
        for(var layerIdx=0; layerIdx<numLayers; layerIdx++){
            var layer = lg.Layers[layerIdx];
            if ( layer.bLegend == true && 
                 (layer.FrendlyName != null || layer.LayerTheme != null || groupTheme != null) &&
                 this.isLayerActive( layer, lg) == true){
                if ( bGroupActive == false ){
                    //If a frendly name exists add label
                    if ( lg.Property.FrendlyName ){
                        legendArr[legendArr.length] = this.createLegendItem(null, lg.Property.FrendlyName, lg.Property.Hint, null, true);
                    }
                    bGroupActive = true;
                }
                if ( layer.Symbol != null ){
                    if ( groupTheme == null ){
                        legendArr[legendArr.length] = this.createLegendItem(layer.Symbol.FillColor, layer.FrendlyName, layer.Hint, layer, false);
                    } else if (this.checkForUniqueTheme(_activeThemeList, layer.ThemeIdx)) {
                        var theme = lg.LayerTheme.Themes[layer.ThemeIdx];
                        legendArr[legendArr.length] = this.createLegendItem(theme.ThemeSymbol.FillColor, theme.FriendlyName, null, layer, false);
                    }
                } else if (layer.LayerTheme != null && this.checkForUniqueTheme(_activeThemeList, layer.LayerTheme.LayerThemeId)){
                    var numThemes = layer.LayerTheme.Themes.length;
                    for(var themeIdx=0; themeIdx<numThemes; themeIdx++){
                        var theme = layer.LayerTheme.Themes[themeIdx];
                        if ( theme.FriendlyName != null){
                            legendArr[legendArr.length] = this.createLegendItem(theme.ThemeSymbol.FillColor, theme.FriendlyName, theme.Hint, layer, false);
                        }
                    }
                }
            }
        }
    }
    
    this.checkForUniqueTheme= function(activeThemeList, themeId)
    {
        for(var i=0; i<activeThemeList.length; i++){
            if ( activeThemeList[i] == themeId){
                //Already in lust, dont add
                return false;
            }
        }
        activeThemeList[activeThemeList.length] = themeId;
        //Add legend
        return true;
    }
    
    this.createLegendItem = function(color, legendText, hintText, layer, bHeaderFlag)
    {
        if ( legendText != null){
            var legendItem = new Array(6);
            legendItem[0] = legendText;
            // Compute the hex color, splis the RGB color list
            // First split RGB color list
            if ( color != null ){
                if ( color.indexOf('#') == 0 ){
                    legendItem[1] = color;
                    //color.substr(1, 2)
                    var R=hex2Dec(color.substr(1, 2));
                    var G=hex2Dec(color.substr(3, 2));
                    var B=hex2Dec(color.substr(5, 2));
                    legendItem[2] = this.getContrastColorFromRGB( R, G, B );
                } else {
                    var rgbList = color.split(',');
                    legendItem[1] = this.getHexColorCodeFromRGB( rgbList[0], rgbList[1], rgbList[2] ); 
                    legendItem[2] = this.getContrastColorFromRGB( rgbList[0], rgbList[1], rgbList[2] ); 
                }
            } else {
                legendItem[1] = "white"; //color white as background
                legendItem[2] = "black"; //color wlack as background
            }
            legendItem[3] = hintText;
            if ( layer!=null && layer.LayerSrc == 0 && _moduleLayers[_currModule].AreaGroupTransparency ){
                //If LayerSrc==0 (Source File, we use Transparency if given)
                legendItem[4]=parseInt((_moduleLayers[_currModule].AreaGroupTransparency/255)*100); //Opacity
            } else {
                legendItem[4]=100; //Opacity
            }
            legendItem[5] = bHeaderFlag; //Header flag
            return legendItem;
        }
        return null;
    }
    ///
    /// Chack if the layer is active or not
    ///
    this.isLayerActive = function( i_layer, i_layerGroup )
    {
        if ( i_layer )
        {
            //Check GEO Limits
            if ( _mapLocation && i_layer.MinScale != -1 && i_layer.MaxScale != -1){
                if ( _mapLocation.MapScale < i_layer.MinScale || _mapLocation.MapScale >= i_layer.MaxScale)
                {
                    return false; //Outside GEO limits
                }
            }
            //Check Status
            if ( this.compareFilterItems(i_layer.LayerStatus, _statusList) == false ){
                return false;
            }
            //Check systype
//            if ( this.compareFilterItems(i_layer.Systypes, _systypeList) == false ){
//                return false;
//            }
            //Check services
//            if ( this.compareFilterItems(i_layer.Services, _serviceList) == false ){
//                return false;
//            }
            
            //Column filters
            if ( this.compareColumnFilter(i_layer.ColumnFilter, i_layerGroup.LayerFilter.ColumnFilters) == false ){
                return false;
            }
            //Check Somethinge else
            //Must be visible now!!!
            return true;
        }
        return false;
    }
    
    
    //**************************************
    // Internal Help function
    //**************************************
    this.compareFilterItems = function(i_layerFilter, i_globalFilter)
    {
        if ( i_layerFilter != null && i_layerFilter != "ignore" && i_layerFilter != "global" && i_globalFilter != null)
        {
            var arr = i_layerFilter.split(",");
            bContains = false;
            for(i=0; i<arr.length; i++){
                if ( i_globalFilter.match(arr[i]) != null) { bContains = true;}
            }
            if( bContains == false ){
                return false;
            }
        }
        return true;
    }
    
    this.compareColumnFilter = function(i_layerColumnFilter, i_appliedColumnFilters)
    {
        if ( i_layerColumnFilter != null && i_appliedColumnFilters != null ){
            for(var i=0; i<i_layerColumnFilter.Filter.length; i++){
                var layerFilter = i_layerColumnFilter.Filter[i].split('|');
                for(var f=0; f<i_appliedColumnFilters.length; f++){
                    var applFilterList = i_appliedColumnFilters[f].Filter;
                    for(var j=0; j<applFilterList.length; j++){
                        var appliedFilter = applFilterList[j].split('|');
                        //Check if the filters are of the same Column
                        if ( layerFilter[0] == appliedFilter[0] ){
                            //Then check if the filters match
                            if ( layerFilter[2] != appliedFilter[2] ) {
                                //Found a matching filter type, but filters differ
                                return false;
                            }
                        }
                    }
                }
            }
        }
        return true;
    }
    
    this.getContrastColorFromRGB = function(R,G,B, bDec)
    {
        var avgColor;
        if ( bDec == true ){
            avgColor = (R+G+B)/3;
        } else {
            avgColor =(parseInt(R)+parseInt(G)+parseInt(B))/3;
        }
        
        if (avgColor > 100){
            return "black";
        } else {
            return "white";
        }
    }
    //Convert and RGB string to Hex Notation x: 255,255,255 = #FFFFFF
    this.getHexColorCodeFromRGB = function(R,G,B)
    {
        return '#' + dec2Hex(R) + dec2Hex(G) + dec2Hex(B);
    }
    
    // convert a hex digit into decimal
    function deHex(aHexDigit)
    {
        return("0123456789ABCDEF".indexOf(aHexDigit))
    }
    //Convert a 2 digit hex (FF) to decimal
    function hex2Dec(hex)
    {
        return deHex(hex.substr(0,1))* 16 + deHex(hex.substr(1,1));
    }
    
    //Convert a decimal number to hex e.g 255 = FF
    function dec2Hex(n)
    {
        var hexString = "0123456789ABCDEF";
        return String(hexString.substr((n >> 4) & 0x0F,1)) + hexString.substr(n & 0x0F,1);
    }
    
   
}
MapApiClient.MapLayerMngr.registerClass('MapApiClient.MapLayerMngr', null, Sys.IDisposable);

