"use strict";
define(function () {
  var EditRuleSnappedOnFeature = {

    $get: function (
      $q,
      $filter,
      RuleCfgFactory,
      EditTypesFactory,
      FeatureTypeFactory
      ) {

      /**
       * check if configLayersToSnapOn
       * @param {Array} configLayersToSnapOn array of objects: [{layerName: 'a', shareObjectName: 'b'}, ...]
       * @param {Object} editdescription 
       * @returns 
       */
      const isRuleRespected = (configLayersToSnapOn, editdescription) => {
        let isRuleRespected = false
        if (editdescription && Array.isArray(editdescription.shareObjects)) {
          //at least one layerconf should be true
          for (const layerConf of configLayersToSnapOn) {
            if (editdescription.shareObjects.some(
              shareObject => shareObject.shareObject === layerConf.shareObjectName
                && shareObject.fti.name === layerConf.layerName)) {
              isRuleRespected = true;
            }
          }
        }
        return isRuleRespected;
      };

      /**
       * Gerenic process of edit rules :
       *  - StartLineSnappedOnPoint
       *  - EndLineSnappedOnPoint
       *  - StartLineSnappedOnLine
       *  - EndLineSnappedOnLine
       * @param {Object} editdescription 
       * @param {Object} ruleConf 
       * @param {Object} featureType 
       * @param {String} geometryType 'point' or 'line'
       */
      const lineSnappedOn = (editdescription, ruleConf, featureType, geometryType) => {
        const configLayersToSnapOn = ruleConf && ruleConf.parameters ? ruleConf.parameters.layersToSnapOn : [];
        const deferred = $q.defer();

        if (isRuleRespected(configLayersToSnapOn, editdescription)) {
          deferred.resolve();
        } else {
          let errorMessage;
          if (geometryType === 'point') {
            errorMessage = $filter('translate')('rulecfg.lineSnappedOnFeature.errorMessagePt1')
              + featureType.alias
              + $filter('translate')('rulecfg.lineSnappedOnFeature.errorMessagePt2Point')
              + configLayersToSnapOn.map(layerConf => layerConf.layerName).join(', ');
          } else {
            errorMessage = $filter('translate')('rulecfg.lineSnappedOnFeature.errorMessagePt1')
              + featureType.alias
              + $filter('translate')('rulecfg.lineSnappedOnFeature.errorMessagePt2Line')
              + configLayersToSnapOn.map(layerConf => layerConf.layerName).join(', ');
          }
          require('toastr').error(errorMessage);
          deferred.reject();
        }
        return deferred.promise;
      };

      const startLineSnappedOnPoint = (editdescription, ruleConf, featureType, map) => {
        return lineSnappedOn(editdescription, ruleConf, featureType, 'point')
      };

      const endLineSnappedOnPoint = (editdescription, ruleConf, featureType, map) => {
        return lineSnappedOn(editdescription, ruleConf, featureType, 'point')
      };

      const startLineSnappedOnLine = (editdescription, ruleConf, featureType, map) => {
        return lineSnappedOn(editdescription, ruleConf, featureType, 'line')
      };

      const endLineSnappedOnLine = (editdescription, ruleConf, featureType, map) => {
        return lineSnappedOn(editdescription, ruleConf, featureType, 'line')
      };

      //
      ///  GENERIC FUNCTIONS RELATED TO CONFIGURATION OF THE EDIT RULES
      //

      /**
       * 
       * @param {*} scope 
       * @param {*} ruleName 
       * @param {*} layerTypeToSnapOn uppercase 'LINE' or 'POINT'
       */
      const configInitRule = (scope, ruleName, layerTypeToSnapOn) => {
        scope.rule.name = ruleName;
        scope.rule.type = 'OnEnd';
        //init edit type 
        const editTypesSource = [
          EditTypesFactory.editTypes.add,
          EditTypesFactory.editTypes.update,
        ];
        RuleCfgFactory.initEditTypeList(scope, editTypesSource);
        //get layer list
        FeatureTypeFactory.get().then( allFtis => {
          if (Array.isArray(allFtis)) {
            scope.ftis = allFtis.filter(fti => fti.typeInfo === layerTypeToSnapOn);
          }
        }, error => {
          console.error('error getting fti list');
        });
        if (scope.rule.parameters == undefined) {
          scope.rule.parameters = getDefaultConfig();
        }
        // Récupération de la liste des noms des objets partagés entre les règles
        RuleCfgFactory.listAllSharedObjects(scope);
      }

      const getDefaultConfig = () => {
        return {
          layersToSnapOn: [],
        }
      };

      const configAddLayer = (rule, layerToSnapOn) => {
        if (!rule.parameters.layersToSnapOn.find(it => it.layerName === layerToSnapOn)) {
          rule.parameters.layersToSnapOn.push(
            {
              layerName: layerToSnapOn,
              shareObjectName: '',
            });
        }
      };

      const configRemoveLayer = (rule, index) => {
        rule.parameters.layersToSnapOn.splice(index, 1);
      };

      return {
        startLineSnappedOnPoint: startLineSnappedOnPoint,
        endLineSnappedOnPoint: endLineSnappedOnPoint,
        startLineSnappedOnLine: startLineSnappedOnLine,
        endLineSnappedOnLine: endLineSnappedOnLine,
        configInitRule: configInitRule,
        configAddLayer: configAddLayer,
        configRemoveLayer: configRemoveLayer,
      };
    }
  };

  EditRuleSnappedOnFeature.$get.$inject = [
    '$q',
    '$filter',
    'RuleCfgFactory',
    'EditTypesFactory',
    'FeatureTypeFactory'
  ];
  return EditRuleSnappedOnFeature;
});