/**
 * For the full copyright and license information, please view the
 * docs/licenses/LICENSE.txt file that was distributed with this source code.
 */
/**
 * Combination bulk actions management
 */
export default function () {
  const bulkForm = $('#bulk-combinations-container');
  const deleteCombinationsBtn = $('#delete-combinations');
  const applyChangesBtn = $('#apply-on-combinations');
  const syncedCollection = $('[data-uniqid]');
  const finalPrice = $('#form_step2_price');
  const finalPriceIT = $('#form_step2_price_ttc');
  const finalPriceBasics = $('#form_step1_price_shortcut');
  const finalPriceBasicsIT = $('#form_step1_price_ttc_shortcut');
  const ecotaxTI = $('#form_step2_ecotax');

  return {
    init: function init() {
      const that = this;
      // stop propagation on buttons
      deleteCombinationsBtn.on('click', (event) => {
        event.preventDefault();
        that.deleteCombinations();
      });

      applyChangesBtn.on('click', (event) => {
        event.preventDefault();
        that.applyChangesOnCombinations()
          .hideForm()
          .resetForm()
          .unselectCombinations()
          .submitUpdate();
      });

      /* if final price change with user interaction, combinations should be impacted */
      finalPrice.on('blur', () => {
        this.syncToPricingTab();
      });

      finalPriceIT.on('blur', () => {
        this.syncToPricingTab();
      });

      /* if we use final price shortcuts, also combinations should be impacted */
      finalPriceBasics.on('blur', () => {
        this.syncToPricingTab();
      });

      finalPriceBasicsIT.on('blur', () => {
        this.syncToPricingTab();
      });

      ecotaxTI.on('blur', () => {
        this.syncToPricingTab();
      });

      syncedCollection.on('DOMSubtreeModified', (event) => {
        const uniqid = event.target.getAttribute('data-uniqid');
        const newValue = event.target.innerText;

        const spans = $(`[data-uniqid="${uniqid}"]`);

        spans.each(function () {
          if ($(this).text() !== newValue) {
            $(this).text(newValue);
          }
        });
      });

      // bulk select animation
      $('#toggle-all-combinations').on('change', (event) => {
        $('#accordion_combinations td:first-child input[type="checkbox"]').each(function () {
          $(this).prop('checked', $(event.currentTarget).prop('checked'));
        });
      });

      $(document).on('change', '.js-combination', () => {
        if ($('.bulk-action').attr('aria-expanded') === 'false' || !$('.js-combination').is(':checked')) {
          $('.js-collapse').collapse('toggle');
        }
        $('span.js-bulk-combinations').text($('input.js-combination:checked').length);
      });
    },
    getSelectedCombinations: function getSelectedCombinations() {
      const combinations = [];
      const selectedCombinations = Array.from(
        $('#accordion_combinations td:first-child input[type="checkbox"]:checked'),
      );
      selectedCombinations.forEach((combination) => {
        const combinationId = combination.getAttribute('data-id');
        const combinationIndex = combination.getAttribute('data-index');
        combinations.push(new Combination(combinationId, combinationIndex));
      });

      return combinations;
    },
    applyChangesOnCombinations: function applyChangesOnCombinations() {
      const values = this.getFormValues();
      const combinations = this.getSelectedCombinations();
      combinations.forEach((combination) => {
        combination.updateForm(values);
        combination.syncValues(values);
      });

      return this;
    },
    deleteCombinations: function deleteCombinations() {
      const combinations = this.getSelectedCombinations();
      const combinationsIds = [];
      combinations.forEach((combination) => {
        combinationsIds.push(combination.domId);
      });

      window.modalConfirmation.create(
        window.translate_javascripts['Are you sure you want to delete the selected item(s)?'],
        null,
        {
          onContinue() {
            const deletionURL = $(deleteCombinationsBtn).attr('data');
            $.ajax({
              type: 'DELETE',
              data: {
                'attribute-ids': combinationsIds,
              },
              url: deletionURL,
              beforeSend() {
                $('#create-combinations, #apply-on-combinations, #submit, .btn-submit').attr('disabled', 'disabled');
              },
              success(response) {
                window.showSuccessMessage(response.message);
                window.refreshTotalCombinations(-1, combinationsIds.length);
                $('span.js-bulk-combinations').text('0');
                combinationsIds.forEach((combinationId) => {
                  const combination = new Combination(combinationId);
                  combination.removeFromDOM();
                });
                window.displayFieldsManager.refresh();
              },
              error(response) {
                window.showErrorMessage(jQuery.parseJSON(response.responseText).message);
              },
              complete() {
                $('#create-combinations, #apply-on-combinations, #submit, .btn-submit').removeAttr('disabled');
              },
            });
          },
        }).show();
    },
    getFormValues: function getFormValues() {
      const values = [];
      $(bulkForm).find('input').each(function () {
        if ($(this).val() !== '' && $(this).attr('id') !== 'product_combination_bulk__token') {
          values.push({
            id: $(this).attr('id'),
            value: $(this).val(),
          });
        }
      });
      return values;
    },
    resetForm: function resetForm() {
      bulkForm.find('input').val('');

      return this;
    },
    unselectCombinations: function unselectCombinations() {
      // Use of the bulk action button. It has an event listener to unselect all the combinations
      $('#toggle-all-combinations').prop('checked', false);

      return this;
    },
    hideForm: function toggleForm() {
      bulkForm.collapse('hide');

      return this;
    },
    submitUpdate: function submitUpdate() {
      const globalProductSubmitButton = $('#form'); // @todo: choose a better identifier
      globalProductSubmitButton.submit();
    },
    syncToPricingTab: function syncToPricingTab() {
      $('tr.combination').toArray().forEach((item) => {
        const tableRow = $(`#${item.id}`);
        // We need this because there is a specific data="smthg" attribute so we can't use data() function
        const attributeId = tableRow.attr('data');

        // Get combination final price value from combination form
        const combinationFinalPrice = window.priceCalculation.getCombinationFinalPriceTaxExcludedById(attributeId);
        const combinationFinalPriceLabel = tableRow.find('.attribute-finalprice span.final-price');
        combinationFinalPriceLabel.html(combinationFinalPrice);

        // Update ecotax preview (tax included)
        let combinationEcotaxTI = window.priceCalculation.getCombinationEcotaxTaxIncludedById(attributeId);

        if (combinationEcotaxTI === 0) {
          combinationEcotaxTI = window.priceCalculation.getProductEcotaxTaxIncluded();
        }
        const ecoTaxLabel = tableRow.find('.attribute-finalprice span.attribute-ecotax');
        ecoTaxLabel.html(Number(window.ps_round(combinationEcotaxTI, 2)).toFixed(2)); // 2 digits for short
        const ecoTaxPreview = tableRow.find('.attribute-finalprice .attribute-ecotax-preview');
        ecoTaxPreview.toggleClass('d-none', Number(combinationEcotaxTI) === 0);
      });
    },
  };
}

