﻿// JScript File

///
/// Container for map overlay data (Lists of network objects etc)
///
MapApiClient.MapDataMngr = function( ) 
{
    var _layerGroups = null;
    var _neArray     = new Array();
    var _propArray   = new Array();
    var _returnArray = new Array(2);
    var _mapLabels = null;
    var _selectPolygon = new Shapes.Polygon();
    
    var _EnumObjectHitMode = null;
    var _bMouseOverEnabled = false;
    
    this.initialize = function()
    {
    
    }
    
    this.setData = function( i_newDataOverlay)
    {
        _layerGroups = i_newDataOverlay;
        //Resolve MouseOver status
        _bMouseOverEnabled = this.getMouseOverStatus();
    }
     
    this.getData = function()
    {
        return _layerGroups;
    }
    this.setHitMode = function( i_hitMode)
    {
        _EnumObjectHitMode = i_hitMode;
    }
    
    this.setMapLabelText = function(location, text, visibility)
    {
        if ( _mapLabels == null ){
            _mapLabels = new Array();
        }
        //Check if Label exists
        var foundIdx = -1;
        for(i=0; i<_mapLabels.length; i++){
            if ( _mapLabels[i].Location == location ){
                foundIdx = i;
                break;
            }
        }
        if ( foundIdx == -1){
            var newIdx = _mapLabels.length;
            _mapLabels[newIdx] = new CV.mBOSS.DAL.MapLabelItem();
            foundIdx = newIdx;
        }
        _mapLabels[foundIdx].Location = location;
        _mapLabels[foundIdx].Active = visibility;
        _mapLabels[foundIdx].Text = text;
    }
    
    this.getSelectPolygon = function()
    {
        return _selectPolygon;
    }
    
    this.setMapLabelVisibility = function(location, visibility)
    {
        if ( _mapLabels == null ){
            _mapLabels = new Array();
        }
        var locationList = location.split('|');
        for(ll=0;ll<locationList.length;ll++){
            var bFound = false;
            for(i=0; i<_mapLabels.length; i++){ 
                if ( _mapLabels[i].Location == locationList[ll] ){
                    _mapLabels[i].Active = visibility;
                    bFound = true;
                }
            }
            if ( bFound == false ){
                var newIdx = _mapLabels.length;
                _mapLabels[newIdx] = new CV.mBOSS.DAL.MapLabelItem();
                _mapLabels[newIdx].Location = locationList[ll];
                _mapLabels[newIdx].Active=visibility;
                _mapLabels[newIdx].Text = "";
            }
        }
    }
    this.getMapLabel = function ()
    {
        var mapLabelConfig = "";
        if ( _mapLabels != null ){
            for(i=0; i<_mapLabels.length; i++){
                if ( _mapLabels[i].Active == true ){
                    if ( mapLabelConfig.length > 0){
                        mapLabelConfig += ";"
                    }
                    mapLabelConfig += _mapLabels[i].Location +":"+_mapLabels[i].Text;
                }
            }
              return mapLabelConfig;
        }
        return null;
    }
    
    ///
    /// Search layerGroups and check if any layers has MouseOver set clas status
    this.getMouseOverStatus = function()
    {
        if ( _layerGroups == null ){
            return false;
        }
        for(var lg=0; lg<_layerGroups.length; lg++)
        {
           if(_layerGroups[lg].Property.Active == true && _layerGroups[lg].Property.bMouseOver == true ){
                return true;
           }
        }
        return false;     
    }
    
    ///
    /// Search for any item in location x,y and return tooltip of first item found
    ///
    this.findMapElementTooltip = function(x, y, bAjaxTooltip )
    {
        var retVal = null;
        if ( _layerGroups != null)
        {
            //debugger
            //Traverse the groups
            for(var lg=0; lg<_layerGroups.length; lg++)
            {
                var layerGroup = _layerGroups[lg];
                var bTooltip = (bAjaxTooltip==true)?layerGroup.Property.bAjaxTooltip : layerGroup.Property.bTooltip;
                if ( layerGroup.Property.Active == true && bTooltip == true ){
                    //Traverse the layers
                    var numLayers = layerGroup.LayerList.length;
                    for (var ll=0; ll<numLayers; ll++)
                    {
                        //Then all network elements in the layer
                        var numElements = layerGroup.LayerList[ll].Properties.length;
                        var layer = layerGroup.LayerList[ll];
                        //First only DB Layers, not FILE (polygon) layers
                        if ( layer.LayerSpec.LayerSrc != CV.mBOSS.DAL.LayerSpec_LAYER_SRC.DB_SRC_LAYER){

                            continue;
                        }
                        if ( layer.LayerSpec.bTooltip==true && layerGroup.Property.bAjaxTooltip == false ){
 
                            for(var ne=0; ne<numElements; ne++)
                            {
                                //Check if it's LayerTheme or LayerSymbol
                                var symbol = null;
                                if ( layer.LayerSpec.Symbol != null ){
                                    symbol = layer.LayerSpec.Symbol;
                                } else if (layer.LayerSpec.LayerTheme != null ) {
                                    var themeIdx = layer.Properties[ne].ThemeIdx;
                                    if ( themeIdx > -1 ){
                                        symbol = layer.LayerSpec.LayerTheme.Themes[themeIdx].ThemeSymbol;
                                    }
                                }
                                if ( symbol == null ){
                                    continue;
                                }
                                var bHit = this.mapElementHitDetect(x, y, layer.Properties[ne], symbol);
                                if ( bHit == true ){
                                    if ( layerGroup.Property.bCommonTooltip == true &&
                                         layer.TooltipList != null){
                                        var tt_idx = -1;
                                        if( layer.AreaElementList != null  ){
                                            tt_idx = parseInt(layer.AreaElementList[ne].TT);
                                        } else if ( layer.RelationList != null ){
                                            tt_idx = parseInt(layer.RelationList[ne].TT);
                                        } else if ( layer.ElementList != null && layer.ElementList.length > 0){
                                            tt_idx = parseInt(layer.ElementList[ne].TT);
                                        } 
                                        if ( tt_idx > -1 && tt_idx < layer.TooltipList.length){
                                            return layer.TooltipList[tt_idx];
                                        }
                                    } else {
                                        if( layer.AreaElementList != null  ){
                                            return layer.AreaElementList[ne].TT;
                                        } else if ( layer.RelationList != null ){
                                            return layer.RelationList[ne].TT;
                                        } else if ( layer.ElementList != null && layer.ElementList.length){
                                            return layer.ElementList[ne].TT;
                                        } 
                                    }
                                }
                            }
                        } else if ( bAjaxTooltip == true && layerGroup.Property.bAjaxTooltip == true){
                              if ( layer.bHasData == true ){
                                if ( retVal==null){
                                    retVal = layerGroup.LayerGroupId + ":"+layer.LayerSpec.LayerId; 
                                } else {
                                    retVal += ","+layer.LayerSpec.LayerId;
                                }
                            }
                        }
                    } // end traverse layers
                }// end traverse groups
            }// end if tooltip
        }
        return retVal;
    }
    ///
    /// Search for any item inside BoundingBox and return NE object list
    ///
    this.findMapElementsInArea = function(LLX, LLY, URX, URY)
    {
        var numElems = 0;
        var neX, neY;
      
        //Clear existing array
        _neArray.length = 0;
        _propArray.length = 0;
        
        if ( _layerGroups != null)
        {
            //debugger
            //Traverse the groups
            for(var lg=0; lg<_layerGroups.length; lg++)
            {
                var layerGroup = _layerGroups[lg];
                if ( layerGroup.Property.bSelectable == true && layerGroup.Property.bSelPolygon == false){
                    //Traverse the layers
                    var numLayers = layerGroup.LayerList.length;
                    for (var ll=0; ll<numLayers; ll++)
                    {
                        var layer = layerGroup.LayerList[ll];
                        if (layer.LayerSpec.bSelectable == false ){
                            continue;
                        }
                        var numElements = 0;
                        if ( layer.ElementList.length > 0 || layer.RelationList != null ){
                            numElements = layer.Properties.length;
                        }
                        for(var ne=0; ne<numElements; ne++)
                        {
                            var symbol = null;
                            if ( layer.LayerSpec.Symbol != null ){
                                symbol = layer.LayerSpec.Symbol;
                            } else if (layer.LayerSpec.LayerTheme != null ) {
                                var themeIdx = layer.Properties[ne].ThemeIdx;
                                if ( themeIdx > -1 ){
                                    symbol = layer.LayerSpec.LayerTheme.Themes[themeIdx].ThemeSymbol;
                                }
                            }
                            if ( symbol == null ){
                                continue;
                            }
                            var bHit = this.mapElementHitDetectArea(LLX, LLY, URX, URY, layer.Properties[ne], symbol);
                            if ( bHit == true)
                            {
                                //debugger
                                _neArray[numElems] = (layer.RelationList != null) ? layer.RelationList[ne] : layer.ElementList[ne];
                                if ( symbol.SymbolType != CV.mBOSS.DAL.SymbolDef_SYMBOL_TYPE.PIE )
                                    //|| symbol.SymbolType == CV.mBOSS.DAL.SymbolDef_SYMBOL_TYPE.RECTANGLE)
                                {
                                    _propArray[numElems] = layer.Properties[ne];
                                    //Add some outline info
                                    var selectProp = null;
                                    if ( _propArray[numElems].SelProp ){
                                        selectProp = _propArray[numElems].SelProp;
                                    } else {
                                        _propArray[numElems].SelProp = new CV.mBOSS.DAL.SelectProperties();
                                        selectProp = _propArray[numElems].SelProp;
                                    }
                                    selectProp.Size         = 2*symbol.RadiusPix;;
                                    selectProp.Shape        = symbol.SelectShape;
                                    selectProp.Color        = symbol.SelectColor;
                                    selectProp.ShadowColor  = symbol.SelectShadowColor;
                                } else {
                                    _propArray[numElems] = null;
                                }
                                numElems++;
                            }
                        }
                    } // end traverse layers
                }// end traverse groups
            }// end if tooltip
        }
        if ( _neArray.length == 0){
            return null;
        } else {
            _returnArray[0] = _neArray;
            _returnArray[1] = _propArray;
            return  _returnArray;   
        }
    }
    ///
    /// Search for any item in location x,y and return NE object list
    /// i_HitMode : {OBJECT_HIT_ANY,OBJECT_HIT_SELECTABLE,OBJECT_HIT_MOUSEOVER}
    /// i_bSearchAreaElements : Defined and true, look in AreaElementList else in NetworkElement list
    /// For NetworkElements we return a list if all NE objects matching XY and HitMode
    /// For AreaNetworkElements we return the first Area object
    ///
    this.findMapElement = function(x, y, i_HitMode, i_bSearchAreaElements )
    {
        var returnArray = new Array(2);
        var neArray = new Array();
        var propArray = new Array();
        var numElems = 0;
        
        if ( i_HitMode && i_HitMode == _EnumObjectHitMode.OBJECT_HIT_MOUSEOVER && _bMouseOverEnabled == false ){
            return null;
        }
        
        if ( _layerGroups != null)
        {
            //debugger
            //Traverse the groups
            for(var lg=0; lg<_layerGroups.length; lg++)
            {
                var bContinue = true;
                if ( i_HitMode && i_HitMode != _EnumObjectHitMode.OBJECT_HIT_ANY ){
                    if ( (i_HitMode == _EnumObjectHitMode.OBJECT_HIT_SELECTABLE && _layerGroups[lg].Property.bSelectable == false) ||
                         (i_HitMode == _EnumObjectHitMode.OBJECT_HIT_MOUSEOVER && _layerGroups[lg].Property.bMouseOver == false)){
                        bContinue = false;
                    } 
                }
                if ( _layerGroups[lg].Property.Active == true && bContinue == true){
                    //Traverse the layers
                    var numLayers = _layerGroups[lg].LayerList.length;
                    for (var ll=0; ll<numLayers; ll++)
                    {
                        //Then all network elements in the layer
                        var numElements = _layerGroups[lg].LayerList[ll].Properties.length;
                        var layer = _layerGroups[lg].LayerList[ll];
                        //First: Is layer selactable and only DB Layers, not FILE (Polygon) Layers
                        if ( layer.LayerSpec.LayerSrc != CV.mBOSS.DAL.LayerSpec_LAYER_SRC.DB_SRC_LAYER){

                            continue;
                        }
                        //Check if Area search active and exists in layer
                        if ( i_bSearchAreaElements && i_bSearchAreaElements == true){
                            //If Area search we continue if no AreaLayer   
                            if ( layer.AreaElementList == null){
                                continue;
                            }
                        } else if (layer.ElementList.length == 0 && layer.RelationList && layer.RelationListlength == 0) {
                            //No Element list or Relation list either
                            continue;
                        }
                        for(var ne=0; ne<numElements; ne++)
                        {
                            //Check if it's LayerTheme or LayerSymbol
                            var symbol = null;
                            if ( layer.LayerSpec.Symbol != null ){
                                symbol = layer.LayerSpec.Symbol;
                            } else if (layer.LayerSpec.LayerTheme != null ) {
                                var themeIdx = layer.Properties[ne].ThemeIdx;
                                if ( themeIdx > -1 ){
                                    symbol = layer.LayerSpec.LayerTheme.Themes[themeIdx].ThemeSymbol;
                                }
                            }
                            var bHit = this.mapElementHitDetect(x, y, layer.Properties[ne], symbol);
                            if ( bHit == true ){
                                var hitElement = null;
                                if ( layer.AreaElementList != null ){
                                    hitElement = layer.AreaElementList[ne];
                                } else {
                                    hitElement = layer.RelationList != null ? layer.RelationList[ne] : layer.ElementList[ne];
                                } 
                                neArray[numElems] = hitElement;
                                //Add some outline/property info
                                if ( symbol.SymbolType != CV.mBOSS.DAL.SymbolDef_SYMBOL_TYPE.PIE ){
                                    propArray[numElems] = layer.Properties[ne];
                                    
                                    var selectProp = null;
                                    if ( propArray[numElems].SelProp ){
                                        selectProp = propArray[numElems].SelProp;
                                    } else {
                                        propArray[numElems].SelProp = new CV.mBOSS.DAL.SelectProperties();
                                        selectProp = propArray[numElems].SelProp;
                                    }
                                    selectProp.Size     = 2*symbol.RadiusPix;//Diameter
                                    selectProp.Shape    = symbol.SelectShape;
                                    selectProp.Color    = symbol.SelectColor;
                                    selectProp.ShadowColor  = symbol.SelectShadowColor;
                                } else {
                                    propArray[numElems] = null;
                                }
                                numElems++
                            } //if hit
                        } //end traverse elements
                    } // end traverse layers
                } //If group active
            }// end traverse groups
        }
        if ( neArray.length == 0){
            return null;
        } else {
            returnArray[0] = neArray;
            returnArray[1] = propArray;
            return  returnArray;   
        }
    }
    
    //
    // Utility to check if the x,y coordinate pair hit the symbol 
    // in the map at location given by "property"
    //
    this.mapElementHitDetect = function(x, y, properties, symbol)
    {
        if ( symbol == null){
            return false;
        }
    
        var neX, neY;
        var bb = properties.BB;
        var pnt = properties.Pnt;
        if ( pnt.x == -1 && pnt.y == -1 && bb != null )
        {
            neX = (bb.LLX + bb.URX)/2.0;
            neY = (bb.LLY + bb.URY)/2.0;
        } else {
            neX = pnt.x + symbol.XSymOffset;
            neY = pnt.y + symbol.YSymOffset;
        }
        var bHit = false;
        switch ( symbol.SymbolType ){
            case CV.mBOSS.DAL.SymbolDef_SYMBOL_TYPE.RECTANGLE:
            //If a bounding rect exist we use it
            if ( bb ){
                if ( x >= bb.LLX && x <= bb.URX && y <= bb.LLY && y >= bb.URY){
                    bHit = true;
                }
            }
            break;
            case CV.mBOSS.DAL.SymbolDef_SYMBOL_TYPE.CIRCLE:
            case CV.mBOSS.DAL.SymbolDef_SYMBOL_TYPE.POINT:
            var deltaX = (x - neX);
            var deltaY = (y - neY);
            var dist = Math.sqrt(deltaX*deltaX + deltaY*deltaY);
            if ( dist <= symbol.RadiusPix ){
                bHit = true;
            }
            break;
            case CV.mBOSS.DAL.SymbolDef_SYMBOL_TYPE.LINE:
            if (properties.Pnt2 != null){
                var pnt2 = properties.Pnt2;
                var neX2 = pnt2.x + symbol.XSymOffset;
                var neY2 = pnt2.y + symbol.YSymOffset;
                //First check bounding box
                var xMax = neX > neX2 ? neX : neX2;
                var xMin = neX > neX2 ? neX2: neX;
                var yMax = neY > neY2 ? neY : neY2;
                var yMin = neY > neY2 ? neY2: neY;
                if ( x >= xMin && x<= xMax && y>= yMin && y<=yMax ){
                    //Then line intersect  y=Kx+B  (y-y1=(y2-y1)/(x2-x1)*(x-x1)
                    var K=(neY2-neY)/(neX2-neX); //Line Slope
                    var B=(neY-K*neX);
                    var Dist = Math.abs( (K*x-y+B)/Math.sqrt(K*K+1) );
                    if ( Dist <= 1){
                         bHit = true;
                    }
                }
            }
            break;
            case CV.mBOSS.DAL.SymbolDef_SYMBOL_TYPE.PIE:
            var BBsize = symbol.RadiusPix/2;
            
            if ( properties.Dir && x < neX+BBsize && x > neX-BBsize && y < neY+BBsize && y>neY-BBsize){
                for(var d=0; d<properties.Dir.length && bHit==false; d++){
                    //Calculate triangle vectors neX/Y is origo
                    var dirB = ((properties.Dir[d]-symbol.OpenAngle/2.0)/180.0)*Math.PI;
                    var dirC = ((properties.Dir[d]+symbol.OpenAngle/2.0)/180.0)*Math.PI;
                    var V0x=symbol.RadiusPix*Math.sin(dirC); //Origo to P1
                    var V0y=symbol.RadiusPix*Math.cos(dirC);
                    var V1x=symbol.RadiusPix*Math.sin(dirB); //Origo to P2
                    var V1y=symbol.RadiusPix*Math.cos(dirB);
                    var V2x=x-neX; //Origio to x/y input coord
                    var V2y=neY-y;
                    //Calculate vector dot products
                    var dot00 = (V0x*V0x+V0y*V0y);
                    var dot01 = (V0x*V1x+V0y*V1y);
                    var dot02 = (V0x*V2x+V0y*V2y);
                    var dot11 = (V1x*V1x+V1y*V1y);
                    var dot12 = (V1x*V2x+V1y*V2y);
                   // Compute barycentric coordinates
                    var invDenom = 1 / (dot00 * dot11 - dot01 * dot01)
                    var u = (dot11 * dot02 - dot01 * dot12) * invDenom
                    var v = (dot00 * dot12 - dot01 * dot02) * invDenom

                    // Check if point is in triangle
                   if ( (u > 0) && (v > 0) && (u + v < 1) ){
                        bHit = true;
                   }
               }
            }
            break;
            case CV.mBOSS.DAL.SymbolDef_SYMBOL_TYPE.IMAGE:
                var xLim = symbol.XSymSize == 0 ? 5 : symbol.XSymSize/2;
                var yLim = symbol.XSymSize == 0 ? 5 : symbol.YSymSize/2;
                if ( Math.abs(x - neX)<xLim && Math.abs(y - neY)<yLim){
                    bHit= true;
                }
            break;
            default:
            if ( Math.abs(x - neX)<5 && Math.abs(y - neY)<5){
                bHit= true;
            }
            break;
        } 
        return bHit;
    },
    
    this.mapElementHitDetectArea = function (LLX, LLY, URX, URY, properties, symbol)
    {
        var neX = properties.Pnt.x + symbol.XSymOffset;
        var neY = properties.Pnt.y + symbol.YSymOffset;
        
        var bHit = false;
        switch ( symbol.SymbolType ){
            case CV.mBOSS.DAL.SymbolDef_SYMBOL_TYPE.LINE:
            
            var neX2 = properties.Pnt2.x + symbol.XSymOffset;
            var neY2 = properties.Pnt2.y + symbol.YSymOffset;
            if ( neX >= LLX && neX <= URX && neY <= LLY && neY >= URY)
            {
                bHit = true; //Point one inside !!
            } else if (neX2 >= LLX && neX2 <= URX && neY2 <= LLY && neY2 >= URY){
                bHit = true; //point 2 inside !!
            } else if ((neX >= LLX || neX2 > LLX) && (neX <= URX || neX2 <= URX) && 
                       (neY <= LLY || neY2 <= LLY) && (neY >= URY || neY2 >= URY)){
                // The line could possibly intersect, but no endpoints inside rect, check cross of the four border lines
                if ( neX == neX2 ){
                    if ( neX >= LLX && neX <= URX) {//vertical line, we check if x between border of rect
                        bHit = true;
                    }
                } else if (neY == neY2){ //horizontal line, check crossing  rect
                    if ( neY<= LLY && neY >= URY){
                        bHit = true;
                    }
                } else { //Have to go the hard way and check line y=a+bx
                    var b = (neY-neY2)/(neX-neX2); //line slope
                    var a = neY-b*neX;
                    //Need only check one side, as line have to cross both the vertical and horizontal
                    var yCross_ll = a+b*LLX;
                    var yCross_ur = a+b*URX;
                    if ( (yCross_ll >= URY && yCross_ll <= LLY )||(yCross_ur >= URY && yCross_ur <= LLY )) {
                        bHit = true;
                    } else {
                        //Didn't cross verstical sides, check horizontal
                        var xCross_ll = (LLY-a)/b;
                        var xCross_ur = (URY-a)/b;
                        if ( (xCross_ll >= LLX && xCross_ll <= URX )||(xCross_ur >= LLX && xCross_ur <= URX )) {
                            bHit = true;
                        }
                    }
                }
            }
            break;
            default:
            //Note "oposite" check for Y direction because Y {0,0} is upper left
            if ( neX >= LLX && neX <= URX && neY <= LLY && neY >= URY)
            {
                 bHit = true;
            }
            break;
        }
        return bHit;
    },
    ///
    ///Search all groups and layers and find the DeviceProperties for the NetworkElements
    ///
    this.getDevicePropertyList = function(i_networkElementList)
    {
        if ( _layerGroups != null && i_networkElementList != null)
        {
            var propArray = new Array();
            for(var i_ne=0; i_ne<i_networkElementList.length; i_ne++){
                propArray[i_ne]= this.findNetworkElementProperty(i_networkElementList[i_ne].Id, i_networkElementList[i_ne].ElementType);
            }
            return propArray;
        }
        return null;
    }
    this.findNetworkElementProperty = function(i_neId, i_neElementType)
    {
        if ( _layerGroups != null )
        {
            //Traverse the groups
            for(var lg=0; lg<_layerGroups.length; lg++)
            {
                if ( _layerGroups[lg].Property.Active == true )
                {
                    //Traverse the layers
                    var numLayers = _layerGroups[lg].LayerList.length;
                    for (var ll=0; ll<numLayers; ll++)
                    {
                        var layer = _layerGroups[lg].LayerList[ll];
                        if ( layer.LayerSpec.LayerSrc != CV.mBOSS.DAL.LayerSpec_LAYER_SRC.DB_SRC_LAYER){
                            continue;
                        }
                        var numElements = layer.ElementList.length;
                        for(var ne=0; ne<numElements; ne++)
                        {
                            if ( layer.ElementList[ne].Id == i_neId && 
                                 layer.ElementList[ne].ElementType ==  i_neElementType)
                            {
                                    //Check if it's LayerTheme or LayerSymbol
                                var symbol = null;
                                if ( layer.LayerSpec.Symbol != null ){
                                    symbol = layer.LayerSpec.Symbol;
                                } else if (layer.LayerSpec.LayerTheme != null ) {
                                    var themeIdx = layer.Properties[ne].ThemeIdx;
                                    if ( themeIdx > -1 ){
                                        symbol = layer.LayerSpec.LayerTheme.Themes[themeIdx].ThemeSymbol;
                                    }
                                }
                                if ( symbol == null ){
                                    continue;
                                }
                            
                                //Copy info from symbol to Property
                                var Property = layer.Properties[ne];
                                var selectProp = null;
                                if ( Property.SelProp ){
                                    selectProp = Property.SelProp;
                                } else {
                                    Property.SelProp = new CV.mBOSS.DAL.SelectProperties();
                                    selectProp = Property.SelProp;
                                }
                                selectProp.Size     = 2*symbol.RadiusPix;//Diameter
                                selectProp.Shape        = symbol.SelectShape;
                                selectProp.Color        = symbol.SelectColor;
                                selectProp.ShadowColor  = symbol.SelectShadowColor;
                                return  layer.Properties[ne];  
                            }
                        } //end elements
                    } // end  layers
                } //end group active
            }// end groups
        }
        return null;
    }
    ///
    /// Search all groups and layers, find an area item with the requested ID
    ///
    this.findAreaItem = function(i_LayerGroupId, i_LayerId, i_AreaItemId)
    {
        if ( _layerGroups != null)
        {
            //debugger
            //Traverse the groups
            for(var lg=0; lg<_layerGroups.length; lg++)
            {
                if ( _layerGroups[lg].LayerGroupId == i_LayerGroupId ){
                    //Traverse the layers
                    var numLayers = _layerGroups[lg].LayerList.length;
                    for (var ll=0; ll<numLayers; ll++)
                    {
                        
                        //Then all network elements in the layer
                        var numElements = _layerGroups[lg].LayerList[ll].Properties.length;
                        var layer = _layerGroups[lg].LayerList[ll];
                        if ( layer.LayerSpec.LayerId == i_LayerId ){
                            for(var ne=0; ne<numElements; ne++)
                            {
                                if ( layer.AreaElementList[ne].Id == i_AreaItemId){
                                    return layer.AreaElementList[ne];
                                }
                            }
                        }
                    } // end traverse layers
                }// end traverse groups
            }// end if tooltip
        }
        return null;
    }
    ///
    /// Traverse all groups and layers and cgreate an HTML <map>
    /// Each <area> tag is a polygon layer element
    ///
    this.getAreaLayerMap = function()
    {
        var mapInnerHtml = "";
        
        if ( _layerGroups != null)
        {
            //debugger
            //Traverse the groups
            for(var lg=0; lg<_layerGroups.length; lg++)
            {
                var layerGroup = _layerGroups[lg];
                if ( layerGroup.Property.bSelPolygon == true && (layerGroup.Property.bSelectable == true || layerGroup.Property.bTooltip == true)){
                    //Traverse the layers
                    var tooltip;
                    var onClick;
                    
                    var numLayers = layerGroup.LayerList.length;
                    for (var ll=0; ll<numLayers; ll++)
                    {
                        //Then all network elements in the layer
                        var numElements = layerGroup.LayerList[ll].Properties.length;
                        var layer = layerGroup.LayerList[ll];
                        for(var neIdx=0; neIdx<numElements; neIdx++)
                        {
                            if ( layer.Properties[neIdx].AreaXY ){
                                //Split in polygons and holdes
                                var ne = layer.AreaElementList[neIdx];
                                var polygon = layer.Properties[neIdx].AreaXY.split('$');
                                //Ignore holes now
                                var polygonId = layerGroup.LayerGroupId + ":" + layer.LayerSpec.LayerId+ ":" + ne.Id;
                                var polyPolygon = polygon[0].split('|');
                                for(pp=0; pp<polyPolygon.length; pp++){
                                    tooltip = "";
                                    onClick = "";
                                    if ( layerGroup.Property.bTooltip == true && ne.TT != null){
                                        tooltip = "alt=\""+ ne.TT +"\"";
                                    }
                                    if (layerGroup.Property.bSelectable == true){
                                        onClick = "onclick=\"onPolygonClicked(\'"+polygonId+"\')\"";
                                    }
                                    mapInnerHtml += "<area shape=\"polygon\" "+ tooltip +" coords=\""+polyPolygon[pp]+"\"  "+onClick+" >";
                                }
                            }
                        }
                    } // end traverse layers
                }// end traverse groups
            }// end if tooltip
        }
       return mapInnerHtml.length > 0 ? mapInnerHtml : null;
    }
}
MapApiClient.MapDataMngr.registerClass('MapApiClient.MapDataMngr', null, Sys.IDisposable);
