/*
Klasické wpj.product.variations přepsané do Class syntaxe. Mělo by to zjednodušit předefinování
jedné funkce na e-shopu bez nutnosti kopírovat celý skript. Pro použití je potřeba změnit include
ve wpj.product.js na

if (MODULES.PRODUCTS_VARIATIONS) {
   const { WpjProductVariations } = require('@assets/js/wpj.product.variations.class.js');
   const variations = new WpjProductVariations($('[data-variations="variations"]'));

   initBuyForm(true, variations);
} else {
   initBuyForm(false);
}
 */

export class WpjProductVariations {
   constructor(allVariations) {
      this.allVariations = allVariations;
      this.sizeConvertionWrapper = $('[data-variation-size-convertion-wrapper]');

      if (!allVariations) {
         return false;
      }

      const me = this;

      if (allVariations.length) {

         let queries = {};
         $.each(document.location.search.substr(1).split('&'),function(c,q){
            const i = q.split('=');
            if (i[0] && i[1]) {
               queries[i[0].toString()] = i[1].toString();
            }
         });

         const hash = location.href.split('#')[1] || queries['id_variation'] ||'';

         if (hash.length > 0 && !isNaN(parseFloat(hash)) && isFinite(hash)) {
            const $variant = allVariations.find(`[name^="IDvariation"][value="${hash}"]`);

            if ($variant.length) {
               $variant.click();
            }

            this.checkSelectedVariation(allVariations);
         } else if (allVariations.find('input[name^="IDvariation"]:checked')) {
            this.checkSelectedVariation(allVariations);
         }
      }

      allVariations.on('change', 'input[name^="IDvariation"]', function() {
         if (me.sizeConvertionWrapper) {
            allVariations.find('[name^="IDvariation"]:checked').prop('checked', false);
            $(this).prop('checked', true);
         }

         me.checkSelectedVariation(allVariations);
      });

      allVariations.on('change', 'input[name^="IDLabel"]', function() {
         me.checkVarFromLabels($(this));
      });
   }

   validateVariations(allVariations) {
      if (allVariations.length) {
         const selectedVariation = allVariations.find('[name^="IDvariation"]:checked');
         if (!selectedVariation.length) {
            return false;
         }
      }

      return true;
   }

   selectConvertionVariation(var_id) {
      const $siblingsVariations = this.sizeConvertionWrapper.find('input[value="' + var_id + '"]');
      $siblingsVariations.prop('checked', true);

      let selected_title = '';
      $siblingsVariations.each(function(index) {
         selected_title = selected_title + (index === 0 ? '' : '&nbsp;&nbsp;|&nbsp; ') + $(this).next('label').data('title');
      });

      $('[data-variation-size-convertion-trigger]').html(selected_title);
   }

   checkSelectedVariation(allVariations) {
      const $selectedVariation = allVariations.find('[name^="IDvariation"]:checked');
      const selectedVarId = $selectedVariation.val();
      // todo sjednotit ?? IDproduct = buy_form | id_product = watchdog
      const productId = $('[data-detail-productid][name="IDproduct"]').val() ?? $('[name="id_product"]').val();

      if (selectedVarId) {
         const varData = wpj.variations[selectedVarId];
         if (varData && varData.combinations) {
            this.checkLabels(varData.combinations);

            const $otherLabels = $('input[name^="IDLabel"]');
            this.disableInvalidLabels($otherLabels, varData.combinations);
         }

         if (this.sizeConvertionWrapper) {
            this.selectConvertionVariation(selectedVarId);
         }

         if ($('[data-reload^="variation"]').length) {
            wpj.domUtils.reloadPartsFromUrl(`/_shop/variation/${productId}/${selectedVarId}/`, $('[data-reload^="variation"]'), null, null);
         } else {
            $('.btn-insert [data-variation-error]').hide();

            if (!$('[data-quantity-discounts="quantityDiscounts"]').length) {
               import('@assets/js/wpj.product.helpers.js').then(wpjHelpers => {
                  wpjHelpers.updateProductPrice(varData.price, varData.priceNoVat, varData.priceCommon);
               })
            }

            if (varData.bonusPoints) {
               $('[data-bonus-points]').html(varData.bonusPoints);
            }

            if (varData.ean) {
               $('[data-ean]').html(varData.ean);
            }

            if (varData.flag) {
               $('[data-flag]').html(varData.flag);
            }

            if (varData.combinations) {
               this.checkLabels(varData.combinations);

               const $otherLabels = $('input[name^="IDLabel"]');
               this.disableInvalidLabels($otherLabels, varData.combinations);
            }

            if (typeof varData.watchdog !== 'undefined' && MODULES.WATCHDOG) {
               import('@assets/js/wpj.watchdog.js').then(wpjWatchdog => {
                  wpjWatchdog.updateVarWatchdog(varData, selectedVarId);
               });
            }

            $('[data-deliverytime]')
               .html(varData.deliveryTime)
               .attr('class', function(i, c) {
                  return c.replace(/(^|\s)(delivery-)(-?\d+)/g, '$1$2' + varData.deliveryTimeIndex);
               });

            if (MODULES.QUANTITY_DISCOUNT) {
               import('@assets/js/wpj.quantity-discount.js').then(quantityDiscounts => {
                  quantityDiscounts.reloadQuantityDiscounts($selectedVariation.val());
               });
            }
         }
          $selectedVariation.trigger('variationSelected');
      }

      if (history.replaceState) {
         history.replaceState(
            null,
            null,
            typeof $selectedVariation.val() != 'undefined' ? '#' + $selectedVariation.val() : ''
         );
      }
   }

