(function() {
  'use strict';

  /**
   *
   * Asidenav Utility
   *  Correctly positions hovered asidenav submenus and handles the favorites button on mobile
   *
   * Attribute: uw-asidenav
   *
   * Example usage:
   *  <div uw-asidenav>
   *    <div .asidenav>
   *      <div .asidenav__box>
   *        <ul .asidenav__list.list--iconless>
   *          <li .asidenav__list-item>
   *            <a .asidenav__link-wrapper href="#">
   *              <div .asidenav__link-shorthand>EIP
   *              <div .asidenav__link-label>Einführung in die Programmierung
   *            <div .asidenav__nested-list-wrapper>
   *              <ul .asidenav__nested-list.list--iconless>
   *                Übungsblätter
   *                ...
   *
   */

  var ASIDENAV_UTIL_NAME = 'asidenav';
  var ASIDENAV_UTIL_SELECTOR = '[uw-asidenav]';

  var FAVORITES_BTN_CLASS = 'navbar__list-item--favorite';
  var FAVORITES_BTN_ACTIVE_CLASS = 'navbar__list-item--active';
  var ASIDENAV_INITIALIZED_CLASS = 'asidenav--initialized';
  var ASIDENAV_EXPANDED_CLASS = 'main__aside--expanded';
  var ASIDENAV_LIST_ITEM_CLASS = 'asidenav__list-item';
  var ASIDENAV_SUBMENU_CLASS = 'asidenav__nested-list-wrapper';

  var asidenavUtil = function(element) {

    function init() {
      if (!element) {
        throw new Error('Asidenav utility cannot be setup without an element!');
      }

      if (element.classList.contains(ASIDENAV_INITIALIZED_CLASS)) {
        return false;
      }

      initFavoritesButton();
      initAsidenavSubmenus();

      // mark initialized
      element.classList.add(ASIDENAV_INITIALIZED_CLASS);

      return {
        name: ASIDENAV_UTIL_NAME,
        element: element,
        destroy: function() {},
      };
    }

    function initFavoritesButton() {
      var favoritesBtn = document.querySelector('.' + FAVORITES_BTN_CLASS);
      favoritesBtn.addEventListener('click', function(event) {
        favoritesBtn.classList.toggle(FAVORITES_BTN_ACTIVE_CLASS);
        element.classList.toggle(ASIDENAV_EXPANDED_CLASS);
        event.preventDefault();
      }, true);
    }

    function initAsidenavSubmenus() {
      var asidenavLinksWithSubmenus = Array.from(element.querySelectorAll('.' + ASIDENAV_LIST_ITEM_CLASS))
        .map(function(listItem) {
          var submenu = listItem.querySelector('.' + ASIDENAV_SUBMENU_CLASS);
          return { listItem, submenu };
        }).filter(function(union) {
          return union.submenu !== null;
        });

      asidenavLinksWithSubmenus.forEach(function(union) {
        union.listItem.addEventListener('mouseover', createMouseoverHandler(union));
      });
    }

    function createMouseoverHandler(union) {
      return function mouseoverHanlder(event) {
        var rectListItem = union.listItem.getBoundingClientRect();
        var rectSubMenu = union.submenu.getBoundingClientRect();

        union.submenu.style.left = (rectListItem.left + rectListItem.width) + 'px';
        if (window.innerHeight - rectListItem.top < rectSubMenu.height) {
          union.submenu.style.top = (rectListItem.top + rectListItem.height - rectSubMenu.height) + 'px';
        } else {
          union.submenu.style.top = rectListItem.top + 'px';
        }

      };
    }

    return init();
  };

  if (UtilRegistry) {
    UtilRegistry.register({
      name: ASIDENAV_UTIL_NAME,
      selector: ASIDENAV_UTIL_SELECTOR,
      setup: asidenavUtil,
    });
  }
})();