class Combination {
  constructor(domId, index) {
    this.inputBulkPattern = 'product_combination_bulk_';
    this.inputPattern = `combination_${index}_`;
    this.domId = domId;
    this.appId = `attribute_${this.domId}`;
    this.element = $(`#${this.appId}`);
    this.form = $(`#combination_form_${this.domId}`);
  }

  isSelected() {
    return this.element.checked;
  }

  removeFromDOM() {
    $(this.element).remove();
  }

  updateForm(values) {
    values.forEach((valueObject) => {
      const valueId = valueObject.id.substr(this.inputBulkPattern.length);
      const $field = $(`#${this.convertInput(valueId)}`);

      if ($field.is(':checkbox')) {
        $field.prop('checked', !!valueObject.value);
      } else {
        $field.val(valueObject.value);
      }
    });
    return this.form;
  }

  /**
   * Returns the related input field in legacy form from
   * bulk form field
   *
   * @param bulkInput
   * @returns {string}
   */
  convertInput(bulkInput) {
    let convertedInput = '';

    switch (bulkInput) {
      case 'quantity':
      case 'reference':
      case 'minimal_quantity':
      case 'low_stock_threshold':
      case 'low_stock_alert':
        convertedInput = `${this.inputPattern}attribute_${bulkInput}`;
        break;
      case 'cost_price':
        convertedInput = `${this.inputPattern}attribute_wholesale_price`;
        break;
      case 'date_availability':
        convertedInput = `${this.inputPattern}available_date_attribute`;
        break;
      case 'impact_on_weight':
        convertedInput = `${this.inputPattern}attribute_weight`;
        break;
      case 'impact_on_price_te':
        convertedInput = `${this.inputPattern}attribute_price`;
        break;
      case 'impact_on_price_ti':
        convertedInput = `${this.inputPattern}attribute_priceTI`;
        break;
      default:
    }

    return convertedInput;
  }

  /**
   * Sync values with fast bulk edit form of each combination
   *
   * @param values
   * @returns {bool}
   */
  syncValues(values) {
    values.forEach((valueObject) => {
      let valueId = valueObject.id.substr(this.inputBulkPattern.length);
      const {value} = valueObject;

      const syncedProperties = [
        'quantity',
        'impact_on_price_te',
      ];

      if (syncedProperties.indexOf(valueId) !== -1) {
        valueId = valueId === 'quantity' ? 'quantity' : 'price';
        const input = $(`#attribute_${this.domId} .attribute-${valueId} input`);
        input.val(value);
        input.change();
      }
    });

    return true;
  }
}
