class AdminMassEdit {
   constructor() {
      this.startEventListenersOnlyOnce()
      this.startEventListeners();

   }

   enableInput(el) {
      const disabled = $(el).is(':checked');
      const $input = $(el).closest('.list_item').find('.input');
      $input.prop('disabled', !disabled);

      if ($input.hasClass('listEdit-autocomplete') || $input.hasClass('listEdit-multiselectAutocomplete')) {
         if (disabled) {
            this.applyChosen($input);
            $input.trigger('chosen:updated');
         } else {
            this.unapplyChosen($input);
         }
      } else if ($input.hasClass('selecter')) {
         $input.trigger('chosen:updated');
      }
   }

   enablerMassAction(el) {
      const enabler = $(el);

      if (this.lastEnabler && this.shifted) {
         const lastName = this.lastEnabler.attr('name').match(/\[([\w]+)/)[1] ?? '';
         const currentName = enabler.attr('name').match(/\[([\w]+)/)[1] ?? '';

         if (lastName === currentName) {
            const lastPos = this.lastEnabler.parents('tr, li').eq(0).index() + 1;
            const currentPos = enabler.parents('tr, li').eq(0).index() + 1;

            const min = Math.min(currentPos, lastPos);
            const max = Math.max(currentPos, lastPos);

            console.log(min + ':' + max);

            for (let i = min; i <= max; i++) {
               const $el = $('.table tr, .table li').eq(i).find('[name^=\'checked[' + currentName + ']\']');

               $el.prop('checked', this.lastEnabler.is(':checked'));
               this.enableInput($el.get());
            }
         }
      }
      this.lastEnabler = enabler;
   }

   enableAll(el) {
      const enabler = $(el);
      const currentName = enabler.attr('name').match(/\[([\w]+)/)[1] ?? '';
      $('[name^=\'checked[' + currentName + ']\']').not(".editFirstRow").prop('checked', enabler.is(':checked')).each((i, el) => {
         this.enableInput(el);
      });
   }

   unapplyChosen($selector) {
      var $selecter = $selector.filter('.ajax-selecter');
      {
         $selecter.chosen('destroy');
      }
   }

   applyChosen($selector) {
      if (!$selector.length) {
         return;
      }
      $selector = $selector.filter('.ajax-selecter');
      $selector.ajaxChosen({
         minTermLength: 0,
         dataType: 'json',
         type: 'GET',
         url: 'launch.php?s=autocomplete.php&type=' + $selector.data('type') + ($selector.attr('data-visibleOnly') === 'false' ? '&visible=0' : '')
         + ($selector.attr('data-autocomplete-params') ? '&' + $selector.attr('data-autocomplete-params') : ''),
      }, function(data) {
         return data;
      }, {
         width: '100%',
         allow_single_deselect: true,
         placeholder_text_single: $selector.data('text-single') ? $selector.data('text-single') : 'Vyberte možnost',
         placeholder_text_multiple: 'Vyberte několik možností',
      })
   }

   // Listeners that has to be started only once. After the list is loaded
   startEventListenersOnlyOnce() {
      $(window).on('beforeunload', this, function(el) {
         if (el.data.contentChanged) {
            return 'Opravdu chcete zahodit změny?';
         }
      });

      $('.massEditForm').on('submit', this, function(el) {
         el.data.contentChanged = false;
      });

      $('[name=\'divide_items\']').on('change', function() {
         const searchParams = new URLSearchParams($('[name="divide_url"]').val());
         searchParams.set('divide', $(this).val());
         searchParams.delete('ErrStr');
         window.location.replace('?' + searchParams.toString());
      });

      $(document).on('keyup keydown', this, function(el) {
         el.data.shifted = el.shiftKey;
      });

      let autocompleteTypes = new Set();
      $('.editFirstRow .listEdit-autocomplete, .editFirstRow .listEdit-multiselectAutocomplete').each(function() {
         autocompleteTypes.add($(this).data('type'));
      });
      autocompleteTypes.forEach((val) => this.applyChosen($('.input[data-type=\'' + val + '\']:not(:disabled)')));

      this.startMassEditListeners();
   }

   // Listeners for mass edit (first row inputs)
   startMassEditListeners() {
      $('.editFirstRow .columnEnabler').on('change', this, function(el) {
         el.data.enableAll(this);
      });

      const findEnabledInputs = (name) => {
         return  $('[name^=\'data[' + name + ']\']').closest('.list_item').has('[name^=\'checked\']:checked:not(.editFirstRow)').find('[name^=\'data[' + name + ']\']');
      }

      $('.editFirstRow .input[type=\'text\'], .editFirstRow .listEdit-select, .editFirstRow .input[type=\'number\']').on('change', this, function(el) {
         const currentName = $(this).attr('name').match(/\[([\w]+)/)[1] ?? '';

         const newValue = $(this).val();

         findEnabledInputs(currentName).each((index, element) => {
            const $target = $(element);
            $target.val(el.data.evaluateExpression($target, newValue)).trigger('change').trigger('chosen:updated');
         });

      }).on('keypress', function(e) {
         if (e.which == 13) {
            $(this).change();
            e.preventDefault();
         }
      });

      const multiselectSelected = [];

      $('.editFirstRow .listEdit-multiselect, .editFirstRow .listEdit-multiselectAutocomplete').on('change', function(el) {
         const currentName = $(this).attr('name').match(/\[([\w]+)/)[1] ?? '';
         const actualValues = $(this).val()

         const oldValues = multiselectSelected[currentName] ?? [];

         const removedValues = oldValues.filter(n => !actualValues.includes(n));
         const addedValues = actualValues.filter(n => !oldValues.includes(n));

         multiselectSelected[currentName] = actualValues;
         const $option = $(el.target).find('option:selected');

         findEnabledInputs(currentName).each(function(i) {

            const rowSelect = $(this);

            const currentVal = [... new Set(rowSelect.val().filter(n => !removedValues.includes(n)).concat(addedValues))];

            $option.each(function() {
               if (!rowSelect.children('[value="' + $(this).val() + '"]').length) {
                  rowSelect.append($(this).clone());
               }
            });

            $(this).val(currentVal).trigger('change').trigger('chosen:updated');

         })
      });

      $('.editFirstRow .input[type=\'checkbox\']').on('change', function(el) {
         const currentName = $(this).attr('name').match(/\[([\w]+)/)[1] ?? '';
         const val = $(this).is(':checked');
         findEnabledInputs(currentName).prop('checked', val);
      });

      $('.editFirstRow .listEdit-autocomplete').change((e, data) => {
         const $option = $(e.target).find('option:selected').clone();
         const currentName = $(e.target).attr('name').match(/\[([\w]+)/)[1] ?? '';
         const $selectors = findEnabledInputs(currentName);
         $selectors.append($option);
         $selectors.val($option.val()).trigger('chosen:updated');
      });
   }

   evaluateExpression($input, expression) {

      if (expression[0] !== '=') {
         return expression;
      }
      let hodnota = $input.attr('value');// original value
      if (!isNaN(hodnota)) {
         hodnota *= 1;
      }
      const value = hodnota;

      try {
         const result = eval(expression.substring(1));
         return result;
      } catch (error) {
         return 'Chyba ve vzorci: ' + error;
      }
   }

   recalculatePriceVat(elem) {
      const $priceElem = $(elem).closest('.list_item').find('.vat_target');

      const targetVat = (Number($(elem).closest('.list_item').find('.vat_value').val()) + 100) / 100;
      let val;
      if ($(elem).val() === '0') {
         val = $priceElem.val() / targetVat;
      } else {
         val = $priceElem.val() * targetVat;
      }
      $priceElem.val(Math.round(val * 10000) / 10000);

   }

   // Listeners for each row. When content is changed dynamically, these listeners have to be restarted (viz. reloadEventListeners)
   startEventListeners() {
      $('.columnEnabler:not(.editFirstRow)').on('change.massEdit', this, function(el) {
         el.data.enableInput(this);
         el.data.enablerMassAction(this);
         el.data.contentChanged = true;
      });

      $('.mass_price_vat:not(.editFirstRow)').on('change.massEdit', this, function(el) {
         el.data.recalculatePriceVat(this)
      });

   }

   reloadEventListeners() {
      $('*').off('.massEdit');
      this.startEventListeners()
   }

}

$(() => {
   wpj.adminListEdit = (() => {
      let adminListEditClass = new AdminMassEdit();

      return {
         reload: () => {
            adminListEditClass.reloadEventListeners();
         }
      };

   })();
});