   checkLabels(combinations) {
      for (const comb in combinations) {
         $(`[name="IDLabel_${comb}"][value="${combinations[comb]}"]`).prop('checked', true);
      }
   }

   /**
    * Searches through wpj.variations object for variation with given label combination
    * @param {object} combinations { id_label: value, ... }
    * @returns {(number|false)} matching variation ID
    */
   findVariation(combinations) {
      let len = Object.getOwnPropertyNames(combinations).length;
      for (const variation in wpj.variations) {
         let count = 0;

         for (const comb in combinations) {
            if (wpj.variations[variation].combinations[comb] === combinations[comb]) {
               count++;
            }
         }

         if (count === len) {
            return variation;
         }
      }
      return false;
   }

   /**
    * Returns label ID and value from input
    * @param {jQuery} $input - jQuery obj. input
    * @returns {number[]} ID label, ID value
    */
   getLabelAndValue($input) {
      const comb_id = $input.attr('name').split('_')[1];
      const value = parseInt($input.val());
      return [comb_id, value];
   }

   disableInvalidLabels($otherLabels, combinations) {
      var me = this;
      $otherLabels.each(function() {
         const $this = $(this);
         const labelAndValue = me.getLabelAndValue($this);
         const local_combination = { ...combinations };
         local_combination[labelAndValue[0]] = labelAndValue[1];

         const variation = me.findVariation(local_combination);
         $this.toggleClass('disabled', !variation);

         if (variation && wpj.variations[variation].hasOwnProperty('watchdog')) {
            $this.toggleClass('soldout', variation && wpj.variations[variation]['watchdog']);
         }

         $('body').trigger('eachLabel', {'label': $this, 'variationId': variation});
      });
   }

   checkVarFromLabels($el) {
      const me = this;
      const $allLabels = me.allVariations.find('input[name^="IDLabel"]:checked');
      let combinations = {};
      let variation;

      $el.removeClass('disabled');

      $allLabels.each(function() {
         const labelAndValue = me.getLabelAndValue($(this));
         combinations[labelAndValue[0]] = labelAndValue[1];
      });

      var $otherLabels = $el
         .closest('form')
         .find('input[name^="IDLabel"]')
         .not('[name=' + $el.attr('name') + ']');

      variation = this.findVariation(combinations);

      if (!variation) {
         const labelAndValue = me.getLabelAndValue($allLabels.first());
         combinations = {};
         combinations[labelAndValue[0]] = labelAndValue[1];
         variation = this.findVariation(combinations);
      }

      if (variation) {
         $(`[name="IDvariation"][value="${variation}"]`).click();
      } else {
         console.log('neexistujici varianta');
         $('.btn-insert [data-variation-error]').show();
         $('[name="IDvariation"]:checked').prop('checked', false);
         $otherLabels.filter(':checked').prop('checked', false);
         this.disableInvalidLabels($otherLabels, combinations);
         $otherLabels
            .filter(':not(.disabled)')
            .first()
            .click();
      }
   }
}
