(function() {
  'use strict';

  window.utils = window.utils || {};

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

  window.utils.aside = function(asideEl) {

    if (!asideEl) {
      throw new Error('asideEl not defined');
    }

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

    function initAsidenavSubmenus() {
      var asidenavLinksWithSubmenus = Array.from(asideEl.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';
        }

      };
    }

    initFavoritesButton();
    initAsidenavSubmenus();

    return {
      scope: asideEl,
      destroy: function() {},
    };
  };
})();
