$.widget('wpj.cart', {
   options: {
      $form: null,
      delivery_types: null,
      select_first: true,
      reload_containers: null,
      custom_delivery_error_callback: null,
      js_shop_reload_event: false // call wpj.jsShop.refresh('cart-detail'); after change, should only be called in first step
   },
   reloadXMLHttpRequest: null,
   doReloadCart: function(url) {
      var data = this.options.$form.serializeArray(),
         me = this;

      var $parts = this.options.$form.find('[data-reload]');

      if (this.options.reload_containers) {
         $.merge($parts, this.options.reload_containers);
      } else {
         $.merge($parts, $('[data-reload=cart-info]'));
      }

      url = url || '?act=recount';

      if (this.reloadXMLHttpRequest) {
         this.reloadXMLHttpRequest.abort();
      }

      if (this.options.js_shop_reload_event && wpj.jsShop && 'clearCache' in wpj.jsShop) {
         wpj.jsShop.clearCache();
      }

      this.reloadXMLHttpRequest = $.post(
         url,
         data,
         function(data) {
            var $newHtml = wpj.domUtils.parseHtml(data);
            $newHtml.find('input[name=payment_id]').each(function() {
               $(this).attr('name', 'payment_id_new');
            });

            var newParts = wpj.domUtils.crossFadeParts($parts, $newHtml, function($old, $new) {
               $old.remove();
               $new.find('input[name=payment_id_new]').each(function() {
                  var $this = $(this);
                  $this.attr('name', 'payment_id');
               });
            });

            me.element.trigger('loaded', [$(newParts)]);

            if (me.options.js_shop_reload_event && 'refresh' in wpj.jsShop) {
               try {
                  wpj.jsShop.refresh('cart-detail'); // jsshop will refresh only if config.ts cartDetailRefresh is true
               } catch (e) {
                  console.log('wpj.cart.js: ', e);
               }
            }
         },
         'html'
      );
   },
   reloadCart: function() {
      var me = this;
      wpj.domUtils.resetTimer('cart', 500, function() {
         me.doReloadCart();
      });
   },
   getItem: function($this) {
      return $this.closest('[data-cart=row]').find('input[name*=pieces]');
   },
   onSpinButton: function(e) {
      // $item = input, $this = button
      var $this = $(e.currentTarget);
      var $item = this.getItem($this);
      var diff = 0;

      var step = $item.attr('step') ? parseFloat($item.attr('step')) : 1;
      var precision = $item.data('precision') ? parseFloat($item.data('precision')) : 0;
      var min = $item.attr('min') ? parseFloat($item.attr('min')) : 1;

      // skryje button pokud BUTTON ma data-max="..."
      // Bacha, musi se oifovat i v template, jinak se tlacitko po reloadu kosiku zase objevi
      if ($this.data('max') === Number($item.val()) + step) {
         $this.hide();
      }

      if ($this.data('cart') === 'plus' && parseFloat($item.attr('max')) === Number($item.val()) + step) {
         $this.addClass('disabled');
      }

      if (
         ($this.data('cart') === 'plus' && parseFloat($item.attr('max')) === Number($item.val())) ||
         ($this.data('cart') === 'minus' && parseFloat($item.attr('min')) === Number($item.val()))
      ) {
         return false;
      }

      if ($this.data('cart') === 'plus') {
         diff = +step;
      } else {
         diff = -step;
      }

      if (Number($item.val()) + diff < min) {
         diff = 0;
      }

      $item.val(Math.max(Number($item.val()) + diff, step).toFixed(precision));

      this.reloadCart();
   },
   onRowDelete: function(e) {
      var url = $(e.currentTarget).attr('href');

      this._trigger('rowdelete', e, {
         id: $(e.currentTarget)
            .closest('[data-product-id]')
            .data('product-id') // todo pridat data-atribut do ordering.cart s id, posilat v data id smazaneho produktu
      });
      this.doReloadCart(url);
      e.preventDefault();
   },
   onPiecesKeydown: function(e) {
      if (e.keyCode === 13) {
         e.preventDefault();
         $(e.target).blur();
      }
   },
   onChange: function(e) {
      var $this = $(e.target);
      if ($this.data('cart') === 'pieces' && $this.val() === '') {
         return;
      }
      if ($this.data('cart') === 'noreload' || $this.closest('[data-cart-noreload]').length) {
         return;
      }

      this.reloadCart();
   },
   onPaymentChange: function(e) {
      if (e) {
         var id = $(e.target).val();
         var $element = $('#payment_description_' + id);

         $element.not(':visible').slideDown('slow');

         $('.payment_description')
            .not($element)
            .filter(':visible')
            .slideUp('slow');

         const $selectedInput = $(e.currentTarget);
         $selectedInput.closest('[data-box="payments"]').find('.payment-item.selected').removeClass('selected');
         if($selectedInput.val() === '-1') {
            $selectedInput.closest('.deliveries').removeClass('payment-selected');
         } else {
            $selectedInput.closest('.deliveries').addClass('payment-selected');
            $selectedInput.closest('.payment-item').addClass('selected');
         }
      }

      this._trigger('paymentchange', e);
      document.querySelector('#cart').dispatchEvent(new CustomEvent('$cartpaymentchange', {
         detail: {
            originalEvent: e,
         }
      }));
   },
   onDeliveryChange: function(e) {
      var me = this,
         delivery_id = e ? $(e.target).val() : 0,
         allowed_payments = this.options.delivery_types[delivery_id],
         $payments = this.getPayments();

      var $this,
         enabled,
         enabledCount = 0,
         index;
      $payments.each(function() {
         $this = $(this);
         index = $this.val().split('-')[0];
         enabled = allowed_payments && allowed_payments[index] != undefined && !$this.data('exception');

         if (enabled) {
            enabledCount++;
         }

         if (!enabled && $this.prop('checked')) {
            $this.prop('checked', false);
            me.onPaymentChange();
         }

         me.disableDeliveryItem($this, !enabled);
      });

      if (
         this.options.select_first &&
         this.options.$form.find('input[name=payment_id]:checked').not(':disabled').length === 0
      ) {
         enabledCount = 1;
      }

      if (enabledCount === 1) {
         this.options.$form
            .find('input[name=payment_id]')
            .not(':disabled')
            .eq(0)
            .prop('checked', true).click();
      }

      if (e) {
         $this = $(e.target);
         var id = $this.val(),
            $element = $('#delivery_description_' + id);
         $element.not(':visible').slideDown('slow');
         $('.delivery_description')
            .not($element)
            .filter(':visible')
            .slideUp('slow');
      } else {
         $('.delivery_description')
            .filter(':visible')
            .slideUp('slow');
      }

      const $selectedInput = $(e.currentTarget);
      $selectedInput.closest('[data-box="deliveries"]').find('[data-cart="item"].selected').removeClass('selected');
      //pokud je mozne vybrat pouze jednu platbu a ta se predvybere (radek 191-197) tak te predvybrane neodebrat classu selected, pak je sice vybrana ale neni videt v collapsible deliveries (oprava tiket 9511)
      if (enabledCount !== 1) {
         $selectedInput.closest('.deliveries').find('.payment-item.selected').removeClass('selected');
      }
      if($selectedInput.val() === '-1') {
         $selectedInput.closest('.deliveries').removeClass('delivery-selected payment-selected');
      } else {
         $selectedInput.closest('.deliveries').addClass('delivery-selected');
         $selectedInput.closest('[data-cart="item"]').addClass('selected');
      }

      this._trigger('deliverychange', e, { delivery_id: delivery_id });
      document.querySelector('#cart').dispatchEvent(new CustomEvent('$cartdeliverychange', {
         detail: {
            originalEvent: e,
            delivery_id: delivery_id,
         }
      }));
   },
   disableDeliveryItem: function($item, disable) {
      $item.prop('disabled', disable);
      $item.closest('[data-cart=item]').toggleClass('disabled', disable);
   },
   initializeDeliveryTypes: function() {
      // Convert deliveryTypes list to better format
      var deliveries = {},
          delivery;

      for (var index in this.options.delivery_types) {
         delivery = this.options.delivery_types[index];

         if (deliveries[delivery[0]] === undefined) {
            deliveries[delivery[0]] = {};
         }

         deliveries[delivery[0]][delivery[1]] = true;
      }

      this.options.delivery_types = deliveries;

      // Disable unavailable fields
      var $payments = this.getPayments();

      // Disable all payments. Will get enabled again if delivery is selected
      this.disableDeliveryItem($payments, true);

      // Simulate click on pre-selected options
      $('input[name=delivery_id][checked]', this.options.$form).click();
      $('input[name=payment_id][checked]', this.options.$form).click();
   },
   getPayments: function () {
      return this.options.$form.find('input[name=payment_id]').not('[data-payment-reset]');
   },
   getDeliveries: function () {
      return this.options.$form.find('input[name=delivery_id]').not('[data-delivery-reset]');
   },
   onFormSubmit: function(hasError) {
      $('[name="OrderNext"]').addClass('is-submitting');
      wpj.domUtils.resetTimer('cart', 500, function() {
         // Nic nedělám - zabráním tím reloadnutí košíku po tom, co jsem zmáčknul odeslání košíku
      });
      var deliveryPick = this.getDeliveries(),
          paymentPick = this.getPayments();

      hasError = hasError || {};

      if (deliveryPick.length && !deliveryPick.is(':checked')) {
         if (this.options.custom_delivery_error_callback) {
            this._trigger('deliveryerror');
         } else {
            const delivery_alert = $('[data-alert-choose-delivery]').data('alert-choose-delivery');
            window.alert(delivery_alert ? delivery_alert : 'Vyberte prosím způsob dopravy');
         }

         $('[name="OrderNext"]').removeClass('is-submitting');
         hasError.error = true;
         return false;
      }

      if (paymentPick.length && !paymentPick.is(':checked')) {
         if (this.options.custom_delivery_error_callback) {
            this._trigger('paymenterror');
         } else {
            const payment_alert = $('[data-alert-choose-payment]').data('alert-choose-payment');
            window.alert(payment_alert ? payment_alert : 'Vyberte prosím typ platby');
         }

         $('[name="OrderNext"]').removeClass('is-submitting');
         hasError.error = true;
         return false;
      }
   },
   onStepSubmit: function(e) {
      $(e.currentTarget).addClass('is-submitting');
   },
   _create: function() {
      var me = this;

      this.options.$form = this.element.closest('form');

      this._on(this.options.$form, {
         'click [data-cart=plus], [data-cart=minus]': this.onSpinButton,
         'click [data-cart=delete]': this.onRowDelete,
         change: this.onChange,
         ifChanged: this.onChange,
         'keydown input[data-cart="pieces"]': this.onPiecesKeydown,
         'click [name="OrderNext"]': this.onStepSubmit
      });

      if (this.options.delivery_types) {
         this._on(this.options.$form, {
            'click input[name=delivery_id]': this.onDeliveryChange,
            'click input[name=payment_id]': this.onPaymentChange
         });

         this.initializeDeliveryTypes(this.options.delivery_types);

         // Preselect if only one delivery
         var $deliveries = $('input[name=delivery_id]');

         if ($deliveries.length === 1 && !$deliveries.prop('checked')) {
            $deliveries.eq(0).click();
         }

         if (this.options.select_first && $deliveries.filter(':checked').length === 0) {
            $deliveries
               .filter(':enabled')
               .eq(0)
               .click();
         }

         if (this.options.select_first) {
            var $payments = $('input[name=payment_id]');
            $payments.filter(':checked').eq(0).click();
         }

         this.options.$form.on('success.form.bv', function(w, hasError) {
            return me.onFormSubmit(hasError);
         });
      }
   }
});
