<commit_before>goog.provide('gmf.LayertreeController');
goog.provide('gmf.layertreeDirective');

goog.require('gmf');
goog.require('ngeo.CreatePopup');
goog.require('ngeo.LayerHelper');
goog.require('ngeo.LayertreeController');
goog.require('ol.Collection');
goog.require('ol.layer.Tile');


gmf.module.value('gmfLayertreeTemplate',
    /**
     * @param {angular.JQLite} element Element.
     * @param {angular.Attributes} attrs Attributes.
     * @return {string} Template.
     */
    function(element, attrs) {
      var subTemplateUrl = gmf.baseTemplateUrl + '/layertree.html';
      return '<div ngeo-layertree="gmfLayertreeCtrl.tree" ' +
          'ngeo-layertree-map="gmfLayertreeCtrl.map" ' +
          'ngeo-layertree-nodelayer="gmfLayertreeCtrl.getLayer(node, depth)" ' +
          'ngeo-layertree-listeners="gmfLayertreeCtrl.listeners(treeScope, ' +
          'treeCtrl)" ' +
          'ngeo-layertree-templateurl="' + subTemplateUrl + '"' +
          '</div>';
    });


// Overrides the path to the layertree template (used by each nodes, except
// the root node that path is defined by the gmfLayertreeTemplate value.
ngeo.module.value('ngeoLayertreeTemplateUrl',
    /**
     * @param {angular.JQLite} element Element.
     * @param {angular.Attributes} attrs Attributes.
     * @return {string} Template URL.
     */
    function(element, attrs) {
      return gmf.baseTemplateUrl + '/layertree.html';
    });


/**
 * This directive creates a layertree based on the c2cgeoportal JSON themes
 * source and a {@link ngeo.layertreeDirective}. The controller used by this
 * directive defines some fonctions for each node that are created by a default
 * template. This default template can be overrided by setting the constant
 * 'gmf.layertreeTemplateUrl' but you will must adapt the
 * ngeoLayertreeTemplateUrl value too (to define the children's nodes template
 * path).
 *
 * @example
 * <gmf-layertree
 *   gmf-layertree-source="ctrl.source"
 *   gmf-layertree-map="ctrl.map"
 * </gmf-layertree>
 *
 * You can add an attribute 'gmf-layertree-openlinksinnewwindow="true"' to open
 * metadata URLs in a new window. By default, and in the default template,
 * links will be opened in a popup.
 *
 * @param {string|function(!angular.JQLite=, !angular.Attributes=)}
 *     gmfLayertreeTemplate Template for the directive.
 * @return {angular.Directive} The directive specs.
 * @ngInject
 * @ngdoc directive
 * @ngname gmfLayertreeDirective
 */
gmf.layertreeDirective = function(gmfLayertreeTemplate) {
  return {
    scope: {
      'map': '=gmfLayertreeMap',
      'tree': '=gmfLayertreeSource',
      'openLinksInNewWindowFn': '&gmfLayertreeOpenlinksinnewwindow'
    },
    bindToController: true,
    controller: 'GmfLayertreeController',
    controllerAs: 'gmfLayertreeCtrl',
    template: gmfLayertreeTemplate
  };
};

gmf.module.directive('gmfLayertree', gmf.layertreeDirective);


/**
 * @param {angular.$http} $http Angular http service.
 * @param {angular.$sce} $sce Angular sce service.
 * @param {ngeo.CreatePopup} ngeoCreatePopup Popup service.
 * @param {ngeo.LayerHelper} ngeoLayerHelper Ngeo Layer Helper.
 * @param {string} gmfWmsUrl URL to the wms service to use by default.
 * @constructor
 * @export
 * @ngInject
 * @ngdoc controller
 * @ngname gmfLayertreeController
 */
