$.widget('wpj.autocomplete', {
   options: {
      $menu: null,

      minLength: 2,
      xhr: null,

      preload: null,
      preloadedContent: null,

      source: null,
      localePrefix: null,

      searchTimer: 650,

      template: '{{~it.items :item :index}} {{#def.menuItem}} {{~}}',
      subtemplates: {
         menuItem:
            '<div data-autocomplete-item="{{? item.value }}{{=item.value}}{{??}}{{=item.label}}{{?}}">{{=item.label}}</div>'
      }
   },
   _create: function() {
      this._super();

      let localePrefixedSource = this.options.source;

      if (this.options.localePrefix) {
         localePrefixedSource = this.options.localePrefix + this.options.source;
      }

      this.options.source = wpj.template.compile(localePrefixedSource);

      var me = this;
      this.element.on('input', function(e) {
         var term = me.element.val();

         if (term.length >= me.options.minLength) {
            wpj.domUtils.resetTimer('autocomplete', me.options.searchTimer, function() {
               me.search(term);
            });
         } else {
            me.cancelSearch();
            me.close();
            if (me.options.preload && term.length === 0) {
               me.openPreloadMenu();
            }
         }
      });

      this.element.on('focus', function(e) {
         if (me.options.preload) {
            me.openPreloadMenu();
         } else if (me.options.minLength === 0) {
            wpj.domUtils.resetTimer('autocomplete', 300, function() {
               me.search('');
            });
         }
      });
   },
   search: function(term) {
      if (this.options.xhr) {
         this.options.xhr.abort();
      }

      term = encodeURIComponent(term);

      var me = this,
         url = this.options.source({ value: term });
      this.options.xhr = $.getJSON(url, function(data) {
         me.open();
         me.render({ ...{searchTerm: term}, ...me.prepareData(data)});
      });
   },
   cancelSearch: function() {
      if (!this.options.xhr) {
         return false;
      }

      this.options.xhr.abort();
      this.options.xhr = null;
   },
   prepareData: function(data) {
      return { items: data };
   },
   select: function(e, $item) {
      var $link = $(e.target).closest('a[href]');
      if ($link.attr('href')) {
         return true;
      }

      if ($item.length === 0) {
         return false;
      }

      // products search - open focused product on enter in autocomplete
      $link = $item.find('a');
      if ($link.attr('href')) {
         $(location).attr('href', $link.attr('href'));
         return true;
      }

      var value = $item.data('autocomplete-item');

      this.element.val(value);

      return false;
   },
   onKeyPress: function(e) {
      switch (e.key) {
         case 'ArrowDown':
            if (isNaN(this.selectPosition)) {
               this.selectPosition = -1;
            }

            this.selectPosition++;

            this.focusItem(this.selectPosition);

            break;
         case 'ArrowUp':
            if (!isNaN(this.selectPosition) && this.selectPosition > 0) {
               this.selectPosition--;
            }

            this.focusItem(this.selectPosition);

            break;
         case 'Enter':
            var $item = $(this.options.$menu[0]).find('[data-autocomplete-position="' + this.selectPosition + '"]');
            this.select(e, $item);
            this.close();
            break;
         default:
            return true;
      }

      return false;
   },
   focusItem: function(itemId) {
      const $item = $(this.options.$menu[0]).find('[data-autocomplete-position="' + itemId + '"]');
      if ($item.length) {
         $item.get(0).focus();
      }

      return true;
   },
   openPreloadMenu: function () {
      // uz se to jednou preloadnulo, a nema smysl to nacitat znovu, kdyz je to static
      if (this.options.preloadedContent) {
         this.open();
         this.options.$menu.html(this.options.preloadedContent);
         return;
      }

      const me = this;

      // preloadnout content
      fetch(this.options.preload)
         .then((response) => response.json())
         .then((data) => {
            me.options.preloadedContent = data.html;
            me.open();
            me.options.$menu.html(data.html);
         });
   },
   open: function() {
      if (this.element.is('.opened')) {
         return false;
      }

      var me = this;

      if (!this.options.$menu) {
         this.options.$menu = $('<div class="autocomplete"></div>').insertAfter(this.element);
      }

      this.element.addClass('opened');
      this.options.$menu.addClass('opened');

      this.options.$menu.on('click', '[data-autocomplete-item]', function(e) {
         me.close();
         return me.select(e, $(e.currentTarget));
      });

      $('body')
         .on('click.productSearch', function(e) {
            if ($(e.target).is(me.element) || me.element.has(e.target).length || $(e.target).closest('.autocomplete.opened').length) {
               return;
            }

            me.close();
         })
         .on('keypress.productSearch', function(e) {
            if (e.key != 'Escape') {
               return me.onKeyPress(e);
            }

            me.hide();
            return false;
         });
   },
   close: function() {
      if (!this.element.is('.opened')) {
         return false;
      }

      this.element.removeClass('opened');
      this.options.$menu.removeClass('opened');

      $('body')
         .off('keydown.hereAddressAutocomplete')
         .off('click.productSearch')
         .off('keypress.productSearch');
   },
   render: function(data) {
      var template = this.getTemplate(),
         html = template(data);

      this.options.$menu.html(html);
   },
   getTemplate: function() {
      return wpj.template.compile(this.options.template, this.options.subtemplates);
   }
});

