'use strict';

var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');

var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

var _createClass2 = require('babel-runtime/helpers/createClass');

var _createClass3 = _interopRequireDefault(_createClass2);

var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray');

var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2);

var _stringUtils = require('../utils/string-utils');

var _fullThrottle = require('../utils/full-throttle');

var _fullThrottle2 = _interopRequireDefault(_fullThrottle);

var _constants = require('../utils/constants');

var _domUtils = require('../utils/dom-utils');

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

/**
 * @license
 * Copyright 2016 Leif Olsen. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * This code is built with Google Material Design Lite,
 * which is Licensed under the Apache License, Version 2.0
 */

/**
 * A menu button is a button that opens a menu. It is often styled as a
 * typical push button with a downward pointing arrow or triangle to hint
 * that activating the button will display a menu.
 */
var JS_MENU_BUTTON = 'mdlext-js-menu-button';
var MENU_BUTTON_MENU = 'mdlext-menu';
var MENU_BUTTON_MENU_ITEM = 'mdlext-menu__item';
var MENU_BUTTON_MENU_ITEM_SEPARATOR = 'mdlext-menu__item-separator';
//const MDL_LAYOUT_CONTENT = 'mdl-layout__content';

/**
 * Creates the menu controlled by the menu button
 * @param element
 * @return {{element: Element, selected: Element, open: (function(*=)), removeListeners: (function()), downgrade: (function())}}
 */

var menuFactory = function menuFactory(element) {

  var ariaControls = null;
  var parentNode = null;

  var removeAllSelected = function removeAllSelected() {
    [].concat((0, _toConsumableArray3.default)(element.querySelectorAll('.' + MENU_BUTTON_MENU_ITEM + '[aria-selected="true"]'))).forEach(function (selectedItem) {
      return selectedItem.removeAttribute('aria-selected');
    });
  };

  var setSelected = function setSelected(item) {
    var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;

    if (force || item && !item.hasAttribute('aria-selected')) {
      removeAllSelected();
      if (item) {
        item.setAttribute('aria-selected', 'true');
      }
    }
  };

  var getSelected = function getSelected() {
    return element.querySelector('.' + MENU_BUTTON_MENU_ITEM + '[aria-selected="true"]');
  };

  var isDisabled = function isDisabled(item) {
    return item && item.hasAttribute('disabled');
  };

  var isSeparator = function isSeparator(item) {
    return item && item.classList.contains(MENU_BUTTON_MENU_ITEM_SEPARATOR);
  };

  var focus = function focus(item) {
    if (item) {
      item = item.closest('.' + MENU_BUTTON_MENU_ITEM);
    }
    if (item) {
      item.focus();
    }
  };

  var nextItem = function nextItem(current) {
    var n = current.nextElementSibling;
    if (!n) {
      n = element.firstElementChild;
    }
    if (!isDisabled(n) && !isSeparator(n)) {
      focus(n);
    } else {
      var i = element.children.length;
      while (n && i-- > 0) {
        if (isDisabled(n) || isSeparator(n)) {
          n = n.nextElementSibling;
          if (!n) {
            n = element.firstElementChild;
          }
        } else {
          focus(n);
          break;
        }
      }
    }
  };

  var previousItem = function previousItem(current) {
    var p = current.previousElementSibling;
    if (!p) {
      p = element.lastElementChild;
    }
    if (!isDisabled(p) && !isSeparator(p)) {
      focus(p);
    } else {
      var i = element.children.length;
      while (p && i-- > 0) {
        if (isDisabled(p) || isSeparator(p)) {
          p = p.previousElementSibling;
          if (!p) {
            p = element.lastElementChild;
          }
        } else {
          focus(p);
          break;
        }
      }
    }
  };

  var firstItem = function firstItem() {
    var item = element.firstElementChild;
    if (isDisabled(item) || isSeparator(item)) {
      nextItem(item);
    } else {
      focus(item);
    }
  };

  var lastItem = function lastItem() {
    var item = element.lastElementChild;
    if (isDisabled(item) || isSeparator(item)) {
      previousItem(item);
    } else {
      focus(item);
    }
  };

  var selectItem = function selectItem(item) {
    if (item && !isDisabled(item) && !isSeparator(item)) {
      setSelected(item);
      close(true, item);
    }
  };

  var keyDownHandler = function keyDownHandler(event) {

    var item = event.target.closest('.' + MENU_BUTTON_MENU_ITEM);

    switch (event.keyCode) {
      case _constants.VK_ARROW_UP:
      case _constants.VK_ARROW_LEFT:
        if (item) {
          previousItem(item);
        } else {
          firstItem();
        }
        break;

      case _constants.VK_ARROW_DOWN:
      case _constants.VK_ARROW_RIGHT:
        if (item) {
          nextItem(item);
        } else {
          lastItem();
        }
        break;

      case _constants.VK_HOME:
        firstItem();
        break;

      case _constants.VK_END:
        lastItem();
        break;

      case _constants.VK_SPACE:
      case _constants.VK_ENTER:
        selectItem(item);
        break;

      case _constants.VK_ESC:
        close(true);
        break;

      case _constants.VK_TAB:
        // We do not have a "natural" tab order from menu, so the best we can do is to set focus back to the button
        close(true);
        break;

      default:
        return;
    }
    event.preventDefault();
  };

  var blurHandler = function blurHandler(event) {

    // See: https://github.com/facebook/react/issues/2011
    var t = event.relatedTarget || event.explicitOriginalTarget || // FF
    document.activeElement; // IE11

    //console.log('***** blur, target, relatedTarget', event.target, t);

    try {
      if (t) {
        if (t.closest('.' + MENU_BUTTON_MENU) !== element && shouldClose(t)) {
          close();
        }
      } else {
        close();
      }
    } catch (err) {
      // FF throws error: "TypeError: n.closest is not a function" if related target is a text node
      close();
    }
  };

  var clickHandler = function clickHandler(event) {
    //console.log('***** click, target', event.target);

    event.preventDefault();
    var t = event.target;
    if (t && t.closest('.' + MENU_BUTTON_MENU) === element) {
      var item = t.closest('.' + MENU_BUTTON_MENU_ITEM);
      if (item) {
        selectItem(item);
      }
    } else {
      if (shouldClose(t)) {
        close();
      }
    }
  };

  var touchStartHandler = function touchStartHandler(event) {
    //console.log('***** touchStart, target', event.target);

    var t = event.target;
    if (!(t && t.closest('.' + MENU_BUTTON_MENU) === element)) {
      if (event.type === 'touchstart') {
        event.preventDefault();
      }
      close();
    }
  };

  var addListeners = function addListeners() {
    element.addEventListener('keydown', keyDownHandler, false);
    element.addEventListener('blur', blurHandler, true);
    element.addEventListener('click', clickHandler, true);
    document.documentElement.addEventListener('touchstart', touchStartHandler, true);
  };

  var _removeListeners = function _removeListeners() {
    element.removeEventListener('keydown', keyDownHandler, false);
    element.removeEventListener('blur', blurHandler, true);
    element.removeEventListener('click', clickHandler, true);
    document.documentElement.removeEventListener('touchstart', touchStartHandler, true);
  };

  var _open = function _open(controlElement) {
    var position = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'first';


    ariaControls = controlElement.closest('.' + JS_MENU_BUTTON);

    element.style['min-width'] = Math.max(124, controlElement.getBoundingClientRect().width) + 'px';
    element.removeAttribute('hidden');
    (0, _domUtils.tether)(controlElement, element);

    var item = void 0;
    switch (position.toLowerCase()) {
      case 'first':
        firstItem();
        break;

      case 'last':
        lastItem();
        break;

      case 'selected':
        item = getSelected();
        if (item && !item.hasAttribute('disabled')) {
          focus(item);
        } else {
          firstItem();
        }
        break;
    }

    addListeners();
  };

  var shouldClose = function shouldClose(target) {
    //console.log('***** shouldClose');

    var result = false;
    var btn = target && target.closest('.' + JS_MENU_BUTTON) || null;
    if (!btn) {
      result = true;
    } else if (btn.getAttribute('aria-controls') === element.id) {
      if (btn !== ariaControls) {
        result = true;
      }
    } else {
      result = true;
    }
    return result;
  };

  var close = function close() {
    var forceFocus = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
    var item = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;

    _removeListeners();

    element.dispatchEvent(new CustomEvent('_closemenu', {
      bubbles: true,
      cancelable: true,
      detail: { forceFocus: forceFocus, item: item }
    }));
  };

  var addWaiAria = function addWaiAria() {
    if (!element.hasAttribute('id')) {
      // Generate a random id
      element.id = 'menu-button-' + (0, _stringUtils.randomString)();
    }
    element.setAttribute('tabindex', '-1');
    element.setAttribute('role', 'menu');
    element.setAttribute('hidden', '');

    [].concat((0, _toConsumableArray3.default)(element.querySelectorAll('.' + MENU_BUTTON_MENU_ITEM))).forEach(function (menuitem) {
      menuitem.setAttribute('tabindex', '-1');
      menuitem.setAttribute('role', 'menuitem');
    });

    [].concat((0, _toConsumableArray3.default)(element.querySelectorAll('.' + MENU_BUTTON_MENU_ITEM_SEPARATOR))).forEach(function (menuitem) {
      menuitem.setAttribute('role', 'separator');
    });
  };

  var init = function init() {
    addWaiAria();
    parentNode = element.parentNode;
    element.classList.add('is-upgraded');
  };

  var _downgrade = function _downgrade() {
    _removeListeners();
    if (element.parentNode !== parentNode) {
      parentNode.appendChild(element);
    }
    element.classList.remove('is-upgraded');
  };

  init();

  return {
    /**
     * Get the menu element
     * @returns {Element} the menu element
     */
    get element() {
      return element;
    },

    /**
     * Set selected menu item
     * @param item
     */
    set selected(item) {
      setSelected(item, true);
    },

    /**
     * Open menu
     * @param {Element} controlElement the element where the menu should be aligned to
     * @param {String} position menuElement item to receive focus after menu element is opened
     */
    open: function open(controlElement) {
      var position = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'first';
      return _open(controlElement, position);
    },

    /**
     * Remove event listeners.
     */
    removeListeners: function removeListeners() {
      return _removeListeners();
    },

    /**
     * Downgrade menu
     */
    downgrade: function downgrade() {
      return _downgrade();
    }
  };
};

/**
 * The menubutton component
 */

var MenuButton = function () {
  function MenuButton(element) {
    var _this = this;

    (0, _classCallCheck3.default)(this, MenuButton);

    this.keyDownHandler = function (event) {
      if (!_this.isDisabled()) {
        switch (event.keyCode) {
          case _constants.VK_ARROW_UP:
            _this.openMenu('last');
            break;

          case _constants.VK_ARROW_DOWN:
            _this.openMenu();
            break;

          case _constants.VK_SPACE:
          case _constants.VK_ENTER:
            _this.openMenu('selected');
            break;

          case _constants.VK_ESC:
            _this.closeMenu();
            break;

          case _constants.VK_TAB:
            _this.closeMenu();
            return;

          default:
            return;
        }
      }
      //event.stopPropagation();
      event.preventDefault();
    };

    this.clickHandler = function () {
      if (!_this.isDisabled()) {
        if (_this.element.getAttribute('aria-expanded').toLowerCase() === 'true') {
          _this.closeMenu(true);
        } else {
          _this.openMenu('selected');
        }
      }
    };

    this.recalcMenuPosition = (0, _fullThrottle2.default)(function () {
      var c = _this.focusElement.getBoundingClientRect();
      var dx = _this.focusElementLastScrollPosition.left - c.left;
      var dy = _this.focusElementLastScrollPosition.top - c.top;
      var left = (parseFloat(_this.menu.element.style.left) || 0) - dx;
      var top = (parseFloat(_this.menu.element.style.top) || 0) - dy;

      _this.menu.element.style.left = left + 'px';
      _this.menu.element.style.top = top + 'px';
      _this.focusElementLastScrollPosition = c;
    });

    this.positionChangeHandler = function () {
      _this.recalcMenuPosition(_this);
    };

    this.closeMenuHandler = function (event) {
      if (event && event.detail) {
        if (event.detail.item && event.detail.item !== _this.selectedItem) {
          _this.selectedItem = event.detail.item;
          _this.dispatchMenuSelect();
        }
        _this.closeMenu(event.detail.forceFocus);
      }
    };

    this.element = element;
    this.focusElement = undefined;
    this.focusElementLastScrollPosition = undefined;
    this.scrollElements = [];
    this.menu = undefined;
    this.selectedItem = null;
    this.init();
  }

  /**
   * Re-position menu if content is scrolled, window is resized or orientation change
   * @see https://javascriptweblog.wordpress.com/2015/11/02/of-classes-and-arrow-functions-a-cautionary-tale/
   */


  (0, _createClass3.default)(MenuButton, [{
    key: 'dispatchMenuSelect',
    value: function dispatchMenuSelect() {
      this.element.dispatchEvent(new CustomEvent('menuselect', {
        bubbles: true,
        cancelable: true,
        detail: { source: this.selectedItem }
      }));
    }
  }, {
    key: 'isDisabled',
    value: function isDisabled() {
      return this.element.hasAttribute('disabled');
    }
  }, {
    key: 'removeListeners',
    value: function removeListeners() {
      this.element.removeEventListener('keydown', this.keyDownHandler);
      this.element.removeEventListener('click', this.clickHandler);
    }
  }, {
    key: 'openMenu',
    value: function openMenu() {
      var _this2 = this;

      var position = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'first';


      if (!this.isDisabled() && this.menu) {

        // Close the menu if button position change
        this.scrollElements = (0, _domUtils.getScrollParents)(this.element);
        this.scrollElements.forEach(function (el) {
          return el.addEventListener('scroll', _this2.positionChangeHandler);
        });

        window.addEventListener('resize', this.positionChangeHandler);
        window.addEventListener('orientationchange', this.positionChangeHandler);
        this.menu.element.addEventListener('_closemenu', this.closeMenuHandler);

        this.menu.selected = this.selectedItem;
        this.menu.open(this.focusElement, position);
        this.element.setAttribute('aria-expanded', 'true');

        this.focusElementLastScrollPosition = this.focusElement.getBoundingClientRect();
      }
    }
  }, {
    key: 'closeMenu',
    value: function closeMenu() {
      var _this3 = this;

      var forceFocus = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;

      if (this.menu) {
        this.menu.removeListeners();
        this.scrollElements.forEach(function (el) {
          return el.removeEventListener('scroll', _this3.positionChangeHandler);
        });
        window.removeEventListener('resize', this.positionChangeHandler);
        window.removeEventListener('orientationchange', this.positionChangeHandler);
        this.menu.element.removeEventListener('_closemenu', this.closeMenuHandler);

        if (forceFocus) {
          this.focus();
        }
        this.element.setAttribute('aria-expanded', 'false');
        this.menu.element.setAttribute('hidden', '');
      }
    }
  }, {
    key: 'focus',
    value: function focus() {
      if (!this.isDisabled()) {
        this.focusElement.focus();
      }
    }
  }, {
    key: 'init',
    value: function init() {
      var _this4 = this;

      var addListeners = function addListeners() {
        _this4.element.addEventListener('keydown', _this4.keyDownHandler);
        _this4.element.addEventListener('click', _this4.clickHandler);
      };

      var addWaiAria = function addWaiAria() {
        _this4.element.setAttribute('role', 'button');
        _this4.element.setAttribute('aria-expanded', 'false');
        _this4.element.setAttribute('aria-haspopup', 'true');
      };

      var addFocusElement = function addFocusElement() {
        _this4.focusElement = _this4.element.querySelector('input[type="text"]');
        if (!_this4.focusElement) {
          _this4.focusElement = _this4.element;

          if (!(_this4.focusElement.tagName.toLowerCase() === 'button' || _this4.focusElement.tagName.toLowerCase() === 'input')) {
            if (!_this4.focusElement.hasAttribute('tabindex')) {
              _this4.focusElement.setAttribute('tabindex', '0');
            }
          }
        }
      };

      var moveElementToDocumentBody = function moveElementToDocumentBody(element) {
        // To position an element on top of all other z-indexed elements, the element should be moved to document.body
        //       See: https://philipwalton.com/articles/what-no-one-told-you-about-z-index/

        if (element.parentNode !== document.body) {
          return document.body.appendChild(element);
        }
        return element;
      };

      var findMenuElement = function findMenuElement() {
        var menuElement = void 0;
        var menuElementId = _this4.element.getAttribute('aria-controls');
        if (menuElementId !== null) {
          menuElement = document.querySelector('#' + menuElementId);
        } else {
          menuElement = _this4.element.parentNode.querySelector('.' + MENU_BUTTON_MENU);
        }
        return menuElement;
      };

      var addMenu = function addMenu() {
        var menuElement = findMenuElement();
        if (menuElement) {
          if (menuElement.componentInstance) {
            _this4.menu = menuElement.componentInstance;
          } else {
            _this4.menu = menuFactory(menuElement);
            menuElement.componentInstance = _this4.menu;
            moveElementToDocumentBody(menuElement);
          }
          _this4.element.setAttribute('aria-controls', _this4.menu.element.id);
        }
      };

      addFocusElement();
      addWaiAria();
      addMenu();
      this.removeListeners();
      addListeners();
    }
  }, {
    key: 'downgrade',
    value: function downgrade() {
      var _this5 = this;

      if (this.menu) {
        // Do not downgrade menu if there are other buttons sharing this menu
        var related = [].concat((0, _toConsumableArray3.default)(document.querySelectorAll('.' + JS_MENU_BUTTON + '[aria-controls="' + this.element.getAttribute('aria-controls') + '"]')));
        if (related.filter(function (c) {
          return c !== _this5.element && c.getAttribute('data-upgraded').indexOf('MaterialExtMenuButton') >= 0;
        }).length === 0) {
          this.menu.downgrade();
        }
      }
      this.removeListeners();
    }
  }]);
  return MenuButton;
}();

(function () {
  'use strict';

  /**
   * https://github.com/google/material-design-lite/issues/4205
   * @constructor
   * @param {Element} element The element that will be upgraded.
   */

  var MaterialExtMenuButton = function MaterialExtMenuButton(element) {
    this.element_ = element;
    this.menuButton_ = null;

    // Initialize instance.
    this.init();
  };
  window['MaterialExtMenuButton'] = MaterialExtMenuButton;

  // Public methods.

  /**
   * Get the menu element controlled by this button, null if no menu is controlled by this button
   * @public
   */
  MaterialExtMenuButton.prototype.getMenuElement = function () {
    return this.menuButton_.menu ? this.menuButton_.menu.element : null;
  };
  MaterialExtMenuButton.prototype['getMenuElement'] = MaterialExtMenuButton.prototype.getMenuElement;

  /**
   * Open menu
   * @public
   * @param {String} position one of "first", "last" or "selected"
   */
  MaterialExtMenuButton.prototype.openMenu = function (position) {
    this.menuButton_.openMenu(position);
  };
  MaterialExtMenuButton.prototype['openMenu'] = MaterialExtMenuButton.prototype.openMenu;

  /**
   * Close menu
   * @public
   */
  MaterialExtMenuButton.prototype.closeMenu = function () {
    this.menuButton_.closeMenu(true);
  };
  MaterialExtMenuButton.prototype['closeMenu'] = MaterialExtMenuButton.prototype.closeMenu;

  /**
   * Get selected menu item
   * @public
   * @returns {Element} The selected menu item or null if no item selected
   */
  MaterialExtMenuButton.prototype.getSelectedMenuItem = function () {
    return this.menuButton_.selectedItem;
  };
  MaterialExtMenuButton.prototype['getSelectedMenuItem'] = MaterialExtMenuButton.prototype.getSelectedMenuItem;

  /**
   * Set (default) selected menu item
   * @param {Element} item
   */
  MaterialExtMenuButton.prototype.setSelectedMenuItem = function (item) {
    this.menuButton_.selectedItem = item;
  };
  MaterialExtMenuButton.prototype['setSelectedMenuItem'] = MaterialExtMenuButton.prototype.setSelectedMenuItem;

  /**
   * Initialize component
   */
  MaterialExtMenuButton.prototype.init = function () {
    if (this.element_) {
      this.menuButton_ = new MenuButton(this.element_);
      this.element_.addEventListener('mdl-componentdowngraded', this.mdlDowngrade_.bind(this));
      this.element_.classList.add(_constants.IS_UPGRADED);
    }
  };

  /**
   * Downgrade component
   * E.g remove listeners and clean up resources
   */
  MaterialExtMenuButton.prototype.mdlDowngrade_ = function () {
    this.menuButton_.downgrade();
  };

  // The component registers itself. It can assume componentHandler is available
  // in the global scope.
  /* eslint no-undef: 0 */
  componentHandler.register({
    constructor: MaterialExtMenuButton,
    classAsString: 'MaterialExtMenuButton',
    cssClass: JS_MENU_BUTTON,
    widget: true
  });
})();