'use strict';
define(function() {
  var pv2Config = function( $filter, ParametersFactory, $q, PrintModelFactory,
    ngDialog, gaJsUtils
  ) {
    function addMissingLayersToAskedLayers(cfgResult, $scope) {
      var layerList, ind, iBlock, lb;
      var view = $scope.map.getView();
      var proj = view.getProjection();

      //-- Récupération de la liste des couches dessinables.
      if ($scope.options.asVisibleOnMap == 'asVisibleOnMap')
        layerList = $scope.getVisibleLayers(proj);
      else layerList = $scope.getLayersConfiguredForScale(proj);

      //-- On vérifie si une des couches manque dans la liste
      //-- des couches potentiellement dessinables du paramétre.

      if (angular.isDefined(cfgResult) && cfgResult.length) {
        for (iBlock = 0; iBlock < cfgResult.length; iBlock++) {
          lb = cfgResult[iBlock];
          if (!lb.askedLegendLayers) lb.askedLegendLayers = [];
          for (ind = 0; ind < layerList.length; ind++) {
            //-- Si la couche fait partie de celles à ignorer, on ne l'ajoute pas dans la liste.'
            //if (ignoredLegendLayers!=undefined && ignoredLegendLayers.indexOf(layerList[ind])!=-1)
            //    continue;
            if (lb.askedLegendLayers.indexOf(layerList[ind]) == -1)
              lb.askedLegendLayers.push(layerList[ind]);
          }
        }
        return lb.askedLegendLayers;
      }

      cfgResult[0] = {};
      cfgResult[0].askedLegendLayers = [];
      cfgResult[0].askedLegendLayers = cfgResult[0].askedLegendLayers.concat(
        layerList
      );

      return angular.copy(cfgResult[0].askedLegendLayers);
    }

    function initResultConfig(name, legends, $scope) {
      var promise, defer;
      if ($scope.initResultConfigName == name) {
        defer = $q.defer();
        promise = defer.promise;
        $scope.printLegCfg.result = angular.isDefined($scope.printLegCfg.result)
          ? $scope.printLegCfg.result
          : [];
        legends = addMissingLayersToAskedLayers(
          $scope.printLegCfg.result,
          $scope
        );
        defer.resolve();
      } else {
        $scope.resultConfig = $scope.resultConfig || [];
        $scope.resultConfig.splice(0);
        //legends = legends.map(function(x){return x.name;});
        promise = PrintModelFactory.getmodel(name);
        promise.then(
          function(res) {
            if (res.data && res.data.elements && res.data.elements.length > 0) {
              var number = res.data.elements
                .map(function(x) {
                  if (
                    x &&
                    x.data &&
                    x.data.class &&
                    x.data.class ===
                      'org.mapfish.print.config.layout.LegendsBlock'
                  )
                    return x;
                })
                .filter(function(x) {
                  if (x) return x;
                });
              var basic = {
                status: 'overflow',
                shrinkFactor: undefined,
                layerFontSize: undefined,
                classFontSize: undefined,
                themeFontSize: undefined,
                askedColumnNumber: undefined,
                askedLegendLayers: [],
                realLegendLayers: undefined,
                selected: {},
                hidealert: true,
              };
              number.map(function(x) {
                var b = angular.copy(basic);
                b.name = x.data.name || x.type + ' ' + x.id;
                $scope.resultConfig.push(b);
              });
            }
            legends = addMissingLayersToAskedLayers(
              $scope.resultConfig,
              $scope
            );
          },
          function(res) {
            console.error('unable to get model');
          }
        );
        $scope.initResultConfigName = name;
      }
      return promise;
    }

    function getInfoFromSynthese(callType, $scope) {
      if (
        callType == 'synthese' &&
        $scope.printLegCfg.result &&
        $scope.printLegCfg.result.length > 0
      )
        $scope.printLegCfg.result.map(function(x) {
          if (x.shrinkFactor != undefined)
            x.shrinkFactor = parseFloat(x.shrinkFactor).toFixed(2);
          if (x && x.askedLegendLayers) {
            if (!x.selected) x.selected = {};
            if (!x.askedButNotDrawn) x.askedButNotDrawn = {};
            $.unique(x.askedLegendLayers).map(function(y) {
              var keys;
              if (x.selected == undefined) x.selected = {};
              keys = Object.keys(x.selected);
              if (y && keys.indexOf(y) === -1) {
                if (
                  x.ignoredLegendLayers &&
                  x.ignoredLegendLayers.length > 0 &&
                  x.ignoredLegendLayers.indexOf(y) != -1
                ) {
                  x.selected[y] = false;
                } else {
                  x.selected[y] = true;
                }
              }

              //-- Si la couche est dans la liste des couches traitées (askedLegendLayers),
              if (x.askedLegendLayers && x.askedLegendLayers.indexOf(y) != -1) {
                //-- Si elle est dans la listes des couches
                //-- à ne pas mettre dans la légende pas de surlignage.
                if (
                  x.ignoredLegendLayers != undefined &&
                  x.ignoredLegendLayers.indexOf(y) != -1
                )
                  x.askedButNotDrawn[y] = '';
                //false;
                //-- Elle est dans la liste des couches à metre dans la légende
                //-- mais n'est pas dessinée (et la dialogue
                //-- est en mode synthese et non paramétrage)
                else if (
                  x.realLegendLayers != undefined &&
                  x.realLegendLayers.indexOf(y) == -1
                ) {
                  if ($scope.printLegendLayersWithoutObjects.indexOf(y) == -1)
                    x.askedButNotDrawn[y] = 'printLegAskedNotDrawn';
                  //true;
                  else x.askedButNotDrawn[y] = 'printLegAskedNoObject'; //true;
                } else x.askedButNotDrawn[y] = ''; //false;
              } else x.askedButNotDrawn[y] = ''; //false;
            });
          }
        });
    }

    function setDefaultParamValuesFromlayoutCopyParams(
      legBlockData,
      $scope,
      ind,
      fromApplied
    ) {
      if (legBlockData != undefined) {
        if ($scope.printLegCfg.result == undefined)
          $scope.printLegCfg.result = [];
        $scope.printLegCfg.result.splice(ind, 1);
        $scope.printLegCfg.result.push({});
        var ex = $scope.printLegCfg.result[ind];
        ex.status = '';
        if (fromApplied) ex.shrinkFactor = legBlockData.shrinkFactor;
        else ex.shrinkFactor = 1;
        ex.layerFontSize = legBlockData.layerFontSize;
        ex.classFontSize = legBlockData.classFontSize;
        if (legBlockData.themeFontSize == undefined)
          ex.themeFontSize = legBlockData.classFontSize + 1;
        else ex.themeFontSize = legBlockData.themeFontSize;
        if (legBlockData.columnNumber != undefined)
          ex.askedColumnNumber = legBlockData.columnNumber;
        else if (legBlockData.askedColumnNumber != undefined)
          ex.askedColumnNumber = legBlockData.askedColumnNumber;

        ex.forceFactor = legBlockData.forceFactor;
        ex.forceThemeFontSize = legBlockData.forceThemeFontSize;
        ex.forceLayerFontSize = legBlockData.forceLayerFontSize;
        ex.forceClassFontSize = legBlockData.forceClassFontSize;
        ex.forceColumnNumber = legBlockData.forceColumnNumber;

        ex.name = legBlockData.name;
        ex.askedLegendLayers = addMissingLayersToAskedLayers(
          $scope.printLegCfg.result,
          $scope
        );
        if (!fromApplied) {
          ex.selected = {};
          ex.askedLegendLayers.map(function(x) {
            ex.selected[x] = true;
          });
        }
      }
    }

    function setDefaultParamValuesFromlayout(callType, $scope) {
      if (
        callType == 'parametrage' &&
        ($scope.currentConfig == undefined ||
          $scope.appliedLegConfig != undefined)
      ) {
        if ($scope.currentConfig == undefined)
          PrintModelFactory.getmodel($scope.layout.name).then(function(res) {
            if (res.data.elements != undefined) {
              var legBlock1 = res.data.elements
                .map(function(x) {
                  if (
                    x &&
                    x.data &&
                    x.data.class &&
                    x.data.class ===
                      'org.mapfish.print.config.layout.LegendsBlock'
                  )
                    return x;
                })
                .filter(function(x) {
                  if (x) return x;
                });
            }
            if (legBlock1 != undefined)
              for (var ib = 0; ib < legBlock1.length; ib++)
                setDefaultParamValuesFromlayoutCopyParams(
                  legBlock1[ib].data,
                  $scope,
                  ib,
                  false
                );
          });
        else {
          if ($scope.appliedLegConfig.result != undefined)
            $scope.printLegCfg = angular.copy($scope.appliedLegConfig);
          else
            for (var ii = 0; ii < $scope.appliedLegConfig.length; ii++) {
              setDefaultParamValuesFromlayoutCopyParams(
                $scope.appliedLegConfig[ii],
                $scope,
                ii,
                true
              );
            }
        }
      }
    }

    function removeAnnotationLayers(layers) {
      if (angular.isDefined(layers)) {
        layers.forEach(function(layer) {
          if (layer.name == 'Edition') layers.remove(layer);
        });
      }
    }

    function getDialogConfig(
      resultConfig,
      layers,
      pdfLegendsToDownload,
      spec,
      callType,
      $scope
    ) {
      $scope.dialogConfigCallType = callType;
      var res = [];

      if (callType != 'parametrage' || $scope.printLegCfg == undefined)
        $scope.printLegCfg = {};
      $scope.printLegCfg.cfg = {};
      if (callType == 'parametrage') {
        if ($scope.appliedLegConfig != undefined) {
          for (var ind = 0; ind < $scope.appliedLegConfig.length; ind++) {
            $scope.appliedLegConfig[ind].askedButNotDrawn = undefined;
          }
          $scope.printLegCfg.result = angular.copy($scope.appliedLegConfig);
          res = $scope.printLegCfg.result;
        } else {
          if (res.length != 0) $scope.printLegCfg.result = res;
          else res = $scope.printLegCfg.result;
        }
        addMissingLayersToAskedLayers(res, $scope);
      } else {
        $scope.printLegCfg.result = angular.copy(resultConfig);
        setDefaultParamValuesFromlayout(callType);
        addMissingLayersToAskedLayers($scope.printLegCfg.result, $scope);
        for (
          var ires = 0;
          ires < $scope.printLegCfg.result.length &&
          spec.pages[0].forceConfig &&
          ires < spec.pages[0].forceConfig.length;
          ires++
        )
          $scope.printLegCfg.result[ires].selected =
            spec.pages[0].forceConfig[ires].selected;
      }
      $scope.printLegCfg.spec = spec;
      $scope.printLegCfg.pdfLegendsToDownload = pdfLegendsToDownload;
      $scope.printLegCfg.layers = layers;

      $scope.filtercomponents = {};
      $scope.selectAll = {};

      getInfoFromSynthese(callType, $scope);
      /**
       * A voir si c'est suffisant ou on voudrait avoir la liste par modèle Uniquement
       * sans le nom de la config du widget
       * @type {[type]}
       */
      $scope.printReportCallType = callType;
      $scope.ConfigNameTemplate =
        'modele_print_' +
        $scope.layout.name +
        '_' +
        $scope.options.asVisibleOnMap;
      $scope.savedLastConfig = angular.copy($scope.printLegCfg.result);
      $scope.ngdiaParameters = ngDialog.openConfirm({
        template: 'js/XG/widgets/mapapp/printv2/views/modal/report.config.html',
        scope: $scope,
        className: 'ngdialog-theme-plain width1000 nopadding miniclose',
      });
      $scope.cfgParamsReady = false;
      $scope.ngdiaParameters.then(
        function(data) {
          $scope.lastAction = 'apply';
          if (data == undefined) data = $scope.printLegCfg;
          if (data.spec && data.spec.pages && data.spec.pages.length > 0) {
            data.spec.pages[0].forceConfig = [];
            $scope.getLegParamModifications(data);
            //-- Sauvegarde paramétrage appliqué.
            $scope.appliedLegConfig = angular.copy(data.result);
            $scope.appliedLegConfigId = data.id;
            if ($scope.currentConfig != undefined) {
              $scope.prevCfg = angular.copy($scope.currentConfig);
              $scope.prevCfgId = $scope.currentConfigId;
            }
            //-- Sauvegarde paramétrage courant.
            $scope.currentConfig = angular.copy($scope.appliedLegConfig);
            for (var ind = 0; ind < data.result.length; ind++) {
              $scope.currentConfig[ind].selected = {};
              $scope.appliedLegConfig[ind].selected = {};
              for (var prop in data.result[ind].selected) {
                $scope.appliedLegConfig[ind].selected[
                  prop
                ] = $scope.currentConfig[ind].selected[prop] =
                  data.result[ind].selected[prop];
              }
            }
            if (data.id == undefined)
              $scope.currentConfigName = $filter('translate')(
                'print.workingConfig'
              );
            else {
              $scope.currentConfigName = data.name;
              $scope.appliedLegConfig.name = data.name;
            }
          }
          $scope.cfgParamsReady = true;
          //                  gaDomUtils.showGlobalLoader();
          //                  createInfo(data.layers , data.pdfLegendsToDownload , data.spec);
        },
        function() {
          if (layers.item(0).theme == 'WebBackGround') {
            console.log('JE RETIRE LE PREMIER ');
            layers.removeAt(0);
            $scope.cfgParamsReady = true;
            $scope.lastAction = $scope.prevAction;
          }

          //After standard print, download the pdf Legends
          //if there are any
          for (var i = 0; i < pdfLegendsToDownload.length; i++) {
            $window.open(pdfLegendsToDownload[i]);
          }

          //-- On s assure que les layers ajoutés pour traiter
          //-- le cas des annotations ne reste pas dans le circuit.
          //-- Effectivement, ils ne servent plus à rien.
          removeAnnotationLayers(layers);

          $scope.getPrintConfig(false);
        }
      );
    }

    function advancedCfgAreIdentical(prevCfg, cfg) {
      var c1, c2, iLeg;

      c1 = prevCfg;
      c2 = cfg;

      //-- Should not occur, but who knows ...
      if (c1.length != c2.length) return false;

      for (iLeg = 0; iLeg < c1.length; iLeg++) {
        if (c1[iLeg].shrinkFactor != c2[iLeg].shrinkFactor) return false;
        if (c1[iLeg].layerFontSize != c2[iLeg].layerFontSize) return false;
        if (c1[iLeg].classFontSize != c2[iLeg].classFontSize) return false;
        if (c1[iLeg].themeFontSize != c2[iLeg].themeFontSize) return false;
        if (c1[iLeg].askedColumnNumber != c2[iLeg].askedColumnNumber)
          return false;
        if (c1[iLeg].forceFactor != c2[iLeg].forceFactor) return false;
        if (c1[iLeg].forceThemeFontSize != c2[iLeg].forceThemeFontSize)
          return false;
        if (c1[iLeg].forceLayerFontSize != c2[iLeg].forceLayerFontSize)
          return false;
        if (c1[iLeg].forceClassFontSize != c2[iLeg].forceClassFontSize)
          return false;
        if (c1[iLeg].forceColumnNumber != c2[iLeg].forceColumnNumber)
          return false;

        //-- "forcedFontSize" est actuellement commenté dans le HTML,
        //-- en décommentant la ligne de cette check box, on peut
        //-- l'utiliser à nouveau.
        if (c1[iLeg].forcedFontSize != c2[iLeg].forcedFontSize) return false;
        /*
                  *-- La liste des couches ne fait pas partie de la configuration avancée.
                  *
                 if (c1[iLeg].askedLegendLayers!=undefined && c2[iLeg].askedLegendLayers!=undefined )
                    {
                     var iLyr;
                     if (c1[iLeg].askedLegendLayers.length!=c2[iLeg].askedLegendLayers.length)
                         return false;
                     for (iLyr=0;iLyr<c1[iLeg].askedLegendLayers.length;iLyr++)
                         {
                          if (c2[iLeg].askedLegendLayers.indexOf(c1[iLeg].askedLegendLayers[iLyr])==-1)
                              return false;
                         }
                    }
                    */
      }
      return true;
    }

    function checkConfigModified(
      paramId,
      paramName,
      prevCfg,
      cfg,
      prevCfgId,
      $scope
    ) {
      var defer = $q.defer();

      $scope.setForceIt(cfg, false);

      //-- S'il y a une configuration précédente et
      //-- si l'identifiant est le même, on vérifie
      //-- s'il y a eut modification entre les 2  versions.
      if (prevCfg != undefined && paramId == prevCfgId) {
        if (!advancedCfgAreIdentical(prevCfg, $scope.currentConfig))
          $scope.setForceIt(cfg, true);
        defer.resolve();
      }

      //-- S'il n'y a pas de configuration précédente et qu'il ne s'agit
      //-- pas d'une paramétre en base alors on contraint l'impression.
      else if (prevCfg == undefined && paramId == undefined) {
        $scope.setForceIt(cfg, true);
        defer.resolve();
      }

      //-- Lorsque l'on modifie un paramètre en base sans l'enregistrer
      //-- son identifiant est mis à undefined car il ne correspond plus
      //--  u paramétre stocké. Par contre le nom lui n'est pas réinitialisé.
      else if (paramId == undefined && paramName != undefined) {
        $scope.setForceIt(cfg, true);
        defer.resolve();
      }

      //-- S'il s'agit d'une configuration stockée comme paramétre
      //-- en base, alors on récupère la description stockée en base.
      //-- Ce cas ne devrait pas arriver.
      else {
        ParametersFactory.getbyid(paramId).then(function() {
          if (paramId != prevCfgId) $scope.setForceIt(cfg, false);
          else if (prevCfg == undefined) $scope.setForceIt(cfg, false);
          else if (!advancedCfgAreIdentical(prevCfg, cfg))
            $scope.setForceIt(cfg, true);

          defer.resolve();
        });
      }

      return defer.promise;
    }

    function getNameFromDollarVariable(text) {
      if (text) {
        text = text
          .replace(/\$/g, '')
          .replace(/\{/g, '')
          .replace(/\}/g, '')
          .replace(/"/g, '');
      }

      return text;
    }

    function searchVariableValueInArray(text, arrayObj) {
      var targetValue = '';
      var found = false;

      if (text && arrayObj) {
        text = getNameFromDollarVariable(text);
        for (var i = 0; i < arrayObj.length; i++) {
          angular.forEach(arrayObj[i], function(value, key) {
            //console.log("----> " + key + " : " + value + " : " + text);
            if (key == text) {
              targetValue = value;
              found = true;
              return;
            }
          });

          if (found) {
            break;
          }
        }
      }

      return targetValue;
    }

    /*
     * configVariables = [{"\"${test}\"":"titi"},{"\"${test2}\"":"tata"}]
     * variablesToExport = [{"test":"titi"},{"test2":"tata"}]
     */
    function updateConfigVariablesFromUserVariables(
      configVariables,
      variablesToExport
    ) {
      var variablesUpdated = [];
      if (configVariables != undefined) {
        for (var i = 0; i < configVariables.length; i++) {
          angular.forEach(configVariables[i], function(value, key) {
            var targetValue = searchVariableValueInArray(
              key,
              variablesToExport
            );

            var obj = configVariables[i];
            if (targetValue) {
              obj[key] = targetValue;
            }

            variablesUpdated.push(obj);
          });
        }
      }

      return variablesUpdated;
    }

    return {
      getDialogConfig: getDialogConfig,
      initResultConfig: initResultConfig,
      checkConfigModified: checkConfigModified,
      addMissingLayersToAskedLayers: addMissingLayersToAskedLayers,
      updateConfigVariablesFromUserVariables: updateConfigVariablesFromUserVariables,
      removeAnnotationLayers: removeAnnotationLayers,
      setDefaultParamValuesFromlayout: setDefaultParamValuesFromlayout,
    };
  };
  pv2Config.$inject = [
    '$filter',
    'ParametersFactory',
    '$q',
    'PrintModelFactory',
    'ngDialog',
    'gaJsUtils',
  ];
  return pv2Config;
});