$.widget('wpj.productSearch', $.wpj.autocomplete, {
   options: {
      source: '/autocomplete/?type=product-categories&term={{=it.value}}',
      template: '#productSearch'
   },
   search: function(term) {
      if (this.options.xhr) {
         this.options.xhr.abort();
      }

      term = encodeURIComponent(term);

      var me = this,
         url = this.options.source({ value: term });
      this.options.xhr = $.getJSON(url, function(data) {
         me.open();

         const results = { ...{searchTerm: term}, ...me.prepareData(data)};

         const insertResult = (name, callback) => {
            const items = results?.items[name]?.items;
            let returnItem = null;

            if (typeof items !== 'undefined' && typeof items !== 'undefined') {
               returnItem = $.map(items, function(item) {
                  if (name === 'Produkty' && typeof item.price_array === 'undefined') {
                     return null;
                  }

                  return callback(item);
               });
            }

            if(!items || (returnItem && returnItem.length === 0)) {
               returnItem = null
            }

            return returnItem
         }

         var layerSearch = {
            'event': 'whisperSearch',
            'search': {
               'searchTerm': term,
               'results': {
                  'products': insertResult('Produkty', (item) => {
                     return {
                        'id': item.id ?? null,
                        'name': item.label ?? null,
                        'price': item.price_array.price_without_vat ?? null,
                        'brand': item.producer.name ?? null,
                     }
                  }),
                  'articles': insertResult('Clanky', (item) => {
                     return {
                        'id': item.id ?? null,
                        'label': item.label ?? null,
                        'image': item.photo ?? null
                     }
                  }),
                  'categories': insertResult('Kategorie', (item) => {
                     return {
                        'id': item.id ?? null,
                        'name': item.name ?? null,
                        'path': item.path ?? null,
                        'label': item.label ?? null,
                        'imageUrl': item.photo_src ?? null,
                     }
                  }),
                  'producers': insertResult('Vyrobci', (item) => item),
                  'pages': insertResult('Stranky', (item) => item)
               }
            }
         };
         if (window.dataLayer) {
            window.dataLayer.push(layerSearch);
         }
         me.render(results);
      });
   },
   select: function(e, $item) {
      if ($item.data('autocomplete-item') != 'show-all') {
         if (this._super(e, $item)) {
            return true;
         }
      }

      $(this.element[0].form)
         .find('[type=submit]')
         .click();

      return false;
   }
});

if (MODULES.LUIGIS_BOX) {
   $.widget('wpj.productSearchLuigi', $.wpj.productSearch, {
      options: {
         trackerId: '',
         template: '#productSearch',
         modifyData: (data, attributes) => data
      },

      _create: function() {
         this._super();
         this.options.source = `https://live.luigisbox.com/autocomplete/v2?q={{=it.value}}&tracker_id=${this.options.trackerId}&unroll_variants=never&type=item:50,category,brand,article`;
         this.options.source = wpj.template.compile(this.options.source);

      },

      prepareData: function(data) {
         var products = [],
            categories = [],
            producers = [],
            articles = [];

         const form = this.element[0].form;
         let $hiddenInput = $(form).find('input[name="suggested_url"][type="hidden"]');
         if (data.suggested_url) {
            if ($hiddenInput.length === 0) {
               $hiddenInput = $('<input>', {
                  type: 'hidden',
                  name: "suggested_url",
                  value: data.suggested_url
               });
               $(form).append($hiddenInput);
            } else {
               $hiddenInput.val(data.suggested_url);
            }
         } else if ($hiddenInput.length > 0) {
            $hiddenInput.remove();
         }

         data.hits.forEach((item) => {
            const data = item.attributes;
            switch (item.type) {
               case 'item':
                  products.push(this.options.modifyData({
                     id: data['original_url'] ?? 0,
                     image: data['image_link'] ?? '',
                     label: data['title.untouched'] ?? data['title'] ?? '',
                     discount: data['discount_price_percentage_amount'] ?? 0,
                     price: data.price ?? 0, // TODO rozlišit ceny pro reg uživatele
                     priceOriginal: data.price_old ?? '',
                     producer: { name: data?.brand?.[0] ?? '' },
                     price_array: { price_without_vat: data.price_no_vat ?? 0 }

                  }, data));
                  break;
               case 'category':
                  categories.push(this.options.modifyData({
                     id: data['original_url'] ?? 0,
                     name: data['title.untouched'] ?? data['title'] ?? ''
                  }, data));
                  break;
               case 'brand':
                  producers.push(this.options.modifyData({
                     id: data['original_url'] ?? 0,
                     name: data['title.untouched'] ?? data['title'] ?? '',
                     label: data['title.untouched'] ?? data['title'] ?? ''
                  }, data));
                  break;
               case 'article':
                  articles.push(this.options.modifyData({
                     id: data['original_url'] ?? 0,
                     photo: data['image_link'] ?? '',
                     label: data['title.untouched'] ?? data['title'] ?? '' ?? ''
                  }, data));
                  break;
            }
         });

         const result = {};

         if (products.length) {
            result['Produkty'] = {
               label: 'Produkty',
               items: products
            };
         }
         if (categories.length) {
            result['Kategorie'] = {
               label: 'Kategorie',
               items: categories
            };
         }
         if (articles.length) {
            result['Clanky'] = {
               label: 'Články',
               items: articles
            };
         }
         if (producers.length) {
            result['Vyrobci'] = {
               label: 'Výrobci',
               items: producers
            };
         }
         return { items: result };

      }
   });
}

