'use strict';

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

var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2);

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

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

(function () {
  'use strict';

  var ACCORDION = 'mdlext-accordion';
  var ACCORDION_VERTICAL = 'mdlext-accordion--vertical';
  var ACCORDION_HORIZONTAL = 'mdlext-accordion--horizontal';
  var PANEL = 'mdlext-accordion__panel';
  var PANEL_ROLE = 'presentation';
  var TAB = 'mdlext-accordion__tab';
  var TAB_CAPTION = 'mdlext-accordion__tab__caption';
  var TAB_ROLE = 'tab';
  var TABPANEL = 'mdlext-accordion__tabpanel';
  var TABPANEL_ROLE = 'tabpanel';
  var RIPPLE_EFFECT = 'mdlext-js-ripple-effect';
  var RIPPLE = 'mdlext-accordion__tab--ripple';
  var ANIMATION_EFFECT = 'mdlext-js-animation-effect';
  var ANIMATION = 'mdlext-accordion__tabpanel--animation';

  /**
   * @constructor
   * @param {Element} element The element that will be upgraded.
   */
  var MaterialExtAccordion = function MaterialExtAccordion(element) {

    // Stores the Accordion HTML element.
    this.element_ = element;

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

  // Helpers
  var accordionPanelElements = function accordionPanelElements(element) {
    if (!element) {
      return {
        panel: null,
        tab: null,
        tabpanel: null
      };
    } else if (element.classList.contains(PANEL)) {
      return {
        panel: element,
        tab: element.querySelector('.' + TAB),
        tabpanel: element.querySelector('.' + TABPANEL)
      };
    } else {
      return {
        panel: element.parentNode,
        tab: element.parentNode.querySelector('.' + TAB),
        tabpanel: element.parentNode.querySelector('.' + TABPANEL)
      };
    }
  };

  // Private methods.

  /**
   * Handles custom command event, 'open', 'close', 'toggle' or upgrade
   * @param event. A custom event
   * @private
   */
  MaterialExtAccordion.prototype.commandHandler_ = function (event) {
    event.preventDefault();
    event.stopPropagation();

    if (event && event.detail) {
      this.command(event.detail);
    }
  };

  /**
   * Dispatch toggle event
   * @param {string} state
   * @param {Element} tab
   * @param {Element} tabpanel
   * @private
   */
  MaterialExtAccordion.prototype.dispatchToggleEvent_ = function (state, tab, tabpanel) {
    var ce = new CustomEvent('toggle', {
      bubbles: true,
      cancelable: true,
      detail: { state: state, tab: tab, tabpanel: tabpanel }
    });
    this.element_.dispatchEvent(ce);
  };

  /**
   * Open tab
   * @param {Element} panel
   * @param {Element} tab
   * @param {Element} tabpanel
   * @private
   */
  MaterialExtAccordion.prototype.openTab_ = function (panel, tab, tabpanel) {
    panel.classList.add(_constants.IS_EXPANDED);
    tab.setAttribute(_constants.ARIA_EXPANDED, 'true');
    tabpanel.removeAttribute('hidden');
    tabpanel.setAttribute(_constants.ARIA_HIDDEN, 'false');
    this.dispatchToggleEvent_('open', tab, tabpanel);
  };

  /**
   * Close tab
   * @param {Element} panel
   * @param {Element} tab
   * @param {Element} tabpanel
   * @private
   */
  MaterialExtAccordion.prototype.closeTab_ = function (panel, tab, tabpanel) {
    panel.classList.remove(_constants.IS_EXPANDED);
    tab.setAttribute(_constants.ARIA_EXPANDED, 'false');
    tabpanel.setAttribute('hidden', '');
    tabpanel.setAttribute(_constants.ARIA_HIDDEN, 'true');
    this.dispatchToggleEvent_('close', tab, tabpanel);
  };

  /**
   * Toggle tab
   * @param {Element} panel
   * @param {Element} tab
   * @param {Element} tabpanel
   * @private
   */
  MaterialExtAccordion.prototype.toggleTab_ = function (panel, tab, tabpanel) {
    if (!(this.element_.hasAttribute('disabled') || tab.hasAttribute('disabled'))) {
      if (tab.getAttribute(_constants.ARIA_EXPANDED).toLowerCase() === 'true') {
        this.closeTab_(panel, tab, tabpanel);
      } else {
        if (this.element_.getAttribute(_constants.ARIA_MULTISELECTABLE).toLowerCase() !== 'true') {
          this.closeTabs_();
        }
        this.openTab_(panel, tab, tabpanel);
      }
    }
  };

  /**
   * Open tabs
   * @private
   */
  MaterialExtAccordion.prototype.openTabs_ = function () {
    var _this = this;

    if (this.element_.getAttribute(_constants.ARIA_MULTISELECTABLE).toLowerCase() === 'true') {
      [].concat((0, _toConsumableArray3.default)(this.element_.querySelectorAll('.' + ACCORDION + ' > .' + PANEL))).filter(function (panel) {
        return !panel.classList.contains(_constants.IS_EXPANDED);
      }).forEach(function (closedItem) {
        var tab = closedItem.querySelector('.' + TAB);
        if (!tab.hasAttribute('disabled')) {
          _this.openTab_(closedItem, tab, closedItem.querySelector('.' + TABPANEL));
        }
      });
    }
  };

  /**
   * Close tabs
   * @private
   */
  MaterialExtAccordion.prototype.closeTabs_ = function () {
    var _this2 = this;

    [].concat((0, _toConsumableArray3.default)(this.element_.querySelectorAll('.' + ACCORDION + ' > .' + PANEL + '.' + _constants.IS_EXPANDED))).forEach(function (panel) {
      var tab = panel.querySelector('.' + TAB);
      if (!tab.hasAttribute('disabled')) {
        _this2.closeTab_(panel, tab, panel.querySelector('.' + TABPANEL));
      }
    });
  };

  // Public methods.

  /**
   * Upgrade an individual accordion tab
   * @public
   * @param {Element} tabElement The HTML element for the accordion panel.
   */
  MaterialExtAccordion.prototype.upgradeTab = function (tabElement) {
    var _this3 = this;

    var _accordionPanelElemen = accordionPanelElements(tabElement),
        panel = _accordionPanelElemen.panel,
        tab = _accordionPanelElemen.tab,
        tabpanel = _accordionPanelElemen.tabpanel;

    var disableTab = function disableTab() {
      panel.classList.remove(_constants.IS_EXPANDED);
      tab.setAttribute('tabindex', '-1');
      tab.setAttribute(_constants.ARIA_EXPANDED, 'false');
      tabpanel.setAttribute('hidden', '');
      tabpanel.setAttribute(_constants.ARIA_HIDDEN, 'true');
    };

    var enableTab = function enableTab() {
      if (!tab.hasAttribute(_constants.ARIA_EXPANDED)) {
        tab.setAttribute(_constants.ARIA_EXPANDED, 'false');
      }

      tab.setAttribute('tabindex', '0');

      if (tab.getAttribute(_constants.ARIA_EXPANDED).toLowerCase() === 'true') {
        panel.classList.add(_constants.IS_EXPANDED);
        tabpanel.removeAttribute('hidden');
        tabpanel.setAttribute(_constants.ARIA_HIDDEN, 'false');
      } else {
        panel.classList.remove(_constants.IS_EXPANDED);
        tabpanel.setAttribute('hidden', '');
        tabpanel.setAttribute(_constants.ARIA_HIDDEN, 'true');
      }
    };

    // In horizontal layout, caption must have a max-width defined to prevent pushing elements to the right of the caption out of view.
    // In JsDom, offsetWidth and offsetHeight properties do not work, so this function is not testable.
    /* istanbul ignore next */
    var calcMaxTabCaptionWidth = function calcMaxTabCaptionWidth() {

      var tabCaption = tab.querySelector('.' + TAB_CAPTION);
      if (tabCaption !== null) {
        var w = [].concat((0, _toConsumableArray3.default)(tab.children)).filter(function (el) {
          return el.classList && !el.classList.contains(TAB_CAPTION);
        }).reduce(function (v, el) {
          return v + el.offsetWidth;
        }, 0);

        var maxWidth = tab.clientHeight - w;
        if (maxWidth > 0) {
          tabCaption.style['max-width'] = maxWidth + 'px';
        }
      }
    };

    var selectTab = function selectTab() {
      if (!tab.hasAttribute(_constants.ARIA_SELECTED)) {
        [].concat((0, _toConsumableArray3.default)(_this3.element_.querySelectorAll('.' + TAB + '[aria-selected="true"]'))).forEach(function (selectedTab) {
          return selectedTab.removeAttribute(_constants.ARIA_SELECTED);
        });
        tab.setAttribute(_constants.ARIA_SELECTED, 'true');
      }
    };

    var tabClickHandler = function tabClickHandler() {
      _this3.toggleTab_(panel, tab, tabpanel);
      selectTab();
    };

    var tabFocusHandler = function tabFocusHandler() {
      selectTab();
    };

    var tabpanelClickHandler = function tabpanelClickHandler() {
      selectTab();
    };

    var tabpanelFocusHandler = function tabpanelFocusHandler() {
      selectTab();
    };

    var tabKeydownHandler = function tabKeydownHandler(e) {

      if (_this3.element_.hasAttribute('disabled')) {
        return;
      }

      if (e.keyCode === _constants.VK_END || e.keyCode === _constants.VK_HOME || e.keyCode === _constants.VK_ARROW_UP || e.keyCode === _constants.VK_ARROW_LEFT || e.keyCode === _constants.VK_ARROW_DOWN || e.keyCode === _constants.VK_ARROW_RIGHT) {

        var nextTab = null;
        var keyCode = e.keyCode;

        if (keyCode === _constants.VK_HOME) {
          nextTab = _this3.element_.querySelector('.' + PANEL + ':first-child > .' + TAB);
          if (nextTab && nextTab.hasAttribute('disabled')) {
            nextTab = null;
            keyCode = _constants.VK_ARROW_DOWN;
          }
        } else if (keyCode === _constants.VK_END) {
          nextTab = _this3.element_.querySelector('.' + PANEL + ':last-child > .' + TAB);
          if (nextTab && nextTab.hasAttribute('disabled')) {
            nextTab = null;
            keyCode = _constants.VK_ARROW_UP;
          }
        }

        if (!nextTab) {
          var nextPanel = panel;

          do {
            if (keyCode === _constants.VK_ARROW_UP || keyCode === _constants.VK_ARROW_LEFT) {
              nextPanel = nextPanel.previousElementSibling;
              if (!nextPanel) {
                nextPanel = _this3.element_.querySelector('.' + PANEL + ':last-child');
              }
              if (nextPanel) {
                nextTab = nextPanel.querySelector('.' + PANEL + ' > .' + TAB);
              }
            } else if (keyCode === _constants.VK_ARROW_DOWN || keyCode === _constants.VK_ARROW_RIGHT) {
              nextPanel = nextPanel.nextElementSibling;
              if (!nextPanel) {
                nextPanel = _this3.element_.querySelector('.' + PANEL + ':first-child');
              }
              if (nextPanel) {
                nextTab = nextPanel.querySelector('.' + PANEL + ' > .' + TAB);
              }
            }

            if (nextTab && nextTab.hasAttribute('disabled')) {
              nextTab = null;
            } else {
              break;
            }
          } while (nextPanel !== panel);
        }

        if (nextTab) {
          e.preventDefault();
          e.stopPropagation();
          nextTab.focus();

          // Workaround for JSDom testing:
          // In JsDom 'element.focus()' does not trigger any focus event
          if (!nextTab.hasAttribute(_constants.ARIA_SELECTED)) {

            [].concat((0, _toConsumableArray3.default)(_this3.element_.querySelectorAll('.' + TAB + '[aria-selected="true"]'))).forEach(function (selectedTab) {
              return selectedTab.removeAttribute(_constants.ARIA_SELECTED);
            });

            nextTab.setAttribute(_constants.ARIA_SELECTED, 'true');
          }
        }
      } else if (e.keyCode === _constants.VK_ENTER || e.keyCode === _constants.VK_SPACE) {
        e.preventDefault();
        e.stopPropagation();
        _this3.toggleTab_(panel, tab, tabpanel);
      }
    };

    if (tab === null) {
      throw new Error('There must be a tab element for each accordion panel.');
    }

    if (tabpanel === null) {
      throw new Error('There must be a tabpanel element for each accordion panel.');
    }

    panel.setAttribute('role', PANEL_ROLE);
    tab.setAttribute('role', TAB_ROLE);
    tabpanel.setAttribute('role', TABPANEL_ROLE);

    if (tab.hasAttribute('disabled')) {
      disableTab();
    } else {
      enableTab();
    }

    if (this.element_.classList.contains(ACCORDION_HORIZONTAL)) {
      calcMaxTabCaptionWidth();
    }

    if (this.element_.classList.contains(RIPPLE_EFFECT)) {
      tab.classList.add(RIPPLE);
    }

    if (this.element_.classList.contains(ANIMATION_EFFECT)) {
      tabpanel.classList.add(ANIMATION);
    }

    // Remove listeners, just in case ...
    tab.removeEventListener('click', tabClickHandler);
    tab.removeEventListener('focus', tabFocusHandler);
    tab.removeEventListener('keydown', tabKeydownHandler);
    tabpanel.removeEventListener('click', tabpanelClickHandler);
    tabpanel.removeEventListener('focus', tabpanelFocusHandler);

    tab.addEventListener('click', tabClickHandler);
    tab.addEventListener('focus', tabFocusHandler);
    tab.addEventListener('keydown', tabKeydownHandler);
    tabpanel.addEventListener('click', tabpanelClickHandler, true);
    tabpanel.addEventListener('focus', tabpanelFocusHandler, true);
  };
  MaterialExtAccordion.prototype['upgradeTab'] = MaterialExtAccordion.prototype.upgradeTab;

  /**
   * Execute command
   * @param detail
   */
  MaterialExtAccordion.prototype.command = function (detail) {
    var _this4 = this;

    var openTab = function openTab(tabElement) {

      if (tabElement === undefined) {
        _this4.openTabs_();
      } else if (tabElement !== null) {
        var _accordionPanelElemen2 = accordionPanelElements(tabElement),
            panel = _accordionPanelElemen2.panel,
            tab = _accordionPanelElemen2.tab,
            tabpanel = _accordionPanelElemen2.tabpanel;

        if (tab.getAttribute(_constants.ARIA_EXPANDED).toLowerCase() !== 'true') {
          _this4.toggleTab_(panel, tab, tabpanel);
        }
      }
    };

    var closeTab = function closeTab(tabElement) {
      if (tabElement === undefined) {
        _this4.closeTabs_();
      } else if (tabElement !== null) {
        var _accordionPanelElemen3 = accordionPanelElements(tabElement),
            panel = _accordionPanelElemen3.panel,
            tab = _accordionPanelElemen3.tab,
            tabpanel = _accordionPanelElemen3.tabpanel;

        if (tab.getAttribute(_constants.ARIA_EXPANDED).toLowerCase() === 'true') {
          _this4.toggleTab_(panel, tab, tabpanel);
        }
      }
    };

    var toggleTab = function toggleTab(tabElement) {
      if (tabElement) {
        var _accordionPanelElemen4 = accordionPanelElements(tabElement),
            panel = _accordionPanelElemen4.panel,
            tab = _accordionPanelElemen4.tab,
            tabpanel = _accordionPanelElemen4.tabpanel;

        _this4.toggleTab_(panel, tab, tabpanel);
      }
    };

    if (detail && detail.action) {
      var action = detail.action,
          target = detail.target;


      switch (action.toLowerCase()) {
        case 'open':
          openTab(target);
          break;
        case 'close':
          closeTab(target);
          break;
        case 'toggle':
          toggleTab(target);
          break;
        case 'upgrade':
          if (target) {
            this.upgradeTab(target);
          }
          break;
        default:
          throw new Error('Unknown action "' + action + '". Action must be one of "open", "close", "toggle" or "upgrade"');
      }
    }
  };
  MaterialExtAccordion.prototype['command'] = MaterialExtAccordion.prototype.command;

  /**
   * Initialize component
   */
  MaterialExtAccordion.prototype.init = function () {
    var _this5 = this;

    if (this.element_) {
      // Do the init required for this component to work
      if (!(this.element_.classList.contains(ACCORDION_HORIZONTAL) || this.element_.classList.contains(ACCORDION_VERTICAL))) {
        throw new Error('Accordion must have one of the classes "' + ACCORDION_HORIZONTAL + '" or "' + ACCORDION_VERTICAL + '"');
      }

      this.element_.setAttribute('role', 'tablist');

      if (!this.element_.hasAttribute(_constants.ARIA_MULTISELECTABLE)) {
        this.element_.setAttribute(_constants.ARIA_MULTISELECTABLE, 'false');
      }

      this.element_.removeEventListener('command', this.commandHandler_);
      this.element_.addEventListener('command', this.commandHandler_.bind(this), false);

      [].concat((0, _toConsumableArray3.default)(this.element_.querySelectorAll('.' + ACCORDION + ' > .' + PANEL))).forEach(function (panel) {
        return _this5.upgradeTab(panel);
      });

      // Set upgraded flag
      this.element_.classList.add(_constants.IS_UPGRADED);
    }
  };

  /*
   * Downgrade component
   * E.g remove listeners and clean up resources
   *
   * Nothing to downgrade
   *
   MaterialExtAccordion.prototype.mdlDowngrade_ = function() {
     'use strict';
     console.log('***** MaterialExtAccordion.mdlDowngrade');
   };
   */

  // The component registers itself. It can assume componentHandler is available
  // in the global scope.
  /* eslint no-undef: 0 */
  componentHandler.register({
    constructor: MaterialExtAccordion,
    classAsString: 'MaterialExtAccordion',
    cssClass: 'mdlext-js-accordion',
    widget: true
  });
})(); /**
       * @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 WAI-ARIA friendly accordion component.
 * An accordion is a collection of expandable panels associated with a common outer container. Panels consist
 * of a header and an associated content region or tabpanel. The primary use of an Accordion is to present multiple sections
 * of content on a single page without scrolling, where all of the sections are peers in the application or object hierarchy.
 * The general look is similar to a tree where each root tree node is an expandable accordion header. The user navigates
 * and makes the contents of each panel visible (or not) by interacting with the Accordion Header
 */