'use strict';
/**
 * Simple list / edit / add / remove list from a json list of elements **Note:**
 * an object editListCfg must be declared in parent scope.<br/> if not, the
 * directive needs configuration object to be passed through data-cfg attribute
 *
 * <pre>
 * &lt;div edit-list data-cfg=&quot;myCfgObject&quot;&gt;&lt;/div&gt;
 * </pre>
 */
define(function() {
  var editList = function(
    ngTableParams,
    ngDialog,
    $rootScope,
    FeatureTypeFactory,
    gaJsUtils,
    $filter,
    InitProvider,
    PortalsFactory,
    gaDomUtils
  ) {
    return {
      restrict: 'A',
      link: function(scope, elem, attrs) {
        if (
          InitProvider &&
          InitProvider.getHpoConfig &&
          InitProvider.getHpoConfig() &&
          InitProvider.getHpoConfig().datastoreuid
        )
          scope.specialHpoAppUid = InitProvider.getHpoConfig().datastoreuid;

        scope.case = { sensitivity: 0 };
        scope.criterias = {};
        scope.searchMode = false;
        scope.svgPage = 1;
        scope.oldcopy = {};

        scope.$watch('currentResources', () => {
          scope.countLength();
        });

        /** display / hide full list when search mode is activated * */
        scope.toggleSearchMode = () => {
          scope.searchMode = !scope.searchMode;
          scope.$emit('searchModeChange',{name:scope.editListCfg.name, searchMode:scope.searchMode});
          scope.criterias = {};
          if (scope.searchMode) {
            scope.svgPage = scope.tableParams.page();
            scope.tableParams.count(scope.tableParams.total());
          } else {
            scope.tableParams.count(_tableParams.count);
            scope.tableParams.page(scope.svgPage);
          }
        };
        /**
         * Sorte les roles , cette focntion peut etre utilisé pour tous les
         * autres
         */
        scope.sortRoles = function() {
          if (scope.editListCfg.resource_type == 'roles') {
            scope.currentResources.sort(function(a, b) {
              var x = a.name.toLowerCase();
              var y = b.name.toLowerCase();
              if (x < y) {
                return -1;
              }
              if (x > y) {
                return 1;
              }
              return 0;
            });
          }
        };

        /**
         * Cancel whatever may be currently selected
         */
        const cancelCurrentSelection = function() {
          if (scope.currentResources) {
            scope.currentResources.forEach(function(x) {
              x.$selected = false;
            });
          }
          scope.selected_resource = null;
          scope.selected_resource_index = -1;
          scope.edit_resource = null;
        };

        /**
         * Edit list filter (search button)
         *
         * @param criterias
         * @returns {Function}
         */
        scope.editListFilter = (criterias) => {
          return (item) => {
            let showItem = true;
            for (let c in criterias) {
              let cmp = '';
              if (item.hasOwnProperty(c) && item[c] !== '' && new Date(item[c]) !== 'Invalid Date') {
                cmp = $filter('date')(item[c], gaJsUtils.getLocaleDateString());
              } else {
              // cast as string or indexOf will throw an error
                cmp += item[c];
              }
              let compareValue = angular.copy(criterias[c]);

              if (!scope.case.sensitivity) {
                cmp = cmp.toLowerCase();
                compareValue = compareValue.toLowerCase();
              }

              if (!item.hasOwnProperty(c) || cmp.indexOf(compareValue) == -1) {
                showItem = false;
              }
            }
            return showItem;
          };
        };
        
        scope.countLength = () => {
          if(scope.currentResources){
            scope.countRessourcesLength = scope.currentResources.filter(scope.editListFilter(scope.criterias)).length;
          }
        }

        var renderTitleEditListCfg = function() {
          scope.editListCfg.titleCol = [];
          scope.editListCfg.cols.forEach(function(colname) {
            scope.editListCfg.titleCol.push(
              scope.editListCfg.dataModule +
                '.' +
                scope.editListCfg.resource_type +
                '.' +
                colname
            );
          });
        };

        /*
         * Configuration
         */

        if (scope.editListCfg && scope.editListCfg.notPagination) {
          var _tableParams = {
            filter: {
              name: 'M',
            },
            count: 1,
            page: 1,
          };
        } else {
          _tableParams = {
            page: 1,
            count: 50,
            filter: {
              name: 'M',
            },
          };
        }

        cancelCurrentSelection();
        /*
         * By default, the directive configuration is inherited from the
         * parentscope which must contain an editListCfg object But if another
         * object is passed from the data-cfg attribute, this one will be used
         */

        if (
          angular.isDefined(scope.editListCfg) &&
          angular.isDefined(scope.editListCfg.dataModule) &&
          angular.isDefined(scope.editListCfg.resource_type) &&
          angular.isDefined(scope.editListCfg.cols) &&
          scope.editListCfg.cols.length > 0
        ) {
          renderTitleEditListCfg();
        }

        if (attrs.cfg) {
          scope.editListCfg = scope[attrs.cfg];

          /*
          set the currentResources to be the one provided by the the cfg object
          if the object provided is undefined, we set it a new empty array
          */
          if (
            scope[attrs.cfg] &&
            scope[attrs.cfg].hasOwnProperty('currentResources')
          ) {
            scope.currentResources = scope[attrs.cfg].currentResources;
          }
          // force the table reset
          scope.resetTable = true;
        }

        if (angular.isUndefined(scope.editListCfg)) {
          scope.editListCfg = {};
        }
        if (angular.isUndefined(scope.editListCfg.addResourceButton)) {
          scope.editListCfg.addResourceButton = true;
        }

        if (angular.isUndefined(scope.editListCfg.deleteResourceButton)) {
          scope.editListCfg.deleteResourceButton = true;
        }

        scope.displayWarning = false;

        // when the object is ready, display it
        if (angular.isDefined(scope.editListCfg.warning)) {
          var deregwarning = scope.$watch(
            scope.editListCfg.warning,
            function(warning) {
              if (angular.isDefined(warning)) {
                scope.editListCfg.warning = warning;
                scope.displayWarning = true;
                deregwarning();
              }
            },
            1
          );
        }

        /**
         * Display the resources in a table
         */
        scope.setTable = function() {
          var data = scope.currentResources;

          if (scope.editListCfg.notPagination) {
            scope.tableParams = new ngTableParams(_tableParams, {
              total: data.length,
              counts: [],
              getData: function($defer, params) {
                data = scope.currentResources;
                if (data.code == 403) {
                  var errorMsg = '<h4>Erreur 403</h4> ';
                  errorMsg += '<br/><h4>Details</h4>';
                  errorMsg += '<br/>' + data.message;
                  require('toastr').error(errorMsg);
                } else {
                  $defer.resolve(
                    data.slice(
                      (params.page() - 1) * params.count(),
                      params.page() * params.count()
                    )
                  );

                  if (params.page() != 1 && data.length == params.count()) {
                    params.page(1);
                    scope.tableParams.reload();
                  }
                }
              },
            });
          } else {
            scope.tableParams = new ngTableParams(_tableParams, {
              total: data.length,
              getData: function($defer, params) {
                data = scope.currentResources;
                if (data.code == 403) {
                  var errorMsg = '<h4>Erreur 403</h4> ';
                  errorMsg += '<br/><h4>Details</h4>';
                  errorMsg += '<br/>' + data.message;
                  require('toastr').error(errorMsg);
                } else {
                  $defer.resolve(
                    data.slice(
                      (params.page() - 1) * params.count(),
                      params.page() * params.count()
                    )
                  );

                  if (params.page() != 1 && data.length == params.count()) {
                    params.page(1);
                  }
                }
              },
            });
          }

          // HOTFIX from https://github.com/esvit/ng-table/issues/297
          scope.tableParams.settings().$scope = scope;
        };

        /**
         * Returns the object to edit which is an empty js object if no
         * defaultValues are set
         *
         * @returns {{}}
         */
        scope.getDefautEditResource = function() {
          var defautResource = {};

          // if some default values are set
          if (scope.editListCfg.defautValues) {
            scope.editListCfg.defautValues.forEach(function(df) {
              defautResource[df.k] = angular.copy(df.v);
            });
          }
          return defautResource;
        };

        /**
         * Edit Resource Modal
         *
         * @param isNew
         */
        var cDialog;
        scope.edit_modal = function(isNew, c, copy) {
          if (copy) {
            scope.editModalIsNew = copy;
            cDialog = ngDialog.open({
              template:
                'js/XG/modules/' +
                scope.editListCfg.dataModule +
                '/views/modals/modal.' +
                scope.editListCfg.resource_type +
                '.html',
              className:
                'ngdialog-theme-plain ' +
                (scope.editListCfg.width || 'width800'),
              closeByDocument: false,
              closeByEscape: false,
              scope: scope,
            });
          } else {
            scope.duplicate =false;
            if (angular.isDefined(scope.editListCfg.restrictAdd)) {
              if (scope.editListCfg.restrictAdd.condition) {
                require('toastr').error(
                  $filter('translate')(scope.editListCfg.restrictAdd.message)
                );
                return;
              }
            }

            scope.editModalIsNew = isNew;
            // force reset

            // a specific add function was configured
            if (isNew && scope.editListCfg.addFunction) {
              scope.editListCfg.addFunction();
              return false;
            }
            if (!isNew && scope.editListCfg.editFunction) {
              scope.editListCfg.editFunction(scope.edit_resource);
              return false;
            }

            scope.isNewResource = isNew || false;
            if (isNew) {
              scope.selected_resource_index = -1;
              scope.edit_resource = scope.getDefautEditResource();
            }

            if (!isNew) {
              scope.oldcopy = angular.copy(scope.edit_resource);
            }

            if (
              isNew &&
              angular.isDefined(scope.cancreate) &&
              !scope.cancreate
            ) {
              console.log('licence cannot add app');
              scope.showAlertLicence();
            } else {
              cDialog = ngDialog.open({
                template:
                  'js/XG/modules/' +
                  scope.editListCfg.dataModule +
                  '/views/modals/modal.' +
                  scope.editListCfg.resource_type +
                  '.html',
                className:
                  'ngdialog-theme-plain ' +
                  (scope.editListCfg.width || 'width800'),
                closeByDocument: false,
                closeByEscape: false,
                scope: scope,
              });
            }
          }

          var deregNgDialog = $rootScope.$on('ngDialog.opened', function(
            e,
            $dialog
          ) {
            if (cDialog.id == $dialog.attr('id')) {
              // Brodcast the fact that the edit modal is loading
              scope.$emit('data_modal', {
                action: 'edit',
                editObject: {
                  name: scope.editListCfg.resource_name,
                  obj: scope.edit_resource,
                  index: scope.selected_resource_index,
                },
                isNew: isNew,
                dialog: $dialog,
                dialogObject: cDialog,
              });
              deregNgDialog();
            }
          });
        };

        $rootScope.$on('ngDialog.close.edit', function(e, $dialog) {
          cDialog.close();
        });

        /**
         * Delete Resource Modal
         *
         * @param type
         */
        var deleteModal;
        scope.delete_modal = () => {
          // Broadcast the fact that the delete modal is loading
          scope.$emit('data_modal', {
            action: 'delete',
            editObject: {
              name: scope.editListCfg.resource_name,
              obj: scope.edit_resource,
              index: scope.selected_resource_index,
            },
          });

          // specific delete template
          if (scope.editListCfg.removeTemplate) {
            if (
              scope.editListCfg.removeTemplate ==
              'js/XG/modules/model/views/modals/modal.featuretypes.remove.html'
            ) {
              if (scope.edit_resource.uid) {
                FeatureTypeFactory.isfeatureindatabase(
                  scope.edit_resource.uid
                ).then(function(res) {
                  scope.edit_resource.isfeatureindatabase = res.data;
                });
              }
            }

            deleteModal = ngDialog.open({
              template: scope.editListCfg.removeTemplate,
              className: 'ngdialog-theme-plain',
              closeByDocument: false,
              scope: scope,
            });

            // else
          } else {
            deleteModal = ngDialog.open({
              template:
                'js/XG/modules/common/views/directives/editListDeleteModal.html',
              className: 'ngdialog-theme-plain',
              closeByDocument: false,
              scope: scope,
            });
          }
        };

        scope.delete_modal_multi = () => {
          if(scope.editListCfg.allowMultipleSelection){
            if (!scope.editListCfg.allowMultipleSelection.deleteTemplate) {
              return;
            }
            scope.isFeaturesInDatabase = false;  
            //Vérifie si au moins une des table séléctionnés existe en BD
            Object.keys(scope.multiResourceSelection).forEach((key) => {
              FeatureTypeFactory.isfeatureindatabase(key).then((res) => {
                if(res.data){
                  scope.isFeaturesInDatabase = true;
                  return;
                }
              })
            });
            deleteModal = ngDialog.open({
              template: scope.editListCfg.allowMultipleSelection.deleteTemplate,
              className: 'ngdialog-theme-plain',
              closeByDocument: false,
              scope: scope,
            });
          }else{
            deleteModal = ngDialog.open({
              template:
                'js/XG/modules/common/views/directives/editListDeleteModal.html',
              className: 'ngdialog-theme-plain',
              closeByDocument: false,
              scope: scope,
            });
          }
        };

        $rootScope.$on('ngDialog.closed', function(e, $dialog) {
          if (deleteModal && deleteModal.id == $dialog.attr('id')) {
            if (scope.tableParams) scope.tableParams.reload();
            else scope.setTable();
          }
          if (cDialog && cDialog.id == $dialog.attr('id')) {
            if (scope.tableParams) scope.tableParams.reload();
            else scope.setTable();
          }
        });

        scope.$on('reloadEditList', () => {
          scope.tableParams.reload();
        });

        scope.multiResourceSelection = {};
        scope.currentSelectionIsMultiple = false;

        const handleMultipleSelection = function(
          obj,
          key,
          alreadySelectedValue
        ) {
          if (alreadySelectedValue) {
            obj[alreadySelectedValue] = true;
          }
          if (obj[key]) {
            delete obj[key];
          } else {
            obj[key] = true;
          }
        };

        scope.AddOrInsertAttributeToFeatureType = function() {
          let index_resource = selectLineResource();
          if (index_resource != -1 && scope.editModalIsNew) {
            swal(
              {
                title: $filter('translate')('common.titleconfirmmsg'),
                type: 'warning',
                showCancelButton: true,
                confirmButtonColor: '#DD6B55',
                confirmButtonText: $filter('translate')('common.yes'),
                cancelButtonText: $filter('translate')('common.no'),
                closeOnConfirm: true,
                closeOnClickOutside: false,
              },
              function(isConfirm) {
                gaDomUtils.showGlobalLoader();
                if (isConfirm) {
                  insertAttributeToFeatureType(index_resource);
                } else {
                  scope.addAttributeToFeatureType();
                }
                cDialog.close();
                gaDomUtils.hideGlobalLoaderAfterTimeout();
              }
            );
          } else {
            gaDomUtils.showGlobalLoader();
            scope.addAttributeToFeatureType();
            cDialog.close();
            gaDomUtils.hideGlobalLoaderAfterTimeout();
          }
        };

        var selectLineResource = function() {
          if(angular.isDefined(scope.selected_resource) && scope.selected_resource !=null)
            return scope.currentFeatureType.attributes.findIndex(item => item.name == scope.selected_resource.name);
          return -1;
          
        };

        // inserer le nouveau attribut à la position d'attribut sélectionner
        var insertAttributeToFeatureType = function(index_resource) {
          scope.currentFeatureType.attributes.splice(
            index_resource,
            0,
            scope.currentFeatureTypeAttribute
          );
        };

        /**
         * Ensure the user can select one line only
         *
         * @param resource
         * @param index
         * @param force
         */
        scope.selectresource = function(resource, index, force) {
          // MultiSelection via ctrlClicking a line
          let msCfg = scope.editListCfg.allowMultipleSelection || scope.editListCfg.allowMultipleSelectionAttribute;
          if (event.ctrlKey && msCfg) {
            let alreadySelectedValue =
              scope.selected_resource != null
                ? scope.selected_resource[msCfg.uniqueKey]
                : false;
            cancelCurrentSelection();
            handleMultipleSelection(
              scope.multiResourceSelection,
              resource[msCfg.uniqueKey],
              alreadySelectedValue
            );
            scope.multiResourceSelectionLength = Object.keys(scope.multiResourceSelection).length;
            scope.currentSelectionIsMultiple = scope.multiResourceSelectionLength > 1;

            if(scope.editListCfg.allowMultipleSelectionAttribute){
              scope.editListCfg.allowMultipleSelectionAttribute.multiResourceSelection = scope.multiResourceSelection;
              scope.deleteAttMultiConfirm = $filter('translate')('common.deleteMultiAttConfirm').replace(
                                            '$1',scope.multiResourceSelectionLength);
            }
            scope.deleteConfirm = $filter('translate')('common.deleteConfirmComponent').replace(
                                      '$1',scope.multiResourceSelectionLength);
            return;
          } else if(scope.editListCfg.allowMultipleSelectionAttribute) {
            scope.editListCfg.allowMultipleSelectionAttribute.multiResourceSelection = {};
          }

          scope.multiResourceSelection = {};
          scope.currentSelectionIsMultiple = false;

          force = force || false;
          if (typeof index == 'undefined') index = -1;

          if (resource.$selected == true && force) {
            cancelCurrentSelection();
          } else {
            cancelCurrentSelection();
            resource.$selected = true;
            scope.selected_resource = resource;
            scope.selected_resource_index = index;
            scope.edit_resource = angular.copy(resource);
            if (scope.editListCfg.resource_type ==='default_filters' || scope.editListCfg.resource_type ==='clauses'){
              scope.$emit('edit_resource', scope.edit_resource);
            }
          }
        };

        /**
         * unSelectAllResources
         */
        scope.unSelectAllResources = function() {
          console.log(scope.selected_resource_index);
        };

        /**
         * moveItem up and down when editListCfg.allowReorder==true
         *
         * @param index
         * @param direction
         * @returns {boolean}
         */
        scope.moveItem = (index, direction) => {
          if (
            (index == 0 &&
              scope.tableParams.page() == 1 &&
              direction == 'up') ||
            (index == scope.currentResources.length - 1 && direction == 'down')
          )
            return false;
          let newIndex = direction == 'up' ? fixIndexCaseManyPages(index) -1 : index + 1;

          scope.currentResources.splice(
            fixIndexCaseManyPages(index),
            0,
            scope.currentResources.splice(newIndex, 1)[0]
          );
          scope.editListCfg.saveChangedOrder();
        };
        scope.isFirstItem = (index) => {
          return index == 0 && scope.tableParams.page() == 1;
        };

        scope.isLastItem = (index) => {
          return fixIndexCaseManyPages(index) === scope.tableParams.total()-1;
        }

        let fixIndexCaseManyPages = (idx) => {
          if(scope.tableParams && idx != -1){
            return (scope.tableParams.page() - 1) * scope.tableParams.count() +idx;
          }else{
            return idx;
          }
        }

        /*
         * Set/Update the table when data changes
         */
        var resourcesLength = 0;

        scope.$watch(
          function() {
            scope.sortRoles();
            return scope.currentResources;
          },
          function(data) {
            if (typeof data != 'undefined') {
              var errorMsg = '';
              if (data == 'calendar_error') {
                scope.editListCfg.dontShowLength = true;
                errorMsg =
                  '<div>Plusieurs sources de données sont actives sur ce portail.<div>';
                errorMsg +=
                  '<br/><div>Veuillez activer le calendrier ce qui permettra de désigner une source de données principale.</div>';
                require('toastr').error(errorMsg);
              } else {
                if (
                  typeof scope.tableParams == 'undefined' ||
                  scope.resetTable
                ) {
                  scope.setTable();
                  scope.resetTable = false;
                }
                if (scope.currentResources.code == 403) {
                  errorMsg = '<h4>Erreur 403</h4> ';
                  errorMsg += '<br/><h4>Details</h4>';
                  errorMsg += '<br/>' + scope.currentResources.message;
                  require('toastr').error(errorMsg);
                } else if (scope.currentResources.length) {
                  scope.tableParams
                    .total(scope.currentResources.length)
                    .reload();

                  /*
                   * Select the resource that was just added If necessary,
                   * change the page
                   */
                  if (
                    scope.currentResources.length > resourcesLength &&
                    resourcesLength > 0 &&
                    data.length > 0 &&
                    !scope.editListCfg.skipSelectAfterAdding
                  ) {
                    scope.selectresource(data[data.length - 1], 1);
                    scope.tableParams.parameters({
                      page: Math.ceil(data.length / _tableParams.count),
                    });
                  }
                  resourcesLength = scope.currentResources.length;
                }
              }
            }
          },
          true
        );

        /**
         * render cols value
         *
         * @param value
         * @param colname
         * @returns {*}
         */
        scope.renderValue = function(value, colname) {
          if (value && value != '' && new Date(value) != 'Invalid Date') {
            value = $filter('date')(value, gaJsUtils.getLocaleDateString());
          }
          return value;
        };

        /**
         * add cols css
         *
         * @param colname
         * @returns {*}
         */
        scope.addColsCss = function(colname) {
          return scope.editListCfg.colsCss[0][colname];
        };

        /**
         * check display Rendu Col
         *
         * @param resource
         * @param colname
         * @returns {boolean}
         */
        scope.displayRenduCol = function(resource, colname) {  
          var res = false;
          if (
            scope.editListCfg &&
            scope.editListCfg.colsCss &&
            scope.editListCfg.colsCss[0] &&
            Object.keys(scope.editListCfg.colsCss[0])[0] == colname &&
            resource[colname] &&
            resource[colname] != ''
          ) {
            res = true;
          }
          return res;
        };

        scope.getPortalByApplicatio = function() {
          PortalsFactory.getPortalAndApps().then(function(res) {
          });
        };

        /**
         * Fonction dans le HTML pour basculer l'affichage des onglets dans le header de la table
         * @returns {boolean} true si le header contient des onglets
         * @see scope.editListCfg
         */
        scope.fixedHeaderTableHasTabs = () => {
          return scope.editListCfg && scope.editListCfg.extraFilterTabs !== undefined && scope.editListCfg.extraFilterTabs.length>0
        }

        let currSortData = {};

        scope.sortTable = (att) => {
          if (scope.editListCfg.sort){
            if (!scope.currentResources || !scope.currentResources.length) {
              return false;
            }

            let sortOrder = 'asc';
            if (currSortData.column === att) {
              if (currSortData.order === 'asc') {
                sortOrder = 'desc';
              }
              if (currSortData.order === 'desc') {
                sortOrder = null;
              }
            }
            currSortData.order = sortOrder;
            currSortData.column = att;
            scope.editListCfg.defaultSort = currSortData.column && currSortData.column !== ''
                ? currSortData.column : '';

            if (scope.editListCfg.defaultSort && currSortData.order) {
              const prefix = currSortData.order === 'asc' ? '+' : '-';
              scope.editListCfg.defaultSort = prefix + scope.editListCfg.defaultSort;
            }
            refreshTableToDisplaySort({column: currSortData.column, direction: currSortData.order});
          }
        };

        /**
         * Rafraîchit la table
         */
        const refreshTableToDisplaySort = (sorting) => {
          const sortingColumnName = sorting.column;
          // recherche l'en-tête de la colomne triée
          const htmlSortedTh = $('.fixTh').filter((index) => {
            if (index > 0 && index <= scope.editListCfg.cols.length) {
              // index > 0 évite de traiter le bouton filtre
              const attname = scope.editListCfg.cols[index - 1];
              // comme index >=1, 'index - 1' permet de commencer la lecture du tableau au début
              return attname === sortingColumnName;
            } else {
              return false;
            }
          });
          scope.sorting = sorting;
          scope.tableParams
          .reload();
        };

        scope.isSortAsc = (colname) => {
          return scope.sorting && scope.sorting.column === colname && scope.sorting.direction
              === 'asc';
        };
        scope.isSortDesc = (colname) => {
          return scope.sorting && scope.sorting.column === colname && scope.sorting.direction
              === 'desc';
        };
      },
      templateUrl: 'js/XG/modules/common/views/directives/editList.html',
    };
  };

  editList.$inject = [
    'ngTableParams',
    'ngDialog',
    '$rootScope',
    'FeatureTypeFactory',
    'gaJsUtils',
    '$filter',
    'InitProvider',
    'PortalsFactory',
    'gaDomUtils'
  ];
  return editList;
});