'use strict';
define(function() {
  var gcelement = function(
    EditRulesFactory,
    ogcFactory,
    EditTypesFactory,
    gcStyleFactory,
    SelectManager,
    $translate,
    gclayers,
    gcInteractions
  ) {
    return {
      templateUrl: 'js/XG/widgets/mapapp/bizedition/views/bizeditdepose.html',
      restrict: 'E',
      scope: {
        map: '=map',
        selectfti: '=selectfti',
        editdescription: '=editdescription',
        isActive: '=isactive',
        menuContext: '=menucontext',
        toolbarwidget: '=?toolbarwidget',
        createeditdescription: '&',
        reset: '&',
      },

      link: function(scope, element, attrs, ctrl) {
        scope.isActive = false;
        var format = new ol.format.GeoJSON();
        var map = scope.map;

        /*SelectionMode: outil utilisé pour sélectionner les objets à éditer
                  normal: dessin d'un cadre
                  polygon: dessin d'un polygon
                  query; récupération d'une sélection courante (après l'utilisation du requeteur)
                */
        scope.selectionMode = { value: 'normal' };

        /**
         * new: chaque nouvelle sélection remplace les objet sélectionné préalablement.
         * add: chaque nouvelle sélection ajoute les objets à la liste des objets édités.
         */
        scope.selectionType = { value: 'new' };

        var selectedFeatures = [];

        var noResultMsg = 'No Result';
        $translate('bizedition.attributesPopupNoResult').then(function(res) {
          noResultMsg = res;
        });

        /**
         * Méthode appelée au clic sur le bouton correspondant à cette directive.
         * @returns {undefined}
         */
        scope.performRules = function() {
          //Activation si désactivé et desactivation si activé
          scope.reset();
          scope.isActive = !scope.isActive;
          draw.setActive(scope.isActive);
          if (scope.isActive) {
            console.log(scope.menuContext);
            if (scope.menuContext && scope.menuContext.length > 2) {
              scope.menuContext.splice(0, scope.menuContext.length - 2);
            }
          }
          dragBox.setActive(scope.isActive);
          if (!scope.isActive) {
            return;
          }

          selectedFeatures.splice(0);

          scope.editdescription = scope.createeditdescription();
          if(scope.editdescription === undefined) return;
          scope.editdescription.editType =
            EditTypesFactory.editTypes.todepose.name;
          scope.editdescription.fti = scope.selectfti;

          var promise = EditRulesFactory.executeInitRules(
            scope.editdescription,
            scope.selectfti,
            map
          );
          promise.then(function() {
            scope.selectfeaturesToRemove();
          });
        };

        /**
         * Active une méthode de sélection de features
         * @returns {undefined}
         */
        scope.selectfeaturesToRemove = function() {
          //Si option de sélection de features par dessin d'un polygone
          if (scope.selectionMode.value == 'polygon') {
            map.removeInteraction(dragBox);
            gcInteractions.setCurrentToolBar(scope.toolbarwidget);
            map.addInteraction(draw);
            //Enregistrement de la reference vers l'interaction pour la retirer de la carte au besoin.
            scope.editdescription.interactions.push(draw);
          } else if (scope.selectionMode.value == 'query') {
            map.removeInteraction(dragBox);
            map.removeInteraction(draw);
            var res = {};
            res.data = SelectManager.getFeaturesByftiType(scope.selectfti.name);
            onSelectionResult(res);
          } else {
            map.removeInteraction(draw);
            gcInteractions.setCurrentToolBar(scope.toolbarwidget);
            map.addInteraction(dragBox);
            //Enregistrement de la reference vers l'interaction pour la retirer de la carte au besoin.
            scope.editdescription.interactions.push(dragBox);
          }
        };

        //Interaction de dessin d'un cadre pour sélectionner des features sur la carte.
        var dragBox = new ol.interaction.DragBox({
          condition: function(evt) {
            //MacEnvironments don't get here because the event is not
            //recognized as mouseEvent on Mac by the google closure.
            //We have to use the apple key on those devices
            return (
              evt.originalEvent.ctrlKey || scope.isActive
            ); /* ||
                      (gaBrowserSniffer.mac && evt.originalEvent.metaKey);*/
          },
          style: gcStyleFactory.getStyle('selectrectangle'),
        });
        dragBox.setActive(false);
        dragBox.set('gctype', 'kis');
        dragBox.set('interaction', 'Select');
        dragBox.set('widget', 'Edition');

        //Interaction de dessin d'un polygone pour sélectionner des features sur la carte.
        var draw = new ol.interaction.Draw({
          type: 'Polygon',
        });
        draw.setActive(false);
        draw.set('gctype', 'kis');
        draw.set('interaction', 'Draw');
        draw.set('widget', 'Edition');

        /**
         * Handler de fin de dessin de polygone de sélection d'objet sur la carte.
         * Permetr de requeter les objets features de la couche sélectionnée, situés à l'intérieur du dessin.
         */
        draw.on('drawend', function(evt) {
          //Fermeture de l'eventuelle popup déjà ouverte.
          if (scope.p != undefined && scope.p.element != null)
            scope.p.destroy();

          //Récupération de la géométrie dessinée
          const polygon = evt.feature.getGeometry();
          const srid = map.getView().getProjection().getCode();
          ogcFactory.findIntersectedFeaturesByPolygon(polygon, srid, scope.editdescription.fti.uid).then(
              onSelectionResult,
              error => {
                console.error('ogcFactory.getfeatures, error:' + error);
                require('toastr').error(error);
              });
        });

        dragBox.on('boxend', function(evt) {
          //Instanciation de l'objet editdescription à chaque nouvelle sélection
          //                    scope.createeditdescription();
          //                    scope.editdescription.editType = EditTypesFactory.editTypes.todepose.name;
          //                    scope.editdescription.fti = scope.selectfti;
          //                    //Enregistrement de la reference vers l'interaction pour la retirer de la carte au besoin.
          //                    scope.editdescription.interactions.push(dragBox);

          //Recherche des objets intersectés par l'intersection
          var extent = dragBox.getGeometry().getExtent();
          var leftX = extent[0];
          var topY = extent[3];
          var rightX = extent[2];
          var bottomY = extent[1];

          var cql_filter =
            'INTERSECTS(geom, POLYGON((' +
            leftX +
            ' ' +
            bottomY +
            ',' +
            rightX +
            ' ' +
            bottomY +
            ',' +
            rightX +
            ' ' +
            topY +
            ',' +
            leftX +
            ' ' +
            topY +
            ',' +
            leftX +
            ' ' +
            bottomY +
            ')))';
          var promise = ogcFactory.getfeatures(
            'GetFeature',
            'WFS',
            '1.0.0',
            scope.editdescription.fti.uid,
            'json',
            map
              .getView()
              .getProjection()
              .getCode(),
            cql_filter
          );
          promise.then(onSelectionResult, function(error) {
            console.error('ogcFactory.getfeatures, error:' + error);
            require('toastr').error(error);
          });

          //Si on veut sélectionner plusieurs fois, on enleve pas l'interaction.
          //map.removeInteraction(dragBox);
        }); //en dragBox.end

        /**
         * Utilitaire: indique si le feature passé en paramètre appartient déjà à la sélection.
         * @param {type} feature
         * @returns {Boolean}
         */
        function isFeatureToAdd(feature) {
          for (var i = 0; i < selectedFeatures.length; i++) {
            if (feature.getId() == selectedFeatures[i].getId()) {
              return false;
            }
          }
          return true;
        }

        /**
         * Appelée lors de la réponse de requete de séléction de features
         * @param {type} res
         * @returns {undefined}
         */
        function onSelectionResult(res) {
          //Instanciation de l'objet editdescription à chaque nouvelle sélection si on veut prendre en compte
          //dynamiquement les changement de type de sélection
          //scope.createeditdescription();
          //                    scope.editdescription.editType = EditTypesFactory.editTypes.delete.name;
          //                    scope.editdescription.fti = scope.selectfti;
          require('toastr').clear();
          if (res.data.features == undefined || res.data.features.length == 0) {
            require('toastr').warning(noResultMsg);
            return;
          }

          //Decodage de la featureCollection, retourne un tableau de ol.feature
          //Si mode nouvelle sélection à chaque fois
          if (scope.selectionType.value == 'new') {
            selectedFeatures = format.readFeatures(res.data);
          }
          //Si la sélection actuelle d'objets doit s'ajouter à la précedente sélection
          else if (scope.selectionType.value == 'add') {
            //Récupération de la nouvelle sélection
            var partialSelection = format.readFeatures(res.data);
            //Filtrage pour ne récupérer que des nouveaux features non précedement sélectionnés
            partialSelection = partialSelection.filter(isFeatureToAdd);
            //Ajout des nouveaux features à la sélection
            selectedFeatures = selectedFeatures.concat(partialSelection);
          }
          //Par defaut, nouvelle sélection
          else {
            selectedFeatures = format.readFeatures(res.data);
          }

          //Mise en evidence des features sélectionnés
          gclayers.getselectSource().clear();
          gclayers.getselectSource().addFeatures(selectedFeatures);

          //Suppression des eventuels precedents features presents dans editDescription
          scope.editdescription.editedfeature = undefined;
          scope.editdescription.relatedfeatures.splice(0);
          scope.editdescription.shareObjects.splice(0);

          //editDescription
          if (selectedFeatures.length > 0) {
            scope.editdescription.editedfeature = selectedFeatures[0];
          }
          for (var i = 1; i < selectedFeatures.length; i++) {
            var newObject = {
              shareObject: '',
              editType: EditTypesFactory.editTypes.todepose.name,
              feature: selectedFeatures[i],
              fti: scope.editdescription.fti,
            };
            scope.editdescription.relatedfeatures.push(newObject);
          }

          //Si au moins un objet trouvé, alors lancement des règles métier 'onend'.
          if (scope.editdescription.editedfeature != undefined) {
            //execution des règles end.
            var promise = EditRulesFactory.executeEndRules(
              scope.editdescription,
              scope.editdescription.fti,
              map
            );
            promise.then(
              function() {
                var t = 0;
                if (
                  scope.editdescription.relatedfeatures &&
                  scope.editdescription.relatedfeatures.length > 0
                ) {
                  scope.editdescription.relatedfeatures.map(function(x) {
                    if (
                      x.editType &&
                      x.editType !== EditTypesFactory.editTypes.todepose.name
                    )
                      x.editType = EditTypesFactory.editTypes.todepose.name;
                  });
                }
              },
              function(errorReason) {
                console.error(
                  'EditRulesFactory.executeEndRules, error:' + errorReason
                );
                require('toastr').error('executeEndRules error.');
              }
            );
          }
        }
      },
    };
  };

  gcelement.$inject = [
    'EditRulesFactory',
    'ogcFactory',
    'EditTypesFactory',
    'gcStyleFactory',
    'SelectManager',
    '$translate',
    'gclayers',
    'gcInteractions',
  ];
  return gcelement;
});