gmf.LayertreeController = function($http, $sce, ngeoCreatePopup,
    ngeoLayerHelper, gmfWmsUrl) {

  /**
   * @private
   * @type {angular.$http}
   */
  this.$http_ = $http;

  /**
   * @private
   * @type {angular.$sce}
   */
  this.$sce_ = $sce;

  /**
   * @type {string}
   * @private
   */
  this.gmfWmsUrl_ = gmfWmsUrl;

  /**
   * @type {ngeo.LayerHelper}
   * @private
   */
  this.layerHelper_ = ngeoLayerHelper;

  /**
   * @private
   * @type {ngeo.Popup}
   */
  this.infoPopup_ = ngeoCreatePopup();

  /**
   * @type {Object.<string, !angular.$q.Promise>}
   * @private
   */
  this.promises_ = {};

  /**
   * @type {Object.<number, Array.<string>>}
   * @private
   */
  this.groupNodeStates_ = {};

  /**
   * @type {boolean}
   * @export
   */
  this.openLinksInNewWindow = this['openLinksInNewWindowFn']() === true ?
      true : false;
};


/**
 * @const
 */
gmf.LayertreeController.TYPE_MIXEDGROUP = 'MixedGroup';


/**
 * @const
 */
gmf.LayertreeController.TYPE_NOTMIXEDGROUP = 'NotMixedGroup';


/**
 * @const
 */
gmf.LayertreeController.TYPE_WMTS = 'WMTS';


/**
 * @const
 */
gmf.LayertreeController.TYPE_EXTERNALWMS = 'externalWMS';


/**
 * @const
 */
gmf.LayertreeController.TYPE_WMS = 'WMS';


/**
 * Return a "type" that defines the node.
 * @param {GmfThemesNode} node Layer tree node.
 * @return {string} A type.
 * @private
 */
gmf.LayertreeController.prototype.getNodeType_ = function(node) {
  var children = node.children;
  var mixed = node.mixed;
  if (goog.isDef(node.children) && mixed) {
    return gmf.LayertreeController.TYPE_MIXEDGROUP;
  }
  if (goog.isDef(children) && !mixed) {
    return gmf.LayertreeController.TYPE_NOTMIXEDGROUP;
  }
  if (node.type === 'WMTS') {
    return gmf.LayertreeController.TYPE_WMTS;
  }
  if (goog.isDefAndNotNull(node.url)) {
    return gmf.LayertreeController.TYPE_EXTERNALWMS;
  }
  return gmf.LayertreeController.TYPE_WMS;
};


/**
 * Create and return a layer corresponding to the ngeo layertree's node.
 * This function will only create a layer for each "top-level" (depth 1) groups.
 *
 * On "not mixed" type nodes, the returned layer will be an ol.layer.Image (WMS)
 * with each name of node's children as LAYERS parameters.
 *
 * On "mixed" type node, the returned  layer will be an ol.layer.Group with
 * a collection of layers that corresponds to each children of the node.
 *
 * All layer created will receive:
 *  - A 'querySourceId' parameter with the node id as value.
 *  - A 'layerName' parameter with the node name as value.
 *
 * All layer created will be added at the top of the map and with a Z Index
 * value of 1.
 *
 * If the node metadata 'isChecked' value is false, the layer visibility will
 * be set to false.
 * @param {GmfThemesNode} node Layer tree node.
 * @param {number=} opt_depth ngeo layertree node depth.
 * @param {boolean=} opt_createWMS True to allow create wms layer.
 * @return {ol.layer.Base} The OpenLayers layer or group for the node.
 * @export
 */
gmf.LayertreeController.prototype.getLayer = function(node, opt_depth,
        opt_createWMS) {
  var type = this.getNodeType_(node);
  var layer = null;

  if (opt_depth === 1) {
    switch (type) {
      case gmf.LayertreeController.TYPE_MIXEDGROUP:
        return this.getLayerCaseMixedGroup_(node);
      case gmf.LayertreeController.TYPE_NOTMIXEDGROUP:
        layer = this.getLayerCaseNotMixedGroup_(node);
        break;
    }
    switch (type) {
      case gmf.LayertreeController.TYPE_WMTS:
        layer = this.getLayerCaseWMTS_(node);
        break;
      case gmf.LayertreeController.TYPE_WMS:
      case gmf.LayertreeController.TYPE_EXTERNALWMS:
        var url = node.url || this.gmfWmsUrl_;
        layer = opt_createWMS ?
            this.layerHelper_.createBasicWMSLayer(url, node.name) : null;
        break;
    }
  }

  if (goog.isDefAndNotNull(layer)) {
    layer.set('querySourceId', node.id);
    layer.set('layerName', node.name);
    // The layer must be upper than the background
    layer.setZIndex(1);
    // Add the new layer on the map but behind (before) others layers
    this.map.getLayerGroup().getLayers().insertAt(0, layer);

    // If layer is 'unchecked', set it to invisible.
    var metadata = node.metadata;
    if (!goog.isDef(node.children) && goog.isDefAndNotNull(metadata)) {
      if (metadata['isChecked'] != 'true') {
        layer.setVisible(false);
      }
    }
  }

  return layer;
};


