wpj.focus = {
   focusName: ADMIN ? "focusAdmin" : "focus",
   create: (options) => {
      let focusName = ADMIN ? "focusAdmin" : "focus";
      let $wpjFocuses = wpj.focus.getFocuses();
      const template = $(wpj.focus.getFocusLoadingTemplate());
      $wpjFocuses.append(template);

      const $focus = template[focusName](options);

      $focus[focusName]('load');

      return $focus[focusName]('instance');
   },
   createDeduplicated: (endpoint, ajaxSubmit = false, removeOnClose = false, focusCustomClass = null, focusTriggerEventName = null) => {
      // zaridim, ze existuje wrapper, ve kterem budu focusy vytvaret
      let $wpjFocuses = wpj.focus.getFocuses();
      let focusName = ADMIN ? "focusAdmin" : "focus";

      // pokud jsem focus uz jednou vytvoril, tak otevru ten uz vytvoreny
      const $existingFocus = $wpjFocuses.find('.focus[data-focus-endpoint="'+ endpoint +'"]');
      if ($existingFocus.length) {
         $existingFocus[focusName]('show');
         return;
      }

      // pridam novy focus s vychozi loading sablonou
      $wpjFocuses.append(
         wpj.focus.getFocusLoadingTemplate(endpoint)
      );

      // inicializuju focus a zavolam na nem load, aby se naloadoval
      const $focus = $wpjFocuses.find('.focus[data-focus-endpoint="'+ endpoint +'"]')[focusName]({
         opened: true,
         onDemandEndpoint: endpoint,
         ajaxSubmit: ajaxSubmit,
         removeOnClose: removeOnClose,
         focusCustomClass: focusCustomClass,
         focusTriggerEventName: focusTriggerEventName
      });

      $focus[focusName]('load');
   },
   getFocusLoadingTemplate: (endpoint) => {
      if (endpoint){
         return '<div data-focus-endpoint="' + endpoint + '" class="focus"><div class="focus-dialog"><div class="focus-content"><div class="focus-loading"></div></div></div></div>';
      }
      return '<div class="focus"><div class="focus-dialog"><div class="focus-content"><div class="focus-loading"></div></div></div></div>';
   },
   getFocuses: () => {
      let $wpjFocuses = $('[data-wpj-focuses]');
      if (!$wpjFocuses.length) {
         // vytvorim si wrapper
         $('body').append('<div data-wpj-focuses style="z-index: 999"></div>');
         $wpjFocuses = $('[data-wpj-focuses]');
      }
      return $wpjFocuses;
   }
};

$.widget("wpj." + wpj.focus.focusName, {
   options: {
      opened: false,
      closeOnBgClick: true,
      addBodyPadding: false,
      onDemandEndpoint: null,
      ajaxSubmit: false,
      removeOnClose: false,
      show: null,
      hide: null,
   },
   _create: function() {
      var me = this;

      this.element.on('click', '[data-focus=close]', function() {
         return me.hide();
      });

      this._super();

      if (this.options.opened) {
         this.show(true);
      }
   },
   toggle: function(show) {
      if (typeof show === 'undefined') {
         show = !this.element.is('.active');
      }

      return show ? this.show() : this.hide();
   },
   show: function(immediate) {
      this.element.addClass('active');

      var me = this,
         $body = $('body');

      if (this.options.addBodyPadding && wpj.domUtils.getScrollbarWidth()) {
         this.element.add('body').css('padding-right', wpj.domUtils.getScrollbarWidth());
      }

      $body
         .on('mousedown.focus', function(e) {
            // pac-item => results in googlemaps input autocomplete
            if (me.element.has(e.target).length || !me.options.closeOnBgClick ||
               $(e.target).hasClass('pac-item') || $(e.target).hasClass('pac-item-query') || $(e.target).parents('.pac-item').length) {
               return;
            }

            me.hide();
         })
         .on('keydown.focus', function(e) {
            if (e.key !== 'Escape') {
               return true;
            }

            me.hide();
            return false;
         })
         .removeClass('focus-closed')
         .addClass('focus-opened');

      if (!immediate) {
         $body.addClass('focus-transition');
      }

      if (this.options.ajaxSubmit) {
         this.registerAjaxSubmit();
      }

      this._trigger( "show" );

      return false;
   },
   hide: function() {
      this.element.removeClass('active');
      $('body')
         .off('mousedown.focus')
         .off('keydown.focus')
         .removeClass('focus-opened')
         .addClass('focus-closed');

      if (this.options.addBodyPadding && wpj.domUtils.getScrollbarWidth()) {
         this.element.add('body').css('padding-right', 0);
      }

      this.element.trigger('focusClosed');

      if (this.options.ajaxSubmit) {
         this.element.off('submit', 'form');
      }

      if (this.options.removeOnClose) {
         this.element.remove();
      }

      this._trigger( "hide" );

      return false;
   },
   load: function () {
      if (!this.options.onDemandEndpoint) {
         return;
      }

      const me = this;
      if (this.options.focusCustomClass) {
         me.element.addClass(this.options.focusCustomClass);//('focus-delivery-widgets');
      }

      // Handle callback
      if (typeof this.options.onDemandEndpoint === "function") {
         this.options.onDemandEndpoint(me.element.find('.focus-content')[0]);
         return;
      }

      // Handle global function
      if (typeof window[this.options.onDemandEndpoint] === "function") {
         window[this.options.onDemandEndpoint](me.element.find('.focus-content')[0]);
         return;
      }

      // nacteni ondemand focusu
      fetch(this.options.onDemandEndpoint)
         .then((response) => response.text())
         .then((response) => {
            const focusClasses = [...$(response).prop('classList'), ...['active']];
            // replacnu obsah focusu naloadovanym obsahem
            me.element.html($(response).html());
            // nastavim focusu classy podle nacteneho focusu
            me.element.attr('class', focusClasses.join(' '))

            if (me.options.focusTriggerEventName) {
               $('body').trigger(me.options.focusTriggerEventName, me);
            }
         });
   },
   registerAjaxSubmit: function () {
      const me = this;
      this.element.on('submit', 'form', function (e) {
         e.preventDefault();

         const $this = $(e.target);
         const data = $this.serialize();
         const url = $this.attr('action');

         wpj.domUtils.reloadPartsFromUrl(url, me.element.find('[data-reload]'), data);
      });

      this.element.on('click', '[data-ondemand]', function(e) {
         const $this = $(e.target);
         const url = $this.attr('href');

         wpj.domUtils.reloadPartsFromUrl(url, me.element.find('[data-reload]'), undefined, () => {});
         return false;
      });
   }
});

$(document).on('click', '[data-wpj-focus]', function () {
   const endpoint  = $(this).data('wpj-focus');
   const ajaxSubmit  = $(this).data('wpj-focus-ajax');
   const removeOnClose = $(this).data('wpj-focus-remove-on-close');
   const focusCustomClass = $(this).data('wpj-focus-custom-class');
   const focusTriggerEventName = $(this).data('wpj-focus-trigger-event-name');
   if (endpoint) {
      wpj.focus.createDeduplicated(endpoint, !!ajaxSubmit, removeOnClose, focusCustomClass, focusTriggerEventName);
   }

   return false;
});

