'use strict';
define(function() {
  var gcmap = function(
    SelectManager,
    gclayers,
    QueryFactory,
    $rootScope,
    $filter,
    gcRestrictionProvider,
    gcInteractions,
    $timeout,
    gaJsUtils,
    layersService,
    mapJsUtils,
    PortalsFactory
  ) {
    return {
      restrict: 'A',
      scope: {
        map: '=gcmapmap',
        isAncOrBac: '=?',
      },

      link: function($scope, element) {
        var map = $scope.map;
        var view = map.getView();
        $scope.$on('mapViewChanged', function() {
          view = map.getView();
        });
        var RESTRICTION_TABLE_NAME = 'CAJ_RES_MAJ';
        // / POPUP
        var container = document.getElementById('popup');
        var content = document.getElementById('popup-content');
        var closer = document.getElementById('popup-closer');

        /**
         * Add a click handler to hide the popup.
         * @return {boolean} Don't follow the href.
         */
        if (closer) {
          closer.onclick = function() {
            for (var i = map.getOverlays().getLength() - 1; i >= 0; i -= 1) {
              var overlay = map.getOverlays().getArray()[i];
              if (overlay.get('origin') === 'bubble') {
                overlay.setPosition(undefined);
              }
            }
            closer.blur();
            return false;
          };
        }

        function getUrl(olLayer) {
          return olLayer.getSource().getUrl
            ? olLayer.getSource().getUrl()
            : olLayer.getSource().getUrls()[0];
        }

        function getDirectUrl(olLayer) {
          return olLayer.get('directUrl');
        }
        /**
         * Create an overlay to anchor the popup to the map.
         */
        var overlay = new ol.Overlay(
          /** @type {olx.OverlayOptions} */ ({
            element: container,
            autoPan: true,
            autoPanAnimation: {
              duration: 250,
            },
          })
        );
        overlay.set('origin', 'bubble');
        map.addOverlay(overlay);
        $scope.isActivePopup = false;

        $scope.$on('activatePopup', function() {
          $scope.isActivePopup = true;
          console.log('je active ' + $scope.isActivePopup);
        });
        $scope.$on('deactivatePopup', function() {
          $scope.isActivePopup = false;
          console.log('je desactive ' + $scope.isActivePopup);
        });
        /**
         * Add a click handler to the map to render the popup.
         */
        map.on('singleclick', function(evt) {
          if (map.getOverlays().getLength() == 0) {
            overlay = new ol.Overlay(
              /** @type {olx.OverlayOptions} */ ({
                element: container,
                autoPan: true,
                autoPanAnimation: {
                  duration: 250,
                },
              })
            );
            overlay.set('origin', 'bubble');
            map.addOverlay(overlay);
          }

          for (var i = map.getOverlays().getLength() - 1; i >= 0; i -= 1) {
            var overlay = map.getOverlays().getArray()[i];
          }
          var coordinate = evt.coordinate;
          var x = evt.coordinate[0];
          var y = evt.coordinate[1];

          if ($scope.isActivePopup) {
            var leftX, rightX, bottomY, topY;
            var view = map.getView();
            var resolution = view.getResolution();

            // var pointExtent = [x, y , x, y];
            if (resolution != 'undefined') {
              leftX = x - 5 * resolution;
              rightX = x + 5 * resolution;
              bottomY = y - 5 * resolution;
              topY = y + 5 * resolution;
            }
            else {
              leftX = x - 5;
              rightX = x + 5;
              bottomY = y - 5;
              topY = y + 5;
            }
            var selectUids = [];
            $scope.selectedUids = {};
            gclayers.getOperationalLayerg2cCollection().forEach(function(l) {
              if (l.visible && l.get('fti')) {
                selectUids.push(l.get('fti').uid);
                $scope.selectedUids[l.get('fti').name] = l.get('fti');
              }
            });
            gclayers.getOperationalLayerESRICollection().forEach(function(l) {
              if (l.visible && l.get('fti')) {
                selectUids.push(l.get('fti').uid);
                $scope.selectedUids[l.get('fti').name] = l.get('fti');
              }
            });
            var filter =
              'INTERSECTS(geom, POLYGON((' +
              leftX +
              ' ' +
              bottomY +
              ',' +
              rightX +
              ' ' +
              bottomY +
              ',' +
              rightX +
              ' ' +
              topY +
              ',' +
              leftX +
              ' ' +
              topY +
              ',' +
              leftX +
              ' ' +
              bottomY +
              ')))';
            var sendata = {
              uids: selectUids,
              filter: filter,
              srid:map.getView().getProjection().getCode(),
            };
            QueryFactory.popupdata(sendata).then(
              function(res) {
                var cont = '';
                if (res.data.features.length > 0) {
                  angular.forEach(res.data.features, function(feat) {
                    /*<div id="tooltip">
                                      <div class="info">
                                        <h2>Kushagra Agarwal</h2>
                                        <p>
                                          HTML/CSS expert <br />
                                          Frontend Designer
                                        </p>

                                      </div>  */

                    var idelement = feat.id;
                    if (idelement) {
                      var name = idelement.substring(0, idelement.indexOf('.'));
                      var fti = $scope.selectedUids[name];
                      idelement = QueryFactory.getObjectId(feat, fti);
                    }

                    cont =
                      cont + '<div style="max-height:250px;overflow:auto" >';
                    cont =
                      cont +
                      '<h5 style="font-weight:bold;color: #31708f;" >' +
                      idelement +
                      '</h5>';
                    cont = cont + '<table style="width:100%">';
                    var cclsse = 'evenattributes';
                    angular.forEach(feat.properties, function(v, k) {
                      cont = cont + '<tr style="width:100%;">';
                      //ng-class-odd="'oddattributes'" ng-class-even="'evenattributes'"
                      if (cclsse === 'oddattributes') {
                        cclsse = 'evenattributes';
                      }
                      else {
                        cclsse = 'oddattributes';
                      }
                      if (v && v.substr(0, 5) === '<img>')
                        cont =
                          cont +
                          '<td classe="' +
                          cclsse +
                          '"> ' +
                          ' : <img src="data:image/png;base64,' +
                          v.substr(5) +
                          '"/> </td>';
                      else
                        cont =
                          cont +
                          '<td classe="' +
                          cclsse +
                          '"> ' +
                          getAttributeAlias(fti, k) +
                          ' : ' +
                          v +
                          ' </td>';

                      cont = cont + '</tr>';
                    });
                    cont = cont + '</table>';
                    cont = cont + '</div>';
                  });
                  content.innerHTML = cont;
                  overlay.setPosition(coordinate);
                }
              },
              function(result) {
                gcRestrictionProvider.showDetailsErrorMessage(result);
              }
            );
          }
        });

        function getAttributeAlias(fti, attrName) {
          var aliasName;
          angular.forEach(fti.attributes, function(attr) {
            if (
              aliasName == null &&
              attr.name.toLowerCase() === attrName.toLowerCase()
            )
              aliasName = attr.alias;
          });

          return aliasName ? aliasName : attrName;
        }

        function hasRestriction() {
          if (
            $rootScope.xgos.user.restriction &&
            $rootScope.xgos.user.restriction.name &&
            $rootScope.xgos.user.restriction.modes &&
            $rootScope.xgos.user.restriction.modes.viewer
          )
            return true;
          else return false;
        }


        const getPortalId = () => {
          return $rootScope.xgos.portal.uid;
        };


        function getEsriWMSParams(typeNames, opacityValue, filtert, group) {
          var dynamicLayers = [];
          for (var i = 0; i < typeNames.length; i++) {
            var dynamicLayerEntry = {
              id: typeNames[i],
              source: {
                type: 'mapLayer',
                mapLayerId: typeNames[i],
              },
            };
            var filter = filtert[i];
            if (filter != null && filter != '1=1')
              dynamicLayerEntry.definitionExpression = filter;

            var opacity = opacityValue[i];
            if (opacity != null)
              dynamicLayerEntry.drawingInfo = {
                transparency: opacity == 1 ? 0 : 100 - opacity * 100,
              };
            dynamicLayers.push(dynamicLayerEntry);
          }

          return {
            dynamicLayers: angular.toJson(dynamicLayers),
            tiled: true,
            tilesorigin: '-20037508.342789236,-20037508.342789236',
            type: 'esri',
            bboxSR: $scope.map.getView().getProjection().getCode().split(':')[1],
            kis_token: localStorage.getItem('auth_token'),
            kis_portal_id:  getPortalId(),
            GROUP: group
          };
        }

        function updateLayersParams(
          srcESRI,
          olLayer,
          LAYERSnewESRI,
          OPACITYnewESRI,
          FILTERnewESRI,
          STYLESnewESRI,
          LABELSnewESRI,
          updateVisibility
        ) {
          // console.log(LAYERSnewESRI);
          var paramsESRI = srcESRI.getParams();
          if (updateVisibility && !olLayer.getVisible())
            olLayer.setVisible(true);
          var dynamicLayers = [];
          for (var i = 0; i < LAYERSnewESRI.length; i++) {
            var dynamicLayerEntry = {
              id: LAYERSnewESRI[i],
              source: {
                type: 'mapLayer',
                mapLayerId: LAYERSnewESRI[i],
              },
            };
            var filter = FILTERnewESRI[i];
            if (filter != null && filter != '1=1')
              dynamicLayerEntry.definitionExpression = filter;
            var opacity = OPACITYnewESRI[i];
            var layerStyle;

            if (STYLESnewESRI != null) {
              layerStyle = STYLESnewESRI[i];
            }

            var layerLabel;

            if (LABELSnewESRI != null) {
              layerLabel = LABELSnewESRI[i];
            }

            if (opacity != null) {
              dynamicLayerEntry.drawingInfo = {
                transparency: opacity == 1 ? 0 : 100 - opacity * 100,
              };
            }

            if (!angular.isUndefined(layerStyle)) {
              if (!angular.isUndefined(dynamicLayerEntry.drawingInfo)) {
                dynamicLayerEntry.drawingInfo.renderer = layerStyle;
              }
              else {
                dynamicLayerEntry.drawingInfo = {
                  renderer: layerStyle,
                };
              }
            }

            if (!angular.isUndefined(layerLabel)) {
              console.log(layerLabel);

              if (!angular.isUndefined(dynamicLayerEntry.drawingInfo)) {
                dynamicLayerEntry.drawingInfo.labelingInfo = layerLabel;
              }
              else {
                dynamicLayerEntry.drawingInfo = {
                  labelingInfo: layerLabel,
                };
              }
            }

            dynamicLayers.push(dynamicLayerEntry);
          }
          paramsESRI.kis_token = localStorage.getItem('auth_token');
          paramsESRI.kis_portal_id = getPortalId();
          paramsESRI.dynamicLayers = angular.toJson(dynamicLayers);
          paramsESRI.t = new Date().getMilliseconds();
          srcESRI.updateParams(paramsESRI);
        }

        function compareUrls(url1, url2) {
          if (!url1 || !url2) {
            return false;
          }
          return (
            url1.replace('MapServer/', 'MapServer') ==
            url2.replace('MapServer/', 'MapServer')
          );
        }

        function updateLayersConfigs(
          l,
          urlESRI,
          urlDirectESRI,
          LAYERSnewESRI,
          OPACITYnewESRI,
          FILTERnewESRI,
          STYLESnewESRI,
          LABELSnewESRI
        ) {
          var currentResolution = view.getResolution();
          if (
            (compareUrls(getFtiWMS(l.fti), urlESRI) ||
              compareUrls(getFtiWMS(l.fti), urlDirectESRI)) &&
            l.visible &&
            l.getMaxResolution() > currentResolution &&
            l.getMinResolution() < currentResolution
          ) {
            LAYERSnewESRI.push(l.fti.ogcId);

            if (STYLESnewESRI != null) {
              STYLESnewESRI.push(l.style);
            }

            if (LABELSnewESRI != null) {
              LABELSnewESRI.push(l.label);
            }

            if (angular.isUndefined(l.invertedOpacity)) {
              OPACITYnewESRI.push(1);
            }
            else {
              OPACITYnewESRI.push(1 - l.invertedOpacity);
            }
            if (angular.isUndefined(l.cql_filter)) {
              FILTERnewESRI.push('1=1');
            }
            else {
              FILTERnewESRI.push(l.cql_filter.replace(l.fti.name, l.fti.ogcId));
            }
          }
        }

        function createFilter(data, l) {
          if (data)
            return (
              data +
              ' AND INTERSECTS(' +
              l.fti.geomName +
              ',querySingle(\'' +
              $rootScope.xgos.portal.uid +
              ':' +
              RESTRICTION_TABLE_NAME +
              '\',\'' +
              $rootScope.xgos.user.restriction.geomName +
              '\',\'' +
              $rootScope.xgos.user.restriction.fidName +
              ' = ' +
              $rootScope.xgos.user.restriction.fid.split('.')[1] +
              '\'))'
            );
          else
            return (
              'INTERSECTS(' +
              l.fti.geomName +
              ',querySingle(\'' +
              $rootScope.xgos.portal.uid +
              ':' +
              RESTRICTION_TABLE_NAME +
              '\',\'' +
              $rootScope.xgos.user.restriction.geomName +
              '\',\'' +
              $rootScope.xgos.user.restriction.fidName +
              ' = ' +
              $rootScope.xgos.user.restriction.fid.split('.')[1] +
              '\'))'
            );
        }

        $scope.maxpergroup = 300;
        $scope.snapon = true;
        map.on('snapAddedEvent', function() {
          $scope.snapon = true;
          checkActivationSnap();
        });

        map.on('snapRemovedEvent', function() {
          $scope.snapon = false;
          if (
            gclayers.getSnapLayerActivation() &&
            Object.keys(gclayers.getSnapLayer()).length > 0
          ) {
            gclayers.DeactivateSnapLayer();
            gclayers.deleteSnapLayer();
            $scope.map.removeLayer(gclayers.getSnapLayer());
            gclayers.addSnapLayer({});
          }
        });

        var checkActivationSnap = function() {
          if ($scope.map.getView().getResolution() < 1.5) {
            if (
              !gclayers.getSnapLayerActivation() &&
              $scope.snapon &&
              Object.keys(gclayers.getSnapLayer()).length > 0
            ) {
              gclayers.ActivateSnapLayer();
              $scope.map.addLayer(gclayers.getSnapLayer());
            }
          }
          else {
            if (
              gclayers.getSnapLayerActivation() &&
              Object.keys(gclayers.getSnapLayer()).length > 0
            ) {
              gclayers.DeactivateSnapLayer();
              gclayers.deleteSnapLayer();
              $scope.map.removeLayer(gclayers.getSnapLayer());
            }
          }
        };

        function esriMoveEnd(olLayer) {
          let srcESRI = olLayer.getSource();
          let urlESRI;
          urlESRI = olLayer.get('url');
          let LAYERSnewESRI = [];
          let OPACITYnewESRI = [];
          let FILTERnewESRI = [];
          let group = layersService.getLayerGroupFromOlLayer(olLayer,
            gclayers.layersGroupedByStore);
          angular.forEach(group.layers,
            function (l) {
              updateLayersConfigs(
                l,
                urlESRI,
                undefined,
                LAYERSnewESRI,
                OPACITYnewESRI,
                FILTERnewESRI
              );
            });
          if (LAYERSnewESRI.join(',') == '') {
            olLayer.setVisible(false);
          }
          else {
            //var paramsESRI = srcESRI.getParams();
            updateLayersParams(
              srcESRI,
              olLayer,
              LAYERSnewESRI,
              OPACITYnewESRI,
              FILTERnewESRI,
              true
            );
          }
        }

        function geoserverMoveEnd(olLayer) {
          var src = olLayer.getSource();
          var LAYERSnew = [];
          var STYLESnew = [];
          var OPACITYnew = [];
          var FILTERnew = [];
          var added_g_cql_filter = false;
          var g_cql_filter = '';
          let group = layersService.getLayerGroupFromOlLayer(olLayer,
            gclayers.layersGroupedByStore);
          if(group != undefined) {
            angular.forEach(group.layers,
              function (l) {
                if (
                  l.visible &&
                  l.getMaxResolution() > $scope.CurrentResolution &&
                  l.getMinResolution() < $scope.CurrentResolution
                ) {
                  LAYERSnew.push(l.name);
                  STYLESnew.push(l.style);
                  if (angular.isUndefined(l.invertedOpacity)) {
                    OPACITYnew.push(1);
                  }
                  else {
                    OPACITYnew.push(1 - l.invertedOpacity);
                  }

                  if (angular.isUndefined(l.cql_filter)) {
                    FILTERnew.push('1=1');
                  }
                  else {
                    FILTERnew.push(l.cql_filter);
                  }
                  if (!added_g_cql_filter && hasRestriction()) {
                    g_cql_filter = createFilter(undefined, l);
                    added_g_cql_filter = true;
                  }
                }
              }
            );

            if (LAYERSnew.join(',') == '') {
              olLayer.setVisible(false);
            }
            else {
              if (!olLayer.getVisible()) olLayer.setVisible(true);
              var params = src.getParams();
              params.LAYERS = LAYERSnew.join(',');
              params.STYLES = STYLESnew.join(',');
              params.OPACITY = OPACITYnew.join(',');
              params.gcql_filter = g_cql_filter;
              params.CQL_FILTER = FILTERnew.join(';'); //console.log(params.CQL_FILTER)
              params.t = new Date().getMilliseconds();
              src.updateParams(params);
            }
          }
          else {
            console.error('erreur le layer group n\'existe pas');
          }
        }

        /**
         * Actualisation carte suite à zoom ou déplacement.
         */
        map.on('moveend', () => {
          if ($rootScope.doNotPropagateMapRefresh) {
            $rootScope.doNotPropagateMapRefresh = false;
            return;
          }
          if ($scope.processingMoveend) {
            return;
          }
          $scope.processingMoveend = true;
          //in anc and bac, we don't need to filter the layers
          if(!$scope.isAncOrBac) {
            //display only the layers that needs to be displayed
            //(regarding geocatalog config and zoom)
            // some layers should not be displayed at certain zoom level

            //console.log('moveend zoom level ' , $scope.map.getView().getZoom());
            var oldres = angular.copy($scope.CurrentResolution);
            $scope.CurrentResolution = $scope.map.getView().getResolution();
            checkActivationSnap();
            if (oldres != $scope.CurrentResolution) {

              $scope.map.getLayers().forEach(function(olLayer) {
                if (!angular.isUndefined(olLayer.get('id'))) {
                  var wms_options = olLayer.get('id');
                  if (wms_options.mode === 'WMS') {
                    if (olLayer.getSource().getParams().type === 'esri') {
                      esriMoveEnd(olLayer);
                    }
                    else if (
                      olLayer.getSource().getParams().type != 'esri') {
                      geoserverMoveEnd(olLayer);
                    }
                  }
                }
              });
            }
            if ($rootScope.xgos.portal != null && $rootScope.xgos.portal.name === 'AFFAIRES')
              $rootScope.$broadcast('init_update_chart_affaire');
          }
          applyAll();
          $scope.processingMoveend = false;
        });

        function parseToolBarWidget(e) {
          if (
            e.mode === 'Panel' ||
            e.type === 'Panel' ||
            angular.isUndefined(e.type)
          )
            return $filter('translate')(e.title);
          else if (e.type === 'widget') {
            return $filter('translate')(e.title);
          }
          else {
            return e.title;
          }
        }

        function parseInteractions(KisInteractionsWidgets, KisWidgetUsed) {
          let i, str;
          var numberOfundefinedTools = KisWidgetUsed.filter(function(x) {
            if (angular.isDefined(x) && angular.isDefined(x.title)) return x;
          }).length;
          if (numberOfundefinedTools > 1) {
            str = $filter('translate')('gcmap.widgets');
            for (i = 0; i < KisInteractionsWidgets.length; i++) {
              if (i === 0) {
                str += parseToolBarWidget(KisWidgetUsed[i]);
              }
              else {
                str +=
                  $filter('translate')('gcmap.and') +
                  parseToolBarWidget(KisWidgetUsed[i]);
              }
            }
            str += $filter('translate')('gcmap.desc1');
            for (i = 0; i < KisInteractionsWidgets.length; i++) {
              if (i === 0) {
                str +=
                  $filter('translate')('gcmap.desc2') +
                  $filter('translate')('common.yes') +
                  $filter('translate')('gcmap.desc3') +
                  parseToolBarWidget(KisWidgetUsed[i + 1]) +
                  ', \'' +
                  $filter('translate')('common.no') +
                  $filter('translate')('gcmap.desc4');
                break;
              }
            }
          }
          else {
            str =
              $filter('translate')('gcmap.full') +
              $filter('translate')('common.yes') +
              $filter('translate')('gcmap.full2') +
              $filter('translate')('common.no') +
              $filter('translate')('gcmap.full3');
          }
          return str;
        }

        function removeInteractionsFromMap(
          KisInteractions,
          widgetName,
          KisWidgetUsed
        ) {
          var t = 0;
          KisInteractions.map(function(i, idx) {
            if (i.get('widget') === widgetName) {
              i.setActive(false);
              $scope.map.removeInteraction(i);
              if (t === 0) {
                var numberOfundefinedTools = KisWidgetUsed.filter(function(x) {
                  if (angular.isDefined(x) && angular.isDefined(x.title))
                    return x;
                }).length;
                if (numberOfundefinedTools > 1) {
                  if (
                    angular.isDefined(KisWidgetUsed[idx]) &&
                    angular.isDefined(KisWidgetUsed[idx].type) &&
                    KisWidgetUsed[idx].type === 'widget'
                  ) {
                    $rootScope.$broadcast(
                      'closeToolsBar_' + KisWidgetUsed[idx].name,
                      KisWidgetUsed[idx].name
                    );
                    $timeout(function() {
                      $rootScope.$broadcast('checkinfotoolbar');
                    }, 1000);
                  }

                  if (
                    angular.isDefined(KisWidgetUsed[idx]) &&
                    (KisWidgetUsed[idx].mode === 'Panel' ||
                      KisWidgetUsed[idx].type === 'Panel' ||
                      angular.isUndefined(KisWidgetUsed[idx].type))
                  ) {
                    KisWidgetUsed[idx].active = false;
                    $rootScope.$broadcast(
                      'closeTools_' + KisWidgetUsed[idx].directive,
                      KisWidgetUsed[idx]
                    );
                  }
                }
                t++;
              }
            }
          });
        }

        $scope.map.getInteractions().on('add', function(evt) {
          var interactions = evt.target;
          var KisInteractions = [];
          var KisInteractionsWidgets = [];
          var KisWidgetUsed = [
            gcInteractions.getOldTool(),
            gcInteractions.getCurrentTool(),
          ];
          /**
           * Crée un bug dans l'annotation
           *
           */
          interactions.forEach(function(interaction) {
            if (
              interaction.get('gctype') === 'kis' &&
              interaction.getActive()
            ) {
              if (
                KisInteractionsWidgets.indexOf(interaction.get('widget')) === -1
              ) {
                KisInteractionsWidgets.push(interaction.get('widget'));
                KisInteractions.push(interaction);
              }
              else {
                if (
                  interaction.get('widget') != 'Edition' &&
                  interaction.get('widget') != 'EditionService'
                ) {
                  removeInteractionsFromMap(
                    KisInteractions,
                    KisInteractionsWidgets[0],
                    KisWidgetUsed
                  );
                }
              }
            }
          });
          if (KisInteractionsWidgets.length > 1) {
            var callback = function(isConfirm) {
              if (isConfirm) {
                removeInteractionsFromMap(
                  KisInteractions,
                  KisInteractionsWidgets[0],
                  KisWidgetUsed
                );
              }
              else {
                removeInteractionsFromMap(
                  KisInteractions,
                  KisInteractionsWidgets[1],
                  KisWidgetUsed
                );
              }
            };
            swal(
              {
                title: $filter('translate')('gcmap.information'),
                text: parseInteractions(KisInteractionsWidgets, KisWidgetUsed),
                type: 'warning',
                showCancelButton: true,
                confirmButtonColor: '#5cb85c',
                confirmButtonText: $filter('translate')('common.yes'),
                cancelButtonText: $filter('translate')('common.no'),
                closeOnConfirm: true,
                closeOnCancel: true,
              },
              callback
            );
          }
        });

        $scope.wmsLayerCollection = new ol.Collection();

        $scope.$on('gcSelectChange', function() {
          try {
            gclayers.getselectSource().clear();
            gclayers.clearhighLightFeatures();
            const geojson = new ol.format.GeoJSON();
            const featuresData = SelectManager.getfeatures();
            for (const feature of featuresData.features) {
              const olFeature = geojson.readFeature(feature);
              if (olFeature.getGeometry()!==null) {
                gclayers.getselectSource().addFeature(olFeature);
              }
            }
          }
          catch (e) {
            require('toastr').info(
              $filter('translate')('intervflowwidget.notgeographic')
            );
          }
        });
        function addLayersFromArray(l) {
          for (var iLyr = 0; iLyr < l.length; iLyr++) {
            map.getLayers().insertAt(iLyr, l[iLyr]);
            gclayers.addGroupLayer(l[iLyr]);
          }
        }
        function addLayersFromParam(l) {
          if (l instanceof Array) {
            addLayersFromArray(l);
          }
          else {
            addLayersFromArray([l]);
          }
        }
        function displayedLayersChanged(l, displayed) {
          if (l.isArray == undefined || !l.isArray())
            if (displayed.length !== 1)
              //-- Un layer en fond de plan et un layer cliqué
              //-- donc est-ce le même ?
              return l.name != displayed[0];
            //-- Plusieurs layer en fond de plan
            //-- et un layer cliqué il y a une différence.
            else return true;

          //-- L'objet layer est COMPOSED,
          //-- donc composé de plusieurs layers.

          //-- La liste des layers cliquée n'a pas la même
          //-- taille, on considère donc un changement.
          if (l.length != displayed.length) return true;

          //-- Vérifier que tous les layers sont
          //-- dans la liste des layers affichés.
          for (var iLyr = l.length - 1; iLyr >= 0; iLyr--) {
            for (var iDisp = displayed.length - 1; iDisp >= 0; iDisp--) {
              if (displayed[iDisp] == l[iLyr].name) {
                displayed.splice(iDisp, 1);
                break;
              }
            }
          }
          //-- Quand la liste displayed n'est pas vide,'
          //-- c'est qu'au moins un des layers n'était pas
          //-- dans la liste, donc il y a un changement.
          return displayed.length != 0;
        }

        $scope.$on('gcBackGroundLayerChange', function(event, l) {
          let iLyr = 0,
            lyr,
            displayed = [];

          // si il existe des couches
          if (map.getLayers().getLength() > 0) {
            // si c une couche de type background
            while (map.getLayers().item(iLyr)) {
              lyr = map.getLayers().item(iLyr);
              if (lyr.theme == 'Fond de Plan' || lyr.theme == 'WebBackGround') {
                displayed.push(lyr.name);
                gclayers.deleteGroupLayer(lyr);
                map.getLayers().forEach(function(l) {
                  if (l == lyr) map.getLayers().removeAt(iLyr);
                });
                //map.getLayers().removeAt(iLyr);
              }
              iLyr++;
            }

            if (displayedLayersChanged(l, displayed)) {
              addLayersFromParam(l);
            }
          }
          else {
            addLayersFromParam(l);
          }
        });

        function getLayerInfo(
          l,
          LAYERSnew,
          STYLESnew,
          OPACITYnew,
          FILTERnew,
          cqlFilterParams
        ) {
          var currentResolution = $scope.map.getView().getResolution();
          if (
            l.visible &&
            l.getMaxResolution() > currentResolution &&
            l.getMinResolution() < currentResolution
          ) {
            LAYERSnew.push(l.name);
            STYLESnew.push(l.style);
            if (angular.isUndefined(l.invertedOpacity)) {
              OPACITYnew.push(1);
            }
            else {
              OPACITYnew.push(1 - l.invertedOpacity);
            }
            //// Restriction
            if (angular.isUndefined(l.cql_filter)) {
              FILTERnew.push('1=1');
            }
            else {
              FILTERnew.push(l.cql_filter);
            }
            if (!cqlFilterParams.added_g_cql_filter && hasRestriction()) {
              cqlFilterParams.g_cql_filter = createFilter(undefined, l);
              cqlFilterParams.added_g_cql_filter = true;
            }
          }
        }


        var UpdateWMSLayerForce = function(olLayer) {
          // Récupère toutes les couches WMS et force leur rafraîchissement
          const refreshAllWMSLayers = () => {
            if (!map) return;

            map.getLayers().forEach((layer) => {
              const options = layer.get('id');
              if (options && options.mode === 'WMS') {
                const source = layer.getSource();
                if (source) {
                  // Force un nouveau timestamp
                  const params = source.getParams();
                  params.t = new Date().getTime();
                  source.updateParams(params);

                  // Nettoie le cache si possible
                  if (source.tileCache) {
                    source.tileCache.clear();
                  }

                  // Force le rafraîchissement
                  source.refresh();
                  layer.changed();
                }
              }
            });

            // Force le rafraîchissement de la carte
            if (map.updateSize) map.updateSize();
            $timeout(() => {
              if (map.renderSync) map.renderSync();
            }, 100);
          };

          // Si une couche spécifique est fournie, vérifie si c'est une couche WMS
          const wms_options = olLayer.get('id');
          if (wms_options && wms_options.mode === 'WMS') {
            refreshAllWMSLayers();
          }
        };


        function getPriorityLayers(olLayer, l, allKisLayers) {
          if (!allKisLayers) {
            return [l];
          }
          let grp = layersService.getLayerGroupFromOlLayer(olLayer,
            gclayers.layersGroupedByStore);
          return grp.layers;
        }

        let PriorityManagerEsri = (l, olLayer) => {
          let urlESRI = getUrl(olLayer);
          let srcESRI = olLayer.getSource();
          let urlDirectESRI = getDirectUrl(olLayer);
          let LAYERSnewESRI = [];
          let STYLESnewESRI = [];
          let LABELSnewESRI = [];
          let OPACITYnewESRI = [];
          let FILTERnewESRI = [];
          let grp = layersService.getLayerGroupFromOlLayer(olLayer, gclayers.
            layersGroupedByStore);
          angular.forEach(grp.layers,
            (l) => {
              updateLayersConfigs(l, urlESRI, urlDirectESRI, LAYERSnewESRI,
                OPACITYnewESRI, FILTERnewESRI, STYLESnewESRI, LABELSnewESRI
              );
            }
          );

          updateLayersParams(srcESRI, olLayer, LAYERSnewESRI,
            OPACITYnewESRI, FILTERnewESRI, STYLESnewESRI,
            LABELSnewESRI, false
          );
        };


        const PriorityManager = (l,allKisLayers) => {
          //-- Obtention de la couche OpebLayers qui contient
          //-- la couche KIS à rendre invisible.
          let olLayer = getWMSGROUPfromLayer(l.name);
          let wms_options = olLayer.get('id');
          let layers = getPriorityLayers(olLayer, l, allKisLayers);
          let iLyr;
          let currentResolution = $scope.map.getView().getResolution();


          if (angular.isDefined(wms_options.activeLayer[0])) {
            if (l.gctype == 'esri') {
              //-- Cas d'un service de carte ArcGIS Server
              PriorityManagerEsri(l, olLayer);
            }
            else {
              for (iLyr = 0; iLyr < layers.length; iLyr++) {
                //-- Cas d'un service de carte GeoServer
                if (layers[iLyr].visible) {
                  layers[iLyr].visible = false;
                  geoserverVisibilityManager(olLayer, layers[iLyr], 'priority',
                    false, currentResolution);
                  layers[iLyr].visible = true;
                  geoserverVisibilityManager(olLayer, layers[iLyr], 'priority',
                    iLyr + 1 == layers.length, currentResolution);
                }
              }
            }
          }
          return;
        };

        var setCqlFilter = function (paramsESRI, filtertESRI, ogid) {
          var dl = JSON.parse(paramsESRI.dynamicLayers);
          let index = dl.map((e) => {
            return e.id;
          }).indexOf(ogid);
          if(index != -1){
            dl[index].definitionExpression = filtertESRI[0];
            paramsESRI.dynamicLayers = JSON.stringify(dl);
          }
        };


        var cqlFilterManager = function(l) {
          const olLayer = getWMSGROUPfromLayer(l.name);
          var wms_options = olLayer.get('id');
          let ind;

          if (angular.isDefined(wms_options.activeLayer[0])) {
            let curRes = $scope.map.getView().getResolution();
            if (l.gctype == 'esri') {
              if (l.visible) {
                l.visible = false;
                esriVisibilityManager(olLayer, l, false, curRes);
                l.visible = true;
                esriVisibilityManager(olLayer, l, true, curRes);
              }
            }
            else {
              var src = olLayer.getSource();
              // var currentl = wms_options[4].split(',');
              // currentl.push(l.name);
              var params = src.getParams();
              params.t = new Date().getMilliseconds();
              var layert = [];
              var stylet = [];
              var opacityt = [];
              var filtert = [];
              var added_g_cql_filter = false;
              var g_cql_filter = '';
              if (params.LAYERS != '') {
                layert = params.LAYERS.split(',');
                stylet = params.STYLES.split(',');
                opacityt = params.OPACITY.split(',');
                filtert = params.CQL_FILTER.split(';');
              }

              if (l.visible && l.getMaxResolution() > curRes &&
              l.getMinResolution() < curRes) {
                if ($.inArray(l.name, layert) > -1) {
                  var layerIndex = layert.indexOf(l.name);
                  stylet[layerIndex] = l.style;
                  if (angular.isUndefined(l.invertedOpacity)) {
                    opacityt[layerIndex] = 1;
                  }
                  else {
                    opacityt[layerIndex] = 1 - l.invertedOpacity;
                  }
                  if (angular.isUndefined(l.cql_filter)) {
                    filtert[layerIndex] = '1=1';
                  }
                  else {
                    filtert[layerIndex] = l.cql_filter; // .replace(/\s=\s/g,
                    // '=');
                  }
                  if (!added_g_cql_filter && hasRestriction()) {
                    g_cql_filter = createFilter(undefined, l);
                    added_g_cql_filter = true;
                  }
                }
                else {
                  layert.push(l.name);
                  stylet.push(l.style);
                  if (angular.isUndefined(l.invertedOpacity)) {
                    opacityt.push(1);
                  }
                  else {
                    opacityt.push(1 - l.invertedOpacity);
                  }

                  // // Restriction
                  if (angular.isUndefined(l.cql_filter)) {
                    filtert.push('1=1');
                  }
                  else {
                    filtert.push(l.cql_filter);
                  }

                  console.log('add' + layert.join(';'));
                }
              }
              else {
                ind = layert.indexOf(l.name);
                if (ind != -1) {
                  layert.splice(ind, 1);
                  stylet.splice(ind, 1);
                  opacityt.splice(ind, 1);
                  filtert.splice(ind, 1);
                  console.log('remove' + layert.join(','));
                }
              }
              params.LAYERS = layert.join(',');
              params.STYLES = stylet.join(',');
              params.GCQL_FILTER = g_cql_filter;
              params.OPACITY = opacityt.join(',');
              params.CQL_FILTER = filtert.join(';');
              src.updateParams(params);
            }
          }
        };


        function getLayerPrioOrder(olLayer, layer, type) {
          let group = layersService.getLayerGroupFromOlLayer(olLayer,
            gclayers.layersGroupedByStore);
          let iLyr;
          for (iLyr = 0; iLyr < group.layers.length; iLyr++) {
            if (group.layers[iLyr].fti.uid == layer.fti.uid) {
              /* Dans le cas d'utilisation des ITVs et des Observations en particulier, et suit eà l'application du filtre, il semblerait que le calcul de la priorité soit le même quel que soit le cas.
              Si pas de bug constaté, enlever ces lignes à terme.
              @EDG le 21/02/2022*/
              if (type == 'esri')
                return group.layers.length - iLyr - 1;
              else
                return iLyr;
            }
          }
        }


        /**
         * Appelé depuis visibilityManager pour rendre visible
         * ou invisible une couche KIS au sein d'une couche OpenLayers
         * qui est un accés à un service de carte regroupant
         * plusieurs couches ESRI.
         *
         * @param {*} olLayer : Couche OpenLayers
         * @param {*} l  : Couche KIS
         */
        let esriVisibilityManager = (olLayer, l, refreshMap, curRes) => {
          //-- Obtention de la source ESRI du layer
          //-- Cette source et seulement celle-ci sera rafraîchie.
          let srcESRI = olLayer.getSource();
          let paramsESRI = srcESRI.getParams();
          paramsESRI.t = new Date().getMilliseconds();
          let transparency;
          let filtert;

          paramsESRI.LAYERS = JSON.parse(paramsESRI.dynamicLayers);

          if (l.visible && l.getMaxResolution() > curRes &&
            l.getMinResolution() < curRes) {
            if (!angular.isUndefined(l.cql_filter)) {
              filtert = l.cql_filter;
            }
            if (angular.isUndefined(l.invertedOpacity)) {
              transparency = 0;
            }
            else {
              transparency = 100 * l.invertedOpacity;
            }

            let lyrPrio = getLayerPrioOrder(olLayer, l, 'esri');
            let lp = {
              id: l.fti.ogcId,
              source: {
                type: 'mapLayer',
                mapLayerId: l.fti.ogcId
              },
              drawingInfo: {
                transparency: transparency
              }
            };
            if (filtert)
              lp.definitionExpression = filtert;
            paramsESRI.LAYERS.splice(lyrPrio, 0, lp);

          }
          else {
            let iLyr;
            for (iLyr = 0; iLyr < paramsESRI.LAYERS.length; iLyr++) {
              if (paramsESRI.LAYERS[iLyr].id == l.fti.ogcId) {
                paramsESRI.LAYERS.splice(iLyr, 1);
                break;
              }
            }
          }
          paramsESRI.LAYERS
            = layersService.sortLayersOnPriority(paramsESRI.LAYERS, 'esri');
          paramsESRI.dynamicLayers = JSON.stringify(paramsESRI.LAYERS);
          delete paramsESRI.LAYERS;
          paramsESRI.t = new Date().getMilliseconds();
          if (refreshMap) {
            srcESRI.updateParams(paramsESRI);
          }
        };


        let ensureLayerVisibility = (olLayer, layert, stylet, opacityt, filtert) => {
          let group = layersService.getLayerGroupFromOlLayer(olLayer,
            gclayers.layersGroupedByStore);
          angular.forEach(group.layers,
            (l) => {
              if (!l.visible) {
                const ind = layert.indexOf(l.name.toString());
                if (ind != -1) {
                  layert.splice(ind, 1);
                  stylet.splice(ind, 1);
                  opacityt.splice(ind, 1);
                  filtert.splice(ind, 1);
                  console.log('remove' + layert.join(','));
                }
              }
            }
          );
        };


        /**
         * Appelé depuis visibilityManager pour rendre visible
         * ou invisible une couche KIS au sein d'une couche OpenLayers
         * qui est un accés à un service de carte regroupant
         * plusieurs couches GeoServer.
         *
         * @param {*} olLayer : Couche OpenLayers
         * @param {*} l  : Couche KIS
         * @param {*} mgmtType : type de gestion undefined = visibilité,
         *                       opacity = transparence
         */
        let geoserverVisibilityManager = (olLayer, l, mgmtType, refreshMap,
          currentResolution) => {
          let ind;
          var src = olLayer.getSource();
          var params = src.getParams();
          params.t = new Date().getMilliseconds();
          var layert = [];
          var stylet = [];
          var opacityt = [];
          var filtert = [];
          var added_g_cql_filter = false;
          var g_cql_filter = '';
          if (params.LAYERS != '') {
            layert = params.LAYERS.split(',');
            stylet = params.STYLES.split(',');
            opacityt = params.OPACITY.split(',');
            filtert = params.CQL_FILTER.split(';');
          }

          if (l.visible &&
            l.getMaxResolution() > currentResolution &&
            l.getMinResolution() < currentResolution) {
            //-- La couche KIS doit être visible, mais l'est-elle déjà ?
            if ($.inArray(l.name.toString(), layert) > -1) {
              //-- L couche KIS doit être visible, mais elle l'est déjà,
              //-- on prend en compte son (nouveau) paramétrage.
              var layerIndex = layert.indexOf(l.name.toString());
              stylet[layerIndex] = l.style;
              if (angular.isUndefined(l.invertedOpacity)) {
                opacityt[layerIndex] = 1;
              }
              else {
                opacityt[layerIndex] = 1 - l.invertedOpacity;
              }
              if (angular.isUndefined(l.cql_filter)) {
                filtert[layerIndex] = '1=1';
              }
              else {
                filtert[layerIndex] = l.cql_filter;
              }
              if (!added_g_cql_filter && hasRestriction()) {
                g_cql_filter = createFilter(undefined, l);
                added_g_cql_filter = true;
              }
            }
            else {
              //-- La couche KIS doit être visible, et elle
              //-- n'est actuellement pas affichée, on va donc l'ajouter.
              let lyrPrio = getLayerPrioOrder(olLayer, l, 'geoserver');
              layert.splice(lyrPrio, 0, l.name);
              stylet.splice(lyrPrio, 0, l.style);
              if (angular.isUndefined(l.invertedOpacity)) {
                opacityt.splice(lyrPrio, 0, 1);
              }
              else {
                opacityt.splice(lyrPrio, 0, 1 - l.invertedOpacity);
              }

              // // Restriction
              if (angular.isUndefined(l.cql_filter)) {
                filtert.splice(lyrPrio, 0, '1=1');
              }
              else {
                filtert.splice(lyrPrio, 0, l.cql_filter);
              }
              if (!added_g_cql_filter && hasRestriction()) {
                g_cql_filter = createFilter(undefined, l);
                added_g_cql_filter = true;
              }
              console.log('add' + layert.join(','));
            }
          }
          else {
            ind = layert.indexOf(l.name.toString());
            if (ind != -1) {
              layert.splice(ind, 1);
              stylet.splice(ind, 1);
              opacityt.splice(ind, 1);
              filtert.splice(ind, 1);
              console.log('remove' + layert.join(','));
            }
          }
          //-- Gestion du cas où on a rendu le groupe invisible juste avant.
          ensureLayerVisibility(olLayer, layert, stylet, opacityt, filtert);
          if (mgmtType == undefined || mgmtType == 'visibility') {
            if (layert.join(',') != '' && !olLayer.getVisible())
              olLayer.setVisible(true);
          }
          params.LAYERS = layert.join(',');
          params.STYLES = stylet.join(',');
          params.OPACITY = opacityt.join(',');
          params.GCQL_FILTER = g_cql_filter;
          params.CQL_FILTER = filtert.join(';');
          params.layerDefs =
            '{' +
            layert.map(function (x, i) {
              return '"' + x + '":"' + filtert[i] + '"';
            }) +
            '}';
          if (refreshMap) {
            src.updateParams(params);
            if (src.changed)
              src.changed();
            src.refresh();
          }
        };

        /**
         * Actualisation de la couche OpenLayers de type GeoServer
         * qui contient la couche à rendre visible ou invisible.
         * Cette methode permet quand il ya plusieurs couches OpenLayers
         * qui chacune contiennent un accés à un service de carte
         * avec une liste de couches précises, de n'actualiser sur la carte
         * que le layer  OpenLayer concerné, sans avoir à redessiner
         * les autres layers OpenLayers(donc sans avoir à appeler
         * les autres services de carte).
         *
         * @param {ol.layer.Vector} l : layer à rendre visible ou invisible,
         *                ce layer correspond à un composant ou FTI.
         * @param mgmtType type de gestion undefined = visibilité, opacity = transparence
         */
        var VisibilityManager = function(l, mgmtType) {

          //-- Obtention de la couche OpebLayers qui contient
          //-- la couche KIS à rendre invisible.
          let olLayer = getWMSGROUPfromLayer(l.name);
          if (olLayer) {
            const wms_options = olLayer.get('id');

            if (angular.isDefined(wms_options.activeLayer[0])) {
              let curRes = $scope.map.getView().getResolution();
              if (l.hasOwnProperty('gctype') && l.gctype === 'esri') {
                //-- Cas d'un service de carte ArcGIS Server
                esriVisibilityManager(olLayer, l, true, curRes);
              }
              else {
                //-- Cas d'un service de carte GeoServer
                geoserverVisibilityManager(olLayer, l, mgmtType, true, curRes);
              }
            }
          }
        };


        var refreshLayer = function(l) {
          var olLayer = getRefWMSGROUPfromLayer(l.name);
          UpdateWMSLayerForce(olLayer);
        };

        var getRefWMSGROUPfromLayer = function(name) {
          var res = null;
          $scope.map.getLayers().forEach(function(olLayer) {
            if (!angular.isUndefined(olLayer.get('id'))) {
              var wms_options = olLayer.get('id');
              // gestion des couches associé

              angular.forEach(wms_options.refLayer, function(li) {
                if (li.name == name) {
                  res = olLayer;
                }
              });
            }
          });
          return res;
        };


        var getWMSGROUPfromLayer = function(name) {
          // console.log(name)
          var res = null;
          $scope.map.getLayers().forEach(function(olLayer) {
            if (!angular.isUndefined(olLayer.get('id'))) {
              var wms_options = olLayer.get('id');
              // gestion des couches associé
              //console.log(wms_options.activeLayer , "wms_options.activeLayer")
              const deleteIndex = Array.isArray(wms_options.activeLayer) ? wms_options.activeLayer.findIndex(al => al.name === name) : -1;
              // $scope.tools.splice(deleteIndex,1);
              if (deleteIndex !== -1) {
                res = olLayer;
              }
              // console.log(wms_options)
            }
          });
          return res;
        };


        let applyAllEsri = (olLayer, group) => {
          var srcESRI = olLayer.getSource();
          var urlESRI = getUrl(olLayer);
          var urlDirectESRI = getDirectUrl(olLayer);
          var LAYERSnewESRI = [];
          var STYLESnewESRI = [];
          var OPACITYnewESRI = [];
          var FILTERnewESRI = [];
          var LABELSnewESRI = [];
          gclayers
            .getOperationalLayerESRICollection()
            .forEach(function(l) {
              updateLayersConfigs(
                l,
                urlESRI,
                urlDirectESRI,
                LAYERSnewESRI,
                OPACITYnewESRI,
                FILTERnewESRI,
                STYLESnewESRI,
                LABELSnewESRI
              );
            });
          if (LAYERSnewESRI.join(',') == '') {
            olLayer.setVisible(false);
          }
          else {
            updateLayersParams(
              srcESRI,
              olLayer,
              LAYERSnewESRI,
              OPACITYnewESRI,
              FILTERnewESRI,
              STYLESnewESRI,
              LABELSnewESRI,
              true
            );
          }
        };


        let applyAllGeoServer = (olLayer) => {
          var src = olLayer.getSource();
          var url = src.getParams().type;
          var LAYERSnew = [];
          var STYLESnew = [];
          var OPACITYnew = [];
          var FILTERnew = [];
          let cqlFilterParams = {};
          cqlFilterParams.added_g_cql_filter = false;
          cqlFilterParams.g_cql_filter = '';
          const ret = layersService.organizeLayers(gclayers.layersGroupedByStore);
          const group = ret.layerGroups.find(lg => lg.group === olLayer.get('groupOfLayers'));
          let layers = group ? group.layers
            : gclayers.getOperationalLayerg2cCollection().getArray();
          if (!$scope.isAncOrBac) {
            layers = layersService.sortLayersOnPriority(layers, 'g2c');
          }
          for (const layer of layers) {
            if (layer.getSource().getParams().type === url) {
              getLayerInfo(layer, LAYERSnew, STYLESnew, OPACITYnew,
                FILTERnew, cqlFilterParams);
            }
          }
          if (LAYERSnew.join(',') == '') {
            olLayer.setVisible(false);
          }
          else {
            let params = src.getParams();
            if (!olLayer.getVisible()) olLayer.setVisible(true);
            params.LAYERS = LAYERSnew.join(',');
            params.STYLES = STYLESnew.join(',');
            params.OPACITY = OPACITYnew.join(',');
            params.GCQL_FILTER = cqlFilterParams.g_cql_filter;
            params.CQL_FILTER = FILTERnew.join(';');
            params.t = new Date().getMilliseconds();
            src.updateParams(params);
          }
        };

        let applyAll = () => {
          $scope.CurrentResolution = $scope.map.getView().getResolution();
          $scope.map.getLayers().forEach(function(olLayer) {
            if (!angular.isUndefined(olLayer.get('id'))) {
              var wms_options = olLayer.get('id');
              if (wms_options.mode == 'WMS') {
                if (olLayer.getSource().getParams().type == 'esri') {
                  applyAllEsri(olLayer);
                }
                else if (olLayer.getSource().getParams().type != 'esri') {
                  applyAllGeoServer(olLayer);
                }
              }
            }
          });
        };


        $scope.$on('gcOperationalLayerChange', function(event, l, type) {

          if (type == 'add') {
            gclayers.addGroupLayer(l);
          }
          if (type == 'visibility') {
            VisibilityManager(l,type);
          }
          if (type == 'priority') {
            PriorityManager(l,false);
          }
          if (type == 'priorityAll') {
            PriorityManager(l,true);
          }
          if (type == 'cql_filter') {
            cqlFilterManager(l);
            $timeout(() => {
              refreshLayer(l);
            });
          }

          if (type == 'refreshlayer') {
            refreshLayer(l);
          }
          if (type == 'applyall') {
            applyAll();
          }
        });


        $scope.$on('gcChangeCursorMap', function(event, cl) {
          // console.log("recup de l'evenement");
          // element.removeClass("glyphicon glyphicon-pencil");

          // la condition évite le décalage du point de dessin (cercle jaune) sur la carte de representation_filière ANC
          // le test sert uniquement pour représentation filière ANC
          if ($rootScope.xgos.sector!=='anc' && ((typeof element.getTarget === 'function'  && element.getTarget() !== 'rf_map') || (element.id && element.id !== 'rf_map'))){
            element.removeAttr('class');
            element.addClass(cl);
          }
        });


        $scope.$on('gcTechnicalLayerChange', function(event, l) {
          gclayers.addGroupLayer(l);
          map.addLayer(l);
        });


        function emptyWmsLayerCollection() {
          $scope.wmsLayerCollection.forEach(function(wmsl) {
            $scope.map.removeLayer(wmsl);
          });
          $scope.wmsLayerCollection.clear();
        }


        $scope.$on('gcOperationalLayerEmptyToUpdate', function () {
          emptyWmsLayerCollection();
        });


        function getLinkUrl(dataStore) {
          if (dataStore.useproxy && dataStore.proxykey)
            return '../services/esriproxy/' + dataStore.proxykey + '/MapServer';
          else dataStore.url;
        }



        function getFtiWMS(fti) {
          var ftiDataStore = mapJsUtils.getFtiDataStore(fti);
          return ftiDataStore ? getLinkUrl(ftiDataStore) : fti.wms;
        }


        function checkDataStoreIsTiled(l) {
          if (l.fti) {
            var ftiDataStore = mapJsUtils.getFtiDataStore(l.fti);
            return ftiDataStore && angular.isDefined(ftiDataStore.tiled)
              ? ftiDataStore.tiled
              : false;
          }

          return true;
        }


        function loadGeoServerLayer(l,currentResolution,params) {
          if (params.tiled == undefined) params.tiled = checkDataStoreIsTiled(l);
          params.layerinWMS.push(l);
          params.reflayerinWMS.push(l);
          params.layerind.push(l.index);

          if (
            l.visible &&
            l.getMaxResolution() > currentResolution &&
            l.getMinResolution() < currentResolution
          ) {
            params.typeNames.push(l.name);
            // OPACITY
            if (angular.isUndefined(l.invertedOpacity)) {
              params.opacityValue.push(1);
            }
            else {
              params.opacityValue.push(1 - l.invertedOpacity);
            }

            // // Restriction
            if (angular.isUndefined(l.cql_filter)) {
              params.filtert.push('1=1');
            }
            else {
              params.filtert.push(l.cql_filter);
            }
            // CQL_FILTER
            if (angular.isUndefined(l.style)) {
              params.styleNames.push('');
            }
            else {
              params.styleNames.push(l.style);
            }

            if (!params.added_g_cql_filter && hasRestriction()) {
              params.g_cql_filter = createFilter(undefined, l);
              params.added_g_cql_filter = true;
            }
          }

          if ($scope.maxpergroup == params.nbpergroup) {
            // cas ou nous avons le maximum par group
            //2- on creer la couche
            var wmsParams = {
              LAYERS: params.typeNames.join(','),
              tiled: false,
              STYLES: params.styleNames.join(','),
              OPACITY: params.opacityValue.join(','),
              CQL_FILTER: params.filtert.join(';'),
              tilesorigin: '-20037508.342789236,-20037508.342789236',
              type: 'g2c',
              GCQL_FILTER: params.g_cql_filter,
            };
            var wmsOptions = {
              url:
                '/services/' +
                PortalsFactory.getPortalId() +
                '/geoserver/wms?token=' +
                localStorage.auth_token,
              layerinWMS: {
                mode: 'WMS',
                refLayer: params.reflayerinWMS,
                type: 'GROUP',
                activeLayer: params.layerinWMS,
                indexWms: params.wmsindx,
                rejected: [],
              },

              //name: wmsindx,
              grouptype: 'GROUP,' + params.wmsindx,
              //theme:"Non Defini",
              gctype: 'g2c',
              olZIndex: params.olZIndex
              //extent: getCapLayer.extent,
              //attribution: gaUrlUtils.getHostname(getCapLayer.wmsUrl)
            };
            params.wmsindx++;
            var wmslayer = generateWmsLayer(wmsParams, wmsOptions);

            //on ajoute la couche a la collection de couche
            $scope.wmsLayerCollection.push(wmslayer);
            params.nbpergroup = -1;
            params.typeNames = [];
            params.styleNames = [];
            params.opacityValue = [];
            params.layerinWMS = [];
            params.params.layerind = [];
            params.reflayerinWMS = [];
            params.added_g_cql_filter = false;
            params.g_cql_filter = '';
          }

          params.nbpergroup++;
        }


        function addAndGenerateEsriWmsLayer(groupOfLayers,params) {

          // cas ou nous avons le maximum par group
          // 2- on crée la couche
          var wmsParams = getEsriWMSParams(params.typeNames,
            params.opacityValue, params.filtert, groupOfLayers.group);
          var wmsOptions = {
            url: params.lien,
            directUrl: params.directUrl,
            layerinWMS: {
              mode: 'WMS',
              refLayer: params.reflayerinWMS,
              type: 'GROUP',
              activeLayer: params.layerinWMS,
              indexWms: params.wmsindx,
              rejected: [],
            },

            // name: wmsindx,
            grouptype: 'GROUP,' + params.wmsindx,
            // theme:"Non Defini",
            gctype: 'esri',
            olZIndex: params.olZIndex
            // extent: getCapLayer.extent,
            // attribution: gaUrlUtils.getHostname(getCapLayer.wmsUrl)
          };

          params.wmsindx++;
          var wmslayer = generateWmsLayer(wmsParams, wmsOptions, params.tiled);
          // on ajoute la couche a la collection de couche
          $scope.wmsLayerCollection.push(wmslayer);
          groupOfLayers.mapOlLayer = wmslayer;

          //-- Réinitialisation de la description du contenu du layer.
          params.nbpergroup = -1;
          params.typeNames = [];
          params.opacityValue = [];
          params.layerinWMS = [];
          params.layerind = [];
          params.reflayerinWMS = [];
          params.urlESRI = [];
        }

        let addAtFirstPos = (arr, item) => {
          //          arr.splice(0, 0, item);
          arr.push(item);
        };

        function loadEsriLayer(l, params, group) {
          let esriInfo;
          let fti = l.fti;
          let ftiDataStore = mapJsUtils.getFtiDataStore(fti);
          esriInfo = params.esriInfos[fti.storeName];
          if (esriInfo==undefined) {
            esriInfo = {
              //-- wmsLink
              url: ftiDataStore ? getLinkUrl(ftiDataStore) : fti.wms,
              directurl: ftiDataStore ? ftiDataStore.url : fti.wms,
              tiled: ftiDataStore ? ftiDataStore.tiled : fti.isTiledMap,
            };
            params.esriInfos[fti.storeName] = esriInfo;
          }

          params.lien = esriInfo.url;
          params.directUrl = esriInfo.directurl;
          params.tiled = esriInfo.tiled;
          params.nbpergroup = 0;
          var currentResolution = view.getResolution();

          var wmsLink = ftiDataStore ? getLinkUrl(ftiDataStore) : fti.wms;
          if (wmsLink == params.lien) {
            addAtFirstPos(params.layerinWMS,l);
            addAtFirstPos(params.reflayerinWMS,l);
            addAtFirstPos(params.layerind,l.index);
            if (
              l.visible &&
              l.getMaxResolution() > currentResolution &&
              l.getMinResolution() < currentResolution
            ) {
              addAtFirstPos(params.urlESRI,wmsLink);
              addAtFirstPos(params.typeNames,l.fti.ogcId);
              // OPACITY
              if (angular.isUndefined(l.invertedOpacity)) {
                addAtFirstPos(params.opacityValue,1);
              }
              else {
                addAtFirstPos(params.opacityValue,1 - l.invertedOpacity);
              }
              // CQL_FILTER
              if (angular.isUndefined(l.cql_filter)) {
                addAtFirstPos(params.filtert,'1=1');
              }
              else {
                addAtFirstPos(params.filtert,l.cql_filter);
              }
            }
          }

          if ($scope.maxpergroup == params.nbpergroup) {
            addAndGenerateEsriWmsLayer(group,params);
          }

          params.nbpergroup++;
        }

        /**
         * Création d'une couche OpenLayers contenant des couches KIS
         * gérées par un même GeoServer.
         *
         * @param {*} groupOfLayers
         * @param {*} params
         */
        function createOpenLayerForGeoserver(groupOfLayers,params) {
          // 2- on crée la couche
          /*
           * wmsParams mis dans le rootScope pour que
           * le module gsScaleValue puisse changer l'échelle de représentation
           * demandée à GeoServer.'
           */
          var wmsParams = {
            LAYERS: params.typeNames.join(','),
            tiled: false,
            STYLES: params.styleNames.join(','),
            OPACITY: params.opacityValue.join(','),
            CQL_FILTER: params.filtert.join(';'),
            scale4Representation: $rootScope.xgos.scale4Representation,
            tilesorigin: '-20037508.342789236,-20037508.342789236',
            type: 'g2c',
            GCQL_FILTER: params.g_cql_filter,
            GROUP: groupOfLayers.group
          };

          $rootScope.xgos.listOfWmsParams.push(wmsParams);

          if (params.reflayerinWMS && params.reflayerinWMS.length > 0) {
            var wmsOptions = {
              //url: 'http://46.105.100.62:8082/geoserver/ed53f43f-7fda-4d61-ba16-9f0c1bfe5503/wms?token=007',
              url:
                '/services/' +
                PortalsFactory.getPortalId() +
                '/geoserver/wms?token=' +
                localStorage.auth_token,
              // url:'/services/'+PortalsFactory.getPortalId()+'/ogc/g2c?token=' +'007',
              // url:'/wsgi/wms-win.py?portal='+PortalsFactory.getPortalId()+'&token=' +'007',
              layerinWMS: {
                mode: 'WMS',
                refLayer: params.reflayerinWMS,
                type: 'GROUP',
                activeLayer: params.layerinWMS,
                indexWms: params.wmsindx,
                rejected: [],
              },
              gctype: 'g2c',
              olZIndex: params.olZIndex
              // extent: getCapLayer.extent,
              //attribution: gaUrlUtils.getHostname(getCapLayer.wmsUrl)
            };
            const wmslayer = generateWmsLayer(wmsParams, wmsOptions,
              params.tiled);
            // on ajoute la couche a la collection de couche
            $scope.wmsLayerCollection.push(wmslayer);
            groupOfLayers.mapOlLayer = wmslayer;
          }
        }

        function getParamsInit(params) {
          let olZIndex;
          let gsLayersLoaded = false, esriLayersLoaded = false;
          if (params) {
            olZIndex = params.olZIndex.value;
            gsLayersLoaded = params.gsLayersLoaded;
            esriLayersLoaded = params.esriLayersLoaded;
          }
          else {
            olZIndex = 100;
            gsLayersLoaded = esriLayersLoaded = false;
          }
          return {
            added_g_cql_filter: false,
            filtert: [],
            g_cql_filter: '',
            layerinWMS: [],
            layerind: [],
            nbpergroup: 0,
            opacityValue: [],
            reflayerinWMS: [],
            styleNames: [],
            typeNames: [],
            wmsindx: 0,
            esriInfos: [],
            urlESRI: [],
            olZIndex: { value: olZIndex },
            gsLayersLoaded: gsLayersLoaded,
            esriLayersLoaded: esriLayersLoaded
          };
        }


        function createOlLayerIfRequired(group, params) {
          if (params.gsLayersLoaded) {
            //-- Mise en place de la couche OpenLayers regroupant
            //-- des couches KIS ESRI.
            createOpenLayerForGeoserver(group,params);
            params.gsLayersLoaded = false;
          }
          else if (params.esriLayersLoaded) {
            //-- Mise en place de la couche OpenLayers regroupant
            //-- des couches KIS GeoServer.
            addAndGenerateEsriWmsLayer(group,params);
            params.esriLayersLoaded = false;
          }
        }

        /**
         * Réaction à un broadcast de l'événement 'gcOperationalLayerOnInit'
         * généré dans 2 cas, celui du chargement initial de la carte et
         * celui de changement de priorité d'une couche OpenLayers
         * regroupant plusieurs couches KIS.
         */
        $scope.$on('gcOperationalLayerOnInit', function () {
          console.log('Initialisation des couches');
          let params;
          //-- Vidage de la liste des couches courante.
          emptyWmsLayerCollection();
          var currentResolution = $scope.map.getView().getResolution();

          $rootScope.xgos.listOfWmsParams = [];

          //-- Récupération de la liste des couches organisée en groupe.
          if (!gclayers.layersGroupedByStore)
            gclayers.layersGroupedByStore = layersService.organizeLayers();

          //-- Parcours de la liste des groupes de couches.
          angular.forEach(gclayers.layersGroupedByStore.layerGroups,
            function (group) {
              params = getParamsInit(params);
              //-- Parcours de la liste des couches du groupe de couche.
              angular.forEach(group.layers,
                function (l) {
                  if (l.getProperties().gctype == 'g2c') {
                    //-- Préparation d'une couche KIS GeoServer.
                    loadGeoServerLayer(l, currentResolution, params);
                    params.gsLayersLoaded = true;
                  }
                  else {
                    //-- Préparation d'une couche KIS ESRI.
                    loadEsriLayer(l, params, group);
                    params.esriLayersLoaded = true;
                  }
                }
              );
              createOlLayerIfRequired(group, params);
            }
          );

          var idx = -1;
          $scope.map.getLayers().forEach(function(layer, index) {
            if (layer && angular.isDefined(layer.theme)
              && layer.theme === 'Techniques'
            ) {
              if (idx === -1) idx = index;
              else {
                idx = Math.min(idx, index);
              }
            }
          });

          addLayers(idx);

          gclayers.clearTechnicalLayers($scope.map);

          gclayers.createselectlayer();
          gclayers.createimportlayer();
          gclayers.createguidelayer();
          gclayers.createhighlightlayer($scope.map);
          gclayers.createeditlayer($scope.map);
          gclayers.createmeasurelayer($scope.map);
          gclayers.createAnnotationLayer($scope.map);
        });

        //-- Actualisation de la liste des couches OpenLayers
        //-- et ajout de celles-ci à la carte.
        var addLayers = function (idx) {
          $scope.wmsLayerCollection.forEach(function(wmsl) {
            if (idx === -1) $scope.map.addLayer(wmsl);
            else {
              $scope.map.getLayers().insertAt(idx + 100, wmsl);
              idx++;
            }
          });
        };

        var generateImageWmsLayer = function(params, options) {
          options = options || {};
          var attributions;
          var source =
            options.gctype == 'esri'
              ? new olkis.KISImageArcGISRest({
                params: params,
                url: options.url,
                crossOrigin: 'anonymous',
                extent: options.extent,
                attributions: attributions,
                ratio: options.ratio || 1,
              })
              : new olkis.KISImageWMSRest({
                gaJsUtils: gaJsUtils,
                params: params,
                url: options.url,
                extent: options.extent,
                attributions: attributions,
                ratio: options.ratio || 1,
              });
          if (angular.isDefined(params.STYLES)) {
            var layer = new ol.layer.Image({
              id: options.layerinWMS,
              url: options.url,
              type: 'WMS',
              layersg: params.LAYERS,
              opacity: options.opacity,
              visible: options.visible,
              attribution: options.attribution,
              fti: options.fti,
              name: options.name,
              style: params.STYLES,
              source: source,
              zIndex: options.olZIndex.value++,
              groupOfLayers: params.GROUP
            });
          }
          else {
            layer = new ol.layer.Image({
              id: options.layerinWMS,
              url: options.url,
              type: 'WMS',
              layersg: params.LAYERS,
              opacity: options.opacity,
              visible: options.visible,
              attribution: options.attribution,
              fti: options.fti,
              name: options.name,
              // style: params.STYLES,
              source: source,
              zIndex: options.olZIndex.value++,
              groupOfLayers: params.GROUP
            });
          }
          layer.preview = options.preview;
          layer.displayInLayerManager = !layer.preview;
          layer.label = options.label;
          return layer;
        };
        var generateWmsLayer = function(params, options, tiled) {
          var layer =
            tiled == undefined || tiled
              ? generateTiledWmsLayer(params, options)
              : generateImageWmsLayer(params, options);
          if (options.directUrl) layer.set('directUrl', options.directUrl);

          return layer;
        };
        var generateTiledWmsLayer = function(params, options) {
          options = options || {};
          var attributions;
          var source;
          if (options.gctype == 'esri') {
            source = new olkis.KISTileArcGISRest({
              params: params,
              url: options.url,
              crossOrigin: 'anonymous',
              extent: options.extent,
              attributions: attributions,
              ratio: options.ratio || 1,
            });
          }
          else
            source = new olkis.KISTileWMSRest({
              gaJsUtils: gaJsUtils,
              params: params,
              url: options.url,
              extent: options.extent,
              attributions: attributions,
              ratio: options.ratio || 1,
            });
          if (angular.isDefined(params.STYLES)) {
            var layer = new ol.layer.Tile({
              id: options.layerinWMS,
              url: options.url,
              type: 'WMS',
              layersg: params.LAYERS,
              opacity: options.opacity,
              visible: options.visible,
              attribution: options.attribution,
              fti: options.fti,
              style: params.STYLES,
              name: options.name,
              source: source,
              zIndex: options.olZIndex.value++
            });
          }
          else {
            layer = new ol.layer.Tile({
              id: options.layerinWMS,
              url: options.url,
              type: 'WMS',
              layersg: params.LAYERS,
              opacity: options.opacity,
              visible: options.visible,
              attribution: options.attribution,
              fti: options.fti,
              // style: params.STYLES,
              name: options.name,
              source: source,
              zIndex: options.olZIndex.value++
            });
          }
          layer.preview = options.preview;
          layer.displayInLayerManager = !layer.preview;
          layer.label = options.label;
          return layer;
        };
      },
    };
  };

  gcmap.$inject = [
    'SelectManager',
    'gclayers',
    'QueryFactory',
    '$rootScope',
    '$filter',
    'gcRestrictionProvider',
    'gcInteractions',
    '$timeout',
    'gaJsUtils',
    'layersService',
    'mapJsUtils',
    'PortalsFactory'
  ];
  return gcmap;
});