/**
 * Create an ol.layer.Group with all node's children as layers except others
 * groups.
 * @param {GmfThemesNode} node Layer tree node.
 * @return {ol.layer.Group} Layer group.
 * @private
 */
gmf.LayertreeController.prototype.getLayerCaseMixedGroup_ = function(node) {
  var i, child, children = node.children;
  var layers = new ol.Collection();
  var layer, subNode;
  var subNodes = [];
  var nodeNames = [];
  this.getFlatNodes_(node, subNodes);
  for (i = 0; i < subNodes.length; i++) {
    subNode = subNodes[i];
    // Create all sublayers include wms layers;
    layer = this.getLayer(subNode, 1, true);
    if (goog.isDefAndNotNull(layer)) {
      layers.push(layer);
      nodeNames.push(subNode.name);
    }
  }
  var group = this.layerHelper_.createBasicGroup(layers);

  // Keep a reference to this group.
  this.groupNodeStates_[goog.getUid(group)] = [];
  return group;
};


/**
 * Create an ol.layer.Image with all node's children as LAYERS params.
 * @param {GmfThemesNode} node Layer tree node.
 * @return {ol.layer.Image} Image layer.
 * @private
 */
gmf.LayertreeController.prototype.getLayerCaseNotMixedGroup_ = function(node) {
  var names = this.retrieveNodeNames_(node, true);
  var url = node.url || this.gmfWmsUrl_;
  var layer = this.layerHelper_.createBasicWMSLayer(url, '');
  this.updateWMSLayerState_(layer, names);

  // Keep a reference to this group with all layer name inside.
  this.groupNodeStates_[goog.getUid(layer)] = [];

  return layer;
};


/**
 * Create an ol.layer.Tile layer.
 * @param {GmfThemesNode} node Layertree node.
 * @return {ol.layer.Tile} The OpenLayers layer or group for the node.
 * @private
 */
gmf.LayertreeController.prototype.getLayerCaseWMTS_ = function(node) {
  var newLayer = new ol.layer.Tile();
  this.layerHelper_.createWMTSLayerFromCapabilitites(node.url || '', node.name)
    .then(function(layer) {
      newLayer.setSource(layer.getSource());
      newLayer.set('capabilitiesStyles', layer.get('capabilitiesStyles'));
    });
  return newLayer;
};


/**
 * Fill the given "nodes" array with all node in the given node including the
 * given node itself.
 * @param {GmfThemesNode} node Layertree node.
 * @param {Array.<GmfThemesNode>} nodes An array.
 * @private
 */
gmf.LayertreeController.prototype.getFlatNodes_ = function(node, nodes) {
  var i, child;
  var children = node.children;
  if (goog.isDef(children)) {
    for (i = 0; i < children.length; i++) {
      this.getFlatNodes_(children[i], nodes);
    }
  } else {
    nodes.push(node);
  }
};


/**
 * Return all names existing in a node and in its children.
 * @param {GmfThemesNode} node Layer tree node.
 * @param {boolean=} opt_onlyChecked return only 'isChecked' node names.
 * @return {Array.<string>} An Array of all nodes names.
 * @private
 */
gmf.LayertreeController.prototype.retrieveNodeNames_ = function(node,
    opt_onlyChecked) {<commit_msg>Fix no-unused-vars eslint error<commit_after>goog.provide('gmf.LayertreeController');
goog.provide('gmf.layertreeDirective');

goog.require('gmf');
goog.require('ngeo.CreatePopup');
goog.require('ngeo.LayerHelper');
goog.require('ngeo.LayertreeController');
goog.require('ol.Collection');
goog.require('ol.layer.Tile');


gmf.module.value('gmfLayertreeTemplate',
    /**
     * @param {angular.JQLite} element Element.
     * @param {angular.Attributes} attrs Attributes.
     * @return {string} Template.
     */
    function(element, attrs) {
      var subTemplateUrl = gmf.baseTemplateUrl + '/layertree.html';
      return '<div ngeo-layertree="gmfLayertreeCtrl.tree" ' +
          'ngeo-layertree-map="gmfLayertreeCtrl.map" ' +
          'ngeo-layertree-nodelayer="gmfLayertreeCtrl.getLayer(node, depth)" ' +
          'ngeo-layertree-listeners="gmfLayertreeCtrl.listeners(treeScope, ' +
          'treeCtrl)" ' +
          'ngeo-layertree-templateurl="' + subTemplateUrl + '"' +
          '</div>';
    });


// Overrides the path to the layertree template (used by each nodes, except
// the root node that path is defined by the gmfLayertreeTemplate value.
ngeo.module.value('ngeoLayertreeTemplateUrl',
    /**
     * @param {angular.JQLite} element Element.
     * @param {angular.Attributes} attrs Attributes.
     * @return {string} Template URL.
     */
    function(element, attrs) {
      return gmf.baseTemplateUrl + '/layertree.html';
    });


/**
 * This directive creates a layertree based on the c2cgeoportal JSON themes
 * source and a {@link ngeo.layertreeDirective}. The controller used by this
 * directive defines some fonctions for each node that are created by a default
 * template. This default template can be overrided by setting the constant
 * 'gmf.layertreeTemplateUrl' but you will must adapt the
 * ngeoLayertreeTemplateUrl value too (to define the children's nodes template
 * path).
 *
 * @example
 * <gmf-layertree
 *   gmf-layertree-source="ctrl.source"
 *   gmf-layertree-map="ctrl.map"
 * </gmf-layertree>
 *
 * You can add an attribute 'gmf-layertree-openlinksinnewwindow="true"' to open
 * metadata URLs in a new window. By default, and in the default template,
 * links will be opened in a popup.
 *
 * @param {string|function(!angular.JQLite=, !angular.Attributes=)}
 *     gmfLayertreeTemplate Template for the directive.
 * @return {angular.Directive} The directive specs.
 * @ngInject
 * @ngdoc directive
 * @ngname gmfLayertreeDirective
 */
gmf.layertreeDirective = function(gmfLayertreeTemplate) {
  return {
    scope: {
      'map': '=gmfLayertreeMap',
      'tree': '=gmfLayertreeSource',
      'openLinksInNewWindowFn': '&gmfLayertreeOpenlinksinnewwindow'
    },
    bindToController: true,
    controller: 'GmfLayertreeController',
    controllerAs: 'gmfLayertreeCtrl',
    template: gmfLayertreeTemplate
  };
};

gmf.module.directive('gmfLayertree', gmf.layertreeDirective);


/**
 * @param {angular.$http} $http Angular http service.
 * @param {angular.$sce} $sce Angular sce service.
 * @param {ngeo.CreatePopup} ngeoCreatePopup Popup service.
 * @param {ngeo.LayerHelper} ngeoLayerHelper Ngeo Layer Helper.
 * @param {string} gmfWmsUrl URL to the wms service to use by default.
 * @constructor
 * @export
 * @ngInject
 * @ngdoc controller
 * @ngname gmfLayertreeController
 */
gmf.LayertreeController = function($http, $sce, ngeoCreatePopup,
    ngeoLayerHelper, gmfWmsUrl) {

  /**
   * @private
   * @type {angular.$http}
   */
  this.$http_ = $http;

  /**
   * @private
   * @type {angular.$sce}
   */
  this.$sce_ = $sce;

  /**
   * @type {string}
   * @private
   */
  this.gmfWmsUrl_ = gmfWmsUrl;

  /**
   * @type {ngeo.LayerHelper}
   * @private
   */
  this.layerHelper_ = ngeoLayerHelper;

  /**
   * @private
   * @type {ngeo.Popup}
   */
  this.infoPopup_ = ngeoCreatePopup();

  /**
   * @type {Object.<string, !angular.$q.Promise>}
   * @private
   */
  this.promises_ = {};

  /**
   * @type {Object.<number, Array.<string>>}
   * @private
   */
  this.groupNodeStates_ = {};

  /**
   * @type {boolean}
   * @export
   */
  this.openLinksInNewWindow = this['openLinksInNewWindowFn']() === true ?
      true : false;
};


/**
 * @const
 */
gmf.LayertreeController.TYPE_MIXEDGROUP = 'MixedGroup';


/**
 * @const
 */
gmf.LayertreeController.TYPE_NOTMIXEDGROUP = 'NotMixedGroup';


/**
 * @const
 */
gmf.LayertreeController.TYPE_WMTS = 'WMTS';


/**
 * @const
 */
gmf.LayertreeController.TYPE_EXTERNALWMS = 'externalWMS';


/**
 * @const
 */
gmf.LayertreeController.TYPE_WMS = 'WMS';


/**
 * Return a "type" that defines the node.
 * @param {GmfThemesNode} node Layer tree node.
 * @return {string} A type.
 * @private
 */
gmf.LayertreeController.prototype.getNodeType_ = function(node) {
  var children = node.children;
  var mixed = node.mixed;
  if (goog.isDef(node.children) && mixed) {
    return gmf.LayertreeController.TYPE_MIXEDGROUP;
  }
  if (goog.isDef(children) && !mixed) {
    return gmf.LayertreeController.TYPE_NOTMIXEDGROUP;
  }
  if (node.type === 'WMTS') {
    return gmf.LayertreeController.TYPE_WMTS;
  }
  if (goog.isDefAndNotNull(node.url)) {
    return gmf.LayertreeController.TYPE_EXTERNALWMS;
  }
  return gmf.LayertreeController.TYPE_WMS;
};


/**
 * Create and return a layer corresponding to the ngeo layertree's node.
 * This function will only create a layer for each "top-level" (depth 1) groups.
 *
 * On "not mixed" type nodes, the returned layer will be an ol.layer.Image (WMS)
 * with each name of node's children as LAYERS parameters.
 *
 * On "mixed" type node, the returned  layer will be an ol.layer.Group with
 * a collection of layers that corresponds to each children of the node.
 *
 * All layer created will receive:
 *  - A 'querySourceId' parameter with the node id as value.
 *  - A 'layerName' parameter with the node name as value.
 *
 * All layer created will be added at the top of the map and with a Z Index
 * value of 1.
 *
 * If the node metadata 'isChecked' value is false, the layer visibility will
 * be set to false.
 * @param {GmfThemesNode} node Layer tree node.
 * @param {number=} opt_depth ngeo layertree node depth.
 * @param {boolean=} opt_createWMS True to allow create wms layer.
 * @return {ol.layer.Base} The OpenLayers layer or group for the node.
 * @export
 */
gmf.LayertreeController.prototype.getLayer = function(node, opt_depth,
        opt_createWMS) {
  var type = this.getNodeType_(node);
  var layer = null;

  if (opt_depth === 1) {
    switch (type) {
      case gmf.LayertreeController.TYPE_MIXEDGROUP:
        return this.getLayerCaseMixedGroup_(node);
      case gmf.LayertreeController.TYPE_NOTMIXEDGROUP:
        layer = this.getLayerCaseNotMixedGroup_(node);
        break;
    }
    switch (type) {
      case gmf.LayertreeController.TYPE_WMTS:
        layer = this.getLayerCaseWMTS_(node);
        break;
      case gmf.LayertreeController.TYPE_WMS:
      case gmf.LayertreeController.TYPE_EXTERNALWMS:
        var url = node.url || this.gmfWmsUrl_;
        layer = opt_createWMS ?
            this.layerHelper_.createBasicWMSLayer(url, node.name) : null;
        break;
    }
  }

  if (goog.isDefAndNotNull(layer)) {
    layer.set('querySourceId', node.id);
    layer.set('layerName', node.name);
    // The layer must be upper than the background
    layer.setZIndex(1);
    // Add the new layer on the map but behind (before) others layers
    this.map.getLayerGroup().getLayers().insertAt(0, layer);

    // If layer is 'unchecked', set it to invisible.
    var metadata = node.metadata;
    if (!goog.isDef(node.children) && goog.isDefAndNotNull(metadata)) {
      if (metadata['isChecked'] != 'true') {
        layer.setVisible(false);
      }
    }
  }

  return layer;
};


/**
 * Create an ol.layer.Group with all node's children as layers except others
 * groups.
 * @param {GmfThemesNode} node Layer tree node.
 * @return {ol.layer.Group} Layer group.
 * @private
 */
gmf.LayertreeController.prototype.getLayerCaseMixedGroup_ = function(node) {
  var i;
  var layers = new ol.Collection();
  var layer, subNode;
  var subNodes = [];
  var nodeNames = [];
  this.getFlatNodes_(node, subNodes);
  for (i = 0; i < subNodes.length; i++) {
    subNode = subNodes[i];
    // Create all sublayers include wms layers;
    layer = this.getLayer(subNode, 1, true);
    if (goog.isDefAndNotNull(layer)) {
      layers.push(layer);
      nodeNames.push(subNode.name);
    }
  }
  var group = this.layerHelper_.createBasicGroup(layers);

  // Keep a reference to this group.
  this.groupNodeStates_[goog.getUid(group)] = [];
  return group;
};


/**
 * Create an ol.layer.Image with all node's children as LAYERS params.
 * @param {GmfThemesNode} node Layer tree node.
 * @return {ol.layer.Image} Image layer.
 * @private
 */
gmf.LayertreeController.prototype.getLayerCaseNotMixedGroup_ = function(node) {
  var names = this.retrieveNodeNames_(node, true);
  var url = node.url || this.gmfWmsUrl_;
  var layer = this.layerHelper_.createBasicWMSLayer(url, '');
  this.updateWMSLayerState_(layer, names);

  // Keep a reference to this group with all layer name inside.
  this.groupNodeStates_[goog.getUid(layer)] = [];

  return layer;
};


/**
 * Create an ol.layer.Tile layer.
 * @param {GmfThemesNode} node Layertree node.
 * @return {ol.layer.Tile} The OpenLayers layer or group for the node.
 * @private
 */
gmf.LayertreeController.prototype.getLayerCaseWMTS_ = function(node) {
  var newLayer = new ol.layer.Tile();
  this.layerHelper_.createWMTSLayerFromCapabilitites(node.url || '', node.name)
    .then(function(layer) {
      newLayer.setSource(layer.getSource());
      newLayer.set('capabilitiesStyles', layer.get('capabilitiesStyles'));
    });
  return newLayer;
};


/**
 * Fill the given "nodes" array with all node in the given node including the
 * given node itself.
 * @param {GmfThemesNode} node Layertree node.
 * @param {Array.<GmfThemesNode>} nodes An array.
 * @private
 */
gmf.LayertreeController.prototype.getFlatNodes_ = function(node, nodes) {
  var i;
  var children = node.children;
  if (goog.isDef(children)) {
    for (i = 0; i < children.length; i++) {
      this.getFlatNodes_(children[i], nodes);
    }
  } else {
    nodes.push(node);
  }
};


/**
 * Return all names existing in a node and in its children.
 * @param {GmfThemesNode} node Layer tree node.
 * @param {boolean=} opt_onlyChecked return only 'isChecked' node names.
 * @return {Array.<string>} An Array of all nodes names.
 * @private
 */
gmf.LayertreeController.prototype.retrieveNodeNames_ = function(node,
    opt_onlyChecked) {
{'fraction_non_alphanumeric': 0.12827644729398455, 'fraction_numerical': 0.0008485762775787291, 'mean_word_length': 3.492376111817027, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3419768', 'n_tokens_mistral': 7243, 'n_tokens_neox': 7107, 'n_words': 1733}