$.widget('wpj.deliveryAutocomplete', $.wpj.autocomplete, {
   options: {
      inputId: null
   },
   _create: function() {
      this._super();

      var $input = this.element;
      var $inputId = this.options.inputId;
      var $deleteZip = $input.closest('[data-delivery-class]').find('.delete-zip');
      var me = this;

      $input.on('change', function() {
         $deleteZip.addClass('active');
      });

      if ($input.val()) {
         $deleteZip.addClass('active');
      }

      $deleteZip.click(function() {
         $input.val('');

         if (me.options.inputId) {
            $inputId.val('').trigger('change');
         }

         $deleteZip.removeClass('active');
      });
   },
   select: function(e, $item) {
      if (this.options.inputId) {
         this.options.inputId.val($item.data('autocomplete-value'));
      }

      this.element.val($item.data('autocomplete-name'));
      this.element.change();
   }
});

$.widget('wpj.hereAddressAutocomplete', $.wpj.autocomplete, {
   options: {
      input: null,
      type: null,
      searchTimer: 300,
      countryCode: 'CZE',
      resultsType: null,
      subtemplates: {
         menuItem:
            '<div' +
            ' tabindex="-1"' +
            ' data-autocomplete-position="{{=index}}"' +
            ' data-autocomplete-item="{{? item.id }}{{=item.id}}{{??}}{{=item.address.label}}{{?}}"' +
            ' data-autocomplete-item-street="{{? item.address.street}}{{=item.address.street}} {{?}}{{? item.address.houseNumber}}{{=item.address.houseNumber}}{{?}}"' +
            ' data-autocomplete-item-city="{{=item.address.city}}"' +
            ' data-autocomplete-item-zip="{{=item.address.postalCode}}"' +
            ' data-autocomplete-item-countycode="{{? item.address.countyCode}}{{=item.address.countyCode}}{{??}}{{? item.address.county}}{{=item.address.county}}{{?}}{{?}}"' +
            '>' +
            '{{=item.address.label}}' +
            '</div>'
      }
   },
   search: function(term) {
      if (this.options.xhr) {
         this.options.xhr.abort();
      }

      /* Pokud je aktivovaný smartform, použije se k našeptání ten (ale jen pro CZ a SK adresy) */
      if ($.inArray(this.options.countryCode, ['CZE', 'SVK']) >= 0 && typeof smartform !== 'undefined' && smartform.isAddressServiceEnabled()) {
         return false;
      }

      term = encodeURIComponent(term);
      this.options.source = `https://autocomplete.search.hereapi.com/v1/autocomplete?apiKey=ocu3EtHk1cEZxNKt68Cb_LuJv3GH776B3nrcevQnCAA&in=countryCode:${this.options.countryCode}${this.options.resultsType ? `&types=${this.options.resultsType}` : ''}&q=`;

      var me = this,
         url = this.options.source + term;
      this.options.xhr = $.getJSON(url, function(data) {
         me.open();
         me.render(data);
      });
   },
   select: function(e, $item) {
      if ($item[0]) {
         for (const [name, value] of Object.entries($item[0].dataset)) {
            const field_name = name.replace('autocompleteItem', '').toLowerCase();
            const $field = $(`[data-field-${this.options.type}-${field_name}]`);
            if (/*($field[0] === this.options.input[0] || !$field.val()) && */ value && value.indexOf('undefined') < 0) {
               $field.val(value).change();
            }
         }
      }
   },
   open: function() {
      this._super();

      var me = this;
      this.selectPosition = NaN;

      me.element.off('keydown.hereAddressAutocomplete')
         .on('keydown.hereAddressAutocomplete', function(e) {
            if (e.key != 'Escape') {
               return me.onKeyPress(e);
            }

            me.close();
            return false;
         });

      me.options.$menu.off('keydown.hereAddressAutocomplete')
         .on('keydown.hereAddressAutocomplete', function(e) {
            if (e.key != 'Escape') {
               return me.onKeyPress(e);
            }

            me.close();
            return false;
         });
   },
   close: function() {
      this._super();

      this.element.off('keydown.hereAddressAutocomplete');
      if (this.options.$menu) {
         this.options.$menu.off('keydown.hereAddressAutocomplete');
      }
   }
});
