'use strict';

exports.__esModule = true;

var _extends2 = require('babel-runtime/helpers/extends');

var _extends3 = _interopRequireDefault(_extends2);

var _objectWithoutProperties2 = require('babel-runtime/helpers/objectWithoutProperties');

var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);

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

var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');

var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);

var _inherits2 = require('babel-runtime/helpers/inherits');

var _inherits3 = _interopRequireDefault(_inherits2);

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _propTypes = require('prop-types');

var _propTypes2 = _interopRequireDefault(_propTypes);

var _lodash = require('lodash');

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

/**
 * List is container component used to help group list items.
 * @category containers
 * @component list-item
 * @variations collab-ui-react
 */

var List = function (_React$Component) {
  (0, _inherits3.default)(List, _React$Component);

  function List() {
    var _temp, _this, _ret;

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

    for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }

    return _ret = (_temp = (_this = (0, _possibleConstructorReturn3.default)(this, _React$Component.call.apply(_React$Component, [this].concat(args))), _this), _this.state = {
      activeIndex: null,
      last: 0,
      focus: null,
      id: _this.props.id || (0, _lodash.uniqueId)('cui-list-')
    }, _this.determineInitialFocus = function () {
      var nonDisabledIndex = _react2.default.Children.toArray(_this.props.children).reduceRight(function (agg, child, idx) {
        return !child.props.disabled && !child.props.isReadOnly ? idx : agg;
      }, null);

      _this.setFocus(nonDisabledIndex);
    }, _this.setSelected = function (e, index, value) {
      var _this$props = _this.props,
          children = _this$props.children,
          onSelect = _this$props.onSelect;
      var activeIndex = _this.state.activeIndex;
      // Don't do anything if onSelect Event Handler is present

      if (onSelect) {
        return onSelect(e, value, index);
      }
      // Don't do anything if index is the same or outside of the bounds
      if (index === activeIndex || index < 0 || index >= children.length) return;

      // Keep reference to last index for event handler
      var last = activeIndex;

      // Call change event handler
      _this.setState({ activeIndex: index, last: last });
    }, _this.setFocus = function (index) {
      _this.setState({ focus: index });
    }, _this.handleClick = function (e, index, disabled, value) {
      if (disabled) {
        e.preventDefault();
        e.stopPropagation();
      }

      _this.setFocus(index);
      _this.setSelected(e, index, value);
    }, _this.getIncludesFirstCharacter = function (str, char) {
      return str.charAt(0).toLowerCase().includes(char);
    }, _this.setFocusByFirstCharacter = function (char, currentIdx, length) {
      var children = _this.props.children;


      var newIndex = _react2.default.Children.toArray(children).reduce(function (agg, child, idx, arr) {

        var index = currentIdx + idx + 1 > length ? Math.abs(currentIdx + idx - length) : currentIdx + idx + 1;

        var label = arr[index].props.role === 'listItem' || arr[index].props.role === 'option' ? arr[index].props.label : arr[index].props.header;

        return !agg.length && !arr[index].props.disabled && !arr[index].props.isReadOnly && _this.getIncludesFirstCharacter(label, char) ? agg.concat(index) : agg;
      }, []);

      !isNaN(newIndex[0]) && _this.setFocus(newIndex[0]);
    }, _this.handleListKeyPress = function (e, idx, length, disabled) {
      if (disabled) {
        e.preventDefault();
        e.stopPropagation();
      }

      var newIndex = void 0,
          clickEvent = void 0;
      var tgt = e.currentTarget;
      var char = e.key;
      var flag = false;

      var getNewIndex = function getNewIndex(currentIndex, change) {
        var getPossibleIndex = function getPossibleIndex() {
          if (currentIndex + change < 0) {
            return length;
          } else if (currentIndex + change > length) {
            return 0;
          }

          return currentIndex + change;
        };

        var possibleIndex = getPossibleIndex();
        var potentialTarget = _react2.default.Children.toArray(_this.props.children)[possibleIndex];

        return potentialTarget.props.disabled || potentialTarget.props.isReadOnly ? getNewIndex(possibleIndex, change) : possibleIndex;
      };

      var isPrintableCharacter = function isPrintableCharacter(str) {
        return str.length === 1 && str.match(/\S/);
      };

      switch (e.which) {
        case 32:
        case 13:
          try {
            clickEvent = new MouseEvent('click', {
              view: window,
              bubbles: true,
              cancelable: true
            });
          } catch (err) {
            if (document.createEvent) {
              // DOM Level 3 for IE 9+
              clickEvent = document.createEvent('MouseEvents');
              clickEvent.initEvent('click', true, true);
            }
          }
          tgt.dispatchEvent(clickEvent);

          flag = true;
          break;

        case 38:
        case 37:
          newIndex = getNewIndex(idx, -1);
          _this.setFocus(newIndex);
          flag = true;
          break;

        case 39:
        case 40:
          newIndex = getNewIndex(idx, 1);
          _this.setFocus(newIndex);
          flag = true;
          break;

        case 33:
        case 36:
          _this.setFocus(0);
          flag = true;
          break;

        case 34:
        case 35:
          _this.setFocus(length);
          flag = true;
          break;
        default:
          if (isPrintableCharacter(char)) {
            _this.setFocusByFirstCharacter(char, idx, length);
            flag = true;
          }
          break;
      }

      if (flag) {
        e.stopPropagation();
        e.preventDefault();
      }
    }, _temp), (0, _possibleConstructorReturn3.default)(_this, _ret);
  }

  List.prototype.componentDidMount = function componentDidMount() {
    this.determineInitialFocus();
  };

  List.prototype.render = function render() {
    var _this2 = this;

    var _props = this.props,
        children = _props.children,
        tabType = _props.tabType,
        role = _props.role,
        className = _props.className,
        type = _props.type,
        itemRole = _props.itemRole,
        isMulti = _props.isMulti,
        active = _props.active,
        props = (0, _objectWithoutProperties3.default)(_props, ['children', 'tabType', 'role', 'className', 'type', 'itemRole', 'isMulti', 'active']);
    var _state = this.state,
        focus = _state.focus,
        activeIndex = _state.activeIndex,
        id = _state.id;
    var visibleClass = this.context.visibleClass;


    var setListItems = _react2.default.Children.map(children, function (child, idx) {
      var arrLength = children.length - 1;
      var disabled = child.props.disabled;
      var value = child.props.value;
      var activeIndicator = !isNaN(active) || Array.isArray(active) ? active : activeIndex;

      switch (child.type.displayName) {
        case 'ListItem':
          return _react2.default.cloneElement(child, (0, _extends3.default)({
            active: idx === activeIndicator,
            type: type,
            focus: focus === idx,
            onClick: function onClick(e) {
              return _this2.handleClick(e, idx, disabled, value);
            },
            onKeyDown: function onKeyDown(e) {
              return _this2.handleListKeyPress(e, idx, arrLength, disabled);
            },
            tabType: tabType,
            role: itemRole,
            id: id + '__list-item'
          }, focus === idx && { ref: function ref(_ref) {
              return _this2.activeChild = _ref;
            } }));
        case 'SpaceListItem':
          return _react2.default.cloneElement(child, (0, _extends3.default)({
            active: idx === activeIndicator,
            focus: focus === idx,
            onClick: function onClick(e) {
              return _this2.handleClick(e, idx, disabled, value);
            },
            onKeyDown: function onKeyDown(e) {
              return _this2.handleListKeyPress(e, idx, arrLength, disabled);
            },
            tabType: tabType,
            role: itemRole,
            id: id + '__sl-item'
          }, focus === idx && { ref: function ref(_ref2) {
              return _this2.activeChild = _ref2;
            } }));
        case 'SpaceListMeeting':
          return _react2.default.cloneElement(child, (0, _extends3.default)({
            active: idx === activeIndicator,
            focus: focus === idx,
            onClick: function onClick(e) {
              return _this2.handleClick(e, idx, disabled, value);
            },
            onKeyDown: function onKeyDown(e) {
              return _this2.handleListKeyPress(e, idx, arrLength, disabled);
            },
            tabType: tabType,
            role: itemRole,
            id: id + '__sl-item'
          }, focus === idx && { ref: function ref(_ref3) {
              return _this2.activeChild = _ref3;
            } }));
        case 'SelectOption':
          return _react2.default.cloneElement(child, (0, _extends3.default)({
            active: Array.isArray(activeIndicator) ? activeIndicator.includes(idx) : idx === activeIndicator,
            focus: focus === idx,
            onClick: function onClick(e) {
              return _this2.handleClick(e, idx, disabled, value);
            },
            onKeyDown: function onKeyDown(e) {
              return _this2.handleListKeyPress(e, idx, arrLength, disabled);
            },
            tabType: tabType,
            role: itemRole,
            isMulti: isMulti,
            id: id + '__so-item'
          }, focus === idx && { ref: function ref(_ref4) {
              return _this2.activeChild = _ref4;
            } }));
        default:
          return child;
      }
    });

    var ActiveDescendantId = this.activeChild && this.activeChild.id;

    /* eslint-disable jsx-a11y/aria-activedescendant-has-tabindex */
    return _react2.default.createElement(
      'div',
      (0, _extends3.default)({
        className: 'cui-list' + (' cui-list' + (tabType && '--' + tabType || '')) + ('' + (visibleClass && ' ' + visibleClass || '')) + ('' + (className && ' ' + className || '')),
        role: role,
        'aria-activedescendant': ActiveDescendantId
      }, props),
      setListItems
    );
    /* eslint-enable*/
  };

  return List;
}(_react2.default.Component);

List.displayName = 'List';
exports.default = List;


List.contextTypes = {
  /** optional visible class prop type */
  visibleClass: _propTypes2.default.string
};

List.defaultProps = {
  active: null,
  children: null,
  className: '',
  id: null,
  isMulti: false,
  itemRole: 'listItem',
  onSelect: null,
  role: 'list',
  type: null,
  tabType: 'vertical'
};
module.exports = exports['default'];