/**
 * @file
 * Behaviors for the search widget in the admin toolbar.
 */

(function ($, Drupal) {

  'use strict';

  Drupal.behaviors.adminToolbarSearch = {

    // If extra links have been fetched.
    extraFetched: false,

    attach: function (context) {
      if (context != document) {
        return;
      }

      var getUrl = window.location;
      var baseUrl = getUrl.protocol + "//" + getUrl.host + "/";
      var $self = this;
      this.links = [];
      $('.toolbar-tray a[data-drupal-link-system-path]').each(function () {
        if (this.href != baseUrl) {
          var label = $self.getItemLabel(this);
          $self.links.push({
            'value': $(this).attr('href'),
            'label': label + ' ' + $(this).attr('href'),
            'labelRaw': label
          });
        }
      });

      $("#admin-toolbar-search-input").autocomplete({
        minLength: 2,
        source: function (request, response) {
          var data = $self.handleAutocomplete(request.term);
          if (!$self.extraFetched && drupalSettings.adminToolbarSearch.loadExtraLinks) {
            $.getJSON( "/admin/admin-toolbar-search", function( data ) {
              $(data).each(function() {
                var item = this;
                item.label = this.labelRaw + ' ' + this.value;
                $self.links.push(item);
              });

              $self.extraFetched = true;

              var results = $self.handleAutocomplete(request.term);
              response(results);
            });
          }
          else {
            response(data);
          }
        },
        open: function () {
          var zIndex = $('#toolbar-item-administration-search-tray')
            .css("z-index") + 1;
          $(this).autocomplete('widget').css('z-index', zIndex);

          return false;
        },
        select: function (event, ui) {
          if (ui.item.value) {
            location.href = ui.item.value;
            return false;
          }
        }
      }).data("ui-autocomplete")._renderItem = (function (ul, item) {
        return $("<li>")
          .append('<div>' + item.labelRaw + ' <span class="admin-toolbar-search-url">' + item.value + '</span></div>')
          .appendTo(ul);
      });

      // Focus on search field when tab is clicked, or enter is pressed.
      $(context).find('#toolbar-item-administration-search')
        .once('admin_toolbar_search')
        .each(function () {
          if (Drupal.behaviors.adminToolbarSearch.isSearchVisible()) {
            $('#admin-toolbar-search-input').focus();
          }
          $(this).on('click', function () {
            $self.focusOnSearchElement();
          });
        });

      // Initialize hotkey / keyboard shortcut.
      this.initHotkey();
    },
    focusOnSearchElement: function () {
      var waitforVisible = function () {
        if ($('#toolbar-item-administration-search-tray:visible').length) {
          $('#admin-toolbar-search-input').focus();
        }
        else {
          setTimeout(function () {
            waitforVisible();
          }, 1);
        }
      };
      waitforVisible();
    },
    getItemLabel: function (item) {
      var breadcrumbs = [];
      $(item).parents().each(function () {
        if ($(this).hasClass('menu-item')) {
          var $link = $(this).find('a:first');
          if ($link.length && !$link.hasClass('admin-toolbar-search-ignore')) {
            breadcrumbs.unshift($link.text());
          }
        }
      });
      return breadcrumbs.join(' > ');
    },
    handleAutocomplete: function (term) {
      var $self = this;
      var keywords = term.split(" "); // Split search terms into list.

      var suggestions = [];
      $self.links.forEach(function (element) {
        var label = element.label.toLowerCase();

        // Add exact matches.
        if (label.indexOf(term.toLowerCase()) >= 0) {
          suggestions.push(element);
        }
        else {
          // Add suggestions where it matches all search terms.
          var matchCount = 0;
          keywords.forEach(function (keyword) {
            if (label.indexOf(keyword.toLowerCase()) >= 0) {
              matchCount++;
            }
          });
          if (matchCount == keywords.length) {
            suggestions.push(element);
          }
        }
      });
      return suggestions;
    },
    /**
     * Whether the search is visible or not.
     *
     * @returns {boolean}
     *   True if visible, false otherwise.
     */
    isSearchVisible: function () {
      return $('#toolbar-item-administration-search-tray').is(':visible');
    },
    /**
     * Toggles the toolbar search tray.
     */
    toggleSearch: function () {
      $('#toolbar-item-administration-search').trigger('click');
    },
    /**
     * Binds a keyboard shortcut to toggle the search.
     */
    initHotkey: function () {
      $(document)
        .once('admin_toolbar_search')
        .keydown(function (event) {
          // Show the form with alt + S.
          if (!Drupal.behaviors.adminToolbarSearch.isSearchVisible()) {
            // 83 = s.
            if (event.altKey === true && event.keyCode === 83) {
              Drupal.behaviors.adminToolbarSearch.toggleSearch();
              event.preventDefault();
            }
          }
          // Hide the search with alt + S or ESC.
          else {
            // 83 = s.
            if (
              (event.altKey === true && event.keyCode === 83) ||
              event.key === 'Escape'
            ) {
              Drupal.behaviors.adminToolbarSearch.toggleSearch();
              event.preventDefault();
            }
          }
        });
    }
  };

})(jQuery, Drupal);
