'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _values = require('babel-runtime/core-js/object/values');

var _values2 = _interopRequireDefault(_values);

var _defineProperty2 = require('babel-runtime/helpers/defineProperty');

var _defineProperty3 = _interopRequireDefault(_defineProperty2);

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

var _extends5 = _interopRequireDefault(_extends4);

var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');

var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);

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

var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

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

var _createClass3 = _interopRequireDefault(_createClass2);

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

var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);

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

var _inherits3 = _interopRequireDefault(_inherits2);

var _stringify = require('babel-runtime/core-js/json/stringify');

var _stringify2 = _interopRequireDefault(_stringify);

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

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

var _propTypes2 = _interopRequireDefault(_propTypes);

var _lodash = require('lodash');

var _lodash2 = _interopRequireDefault(_lodash);

var _Table = require('./Table');

var _Table2 = _interopRequireDefault(_Table);

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

var defaultValueRenderer = function defaultValueRenderer(val) {
  return _lodash2.default.isString(val) ? val : _lodash2.default.isArray(val) ? '[' + val.map(defaultValueRenderer).join(',') + ']' : (0, _stringify2.default)(val);
};

/**
 * This is a helper behavioral implementation of a table.
 * Note that this component is not designed to support all use cases, just very simple ones.
 * This component may be moved out of the library in the future.
 *
 * @class SimpleTable
 * @extends {React.Component}
 */

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

  function SimpleTable() {
    var _ref;

    var _temp, _this, _ret;

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

    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, (_ref = SimpleTable.__proto__ || (0, _getPrototypeOf2.default)(SimpleTable)).call.apply(_ref, [this].concat(args))), _this), _this.state = {
      sortOrders: {},
      detailsItemId: null
    }, _this.blankSortOrders = function () {
      return _this.props.columns.reduce(function (orders, _ref2) {
        var name = _ref2.name;
        return (0, _extends5.default)({}, orders, (0, _defineProperty3.default)({}, name, 0));
      }, {});
    }, _this.indexOfDetailsItem = function () {
      return _this.props.items.findIndex(function (item) {
        return _this.props.getId(item) === _this.state.detailsItemId;
      });
    }, _this.createHeaderClickHandler = function (headerName) {
      return _this.props.onSortChanged ? function (sortOrder) {
        var newSortOrder = sortOrder || -_this.state.sortOrders[headerName] || 1;
        _this.setState({
          sortOrders: (0, _extends5.default)({}, _this.blankSortOrders(), (0, _defineProperty3.default)({}, headerName, newSortOrder))
        });
        _this.props.onSortChanged(headerName, newSortOrder);
      } : null;
    }, _this.createRowClickHandler = function (item) {
      return function () {
        if (!_this.props.renderDetails) {
          return;
        }

        if (_this.state.detailsItemId === _this.props.getId(item)) {
          _this.setState({ detailsItemId: null });
        } else {
          _this.setState({ detailsItemId: _this.props.getId(item) });
        }
      };
    }, _this.renderDetails = function (item) {
      var renderDetails = _this.props.renderDetails;

      return _react2.default.createElement(
        _Table2.default.RowDetails,
        { key: 'details' },
        renderDetails(item)
      );
    }, _this.renderUpperSection = function () {
      var _this$props = _this.props,
          items = _this$props.items,
          renderRow = _this$props.renderRow;

      var detailsItemIndex = _this.indexOfDetailsItem();
      return _react2.default.createElement(
        _Table2.default.Body,
        { key: 'upperSection' },
        items.slice(0, detailsItemIndex >= 0 ? detailsItemIndex + 1 : undefined).map(function (item) {
          return _react2.default.cloneElement(renderRow(item), {
            onClick: _this.createRowClickHandler(item),
            key: (0, _stringify2.default)(item)
          });
        })
      );
    }, _this.renderRowDetails = function () {
      var itemIdx = _this.indexOfDetailsItem();

      if (!_this.props.renderDetails || itemIdx === -1) {
        return null;
      }

      var item = _this.props.items[itemIdx];
      return _react2.default.createElement(
        _Table2.default.RowDetails,
        { rowIndex: itemIdx, key: 'rowDetails' },
        _this.props.renderDetails(item)
      );
    }, _this.renderLowerSection = function () {
      var _this$props2 = _this.props,
          items = _this$props2.items,
          renderRow = _this$props2.renderRow;

      var itemIdx = _this.indexOfDetailsItem();
      // if details item is not present, the upper section contains all rows already
      if (itemIdx === -1) {
        return null;
      }

      return _react2.default.createElement(
        _Table2.default.Body,
        { startIndex: itemIdx + 1, key: 'lowerSection' },
        items.slice(itemIdx + 1).map(function (item) {
          return _react2.default.cloneElement(renderRow(item), {
            onClick: _this.createRowClickHandler(item),
            key: (0, _stringify2.default)(item)
          });
        })
      );
    }, _this.renderRows = function () {
      return [_this.renderUpperSection(), _this.renderRowDetails(), _this.renderLowerSection()];
    }, _this.renderColumnHeaders = function () {
      var _this$props3 = _this.props,
          columns = _this$props3.columns,
          onSortChanged = _this$props3.onSortChanged;
      var sortOrders = _this.state.sortOrders;

      if (!columns) {
        return null;
      }

      return _react2.default.createElement(
        _Table2.default.Row,
        null,
        columns.map(function (column, idx) {
          return _react2.default.createElement(
            _Table2.default.Header,
            {
              key: column.name,
              onClick: column.sortable && _this.createHeaderClickHandler(column.name),
              sortable: column.sortable,
              sortOrder: sortOrders[column.name]
            },
            column.displayName || column.name
          );
        })
      );
    }, _temp), (0, _possibleConstructorReturn3.default)(_this, _ret);
  }

  (0, _createClass3.default)(SimpleTable, [{
    key: 'render',
    value: function render() {
      return _react2.default.createElement(
        _Table2.default,
        {
          headers: this.renderColumnHeaders(),
          loading: this.props.loading,
          wrapBody: false
        },
        this.renderRows()
      );
    }
  }]);
  return SimpleTable;
}(_react2.default.Component);

SimpleTable.propTypes = {
  /**
   * An array of data items to use for the rows of the table.
   */
  items: _propTypes2.default.array.isRequired,
  /**
   * Renders a Table.Row that represents a particular item. Row must include an onClick prop for details to work.
   * (item) => <Row />
   */
  renderRow: _propTypes2.default.func,
  /**
   * Renders the detail view of any item when that item is selected.
   */
  renderDetails: _propTypes2.default.func,
  /**
   * An array of column descriptions. Column name should correspond to a key in the data items. displayName is what is actually rendered (defaults to name).
   */
  columns: _propTypes2.default.arrayOf(_propTypes2.default.shape({
    name: _propTypes2.default.string.isRequired,
    displayName: _propTypes2.default.string,
    sortable: _propTypes2.default.bool
  })),
  /**
   * Called when the user changes the sort state of a column. Column name and sort order are passed as params.
   * (columnName, sortOrder) => void
   */
  onSortChanged: _propTypes2.default.func,
  /**
   * Indicates whether the table should render a loading state.
   */
  loading: _propTypes2.default.bool,
  /**
   * A function that provides an unique id for a row item.
   */
  getId: _propTypes2.default.func
};
SimpleTable.defaultProps = {
  renderRow: function renderRow(item) {
    return _react2.default.createElement(
      _Table2.default.Row,
      { key: (0, _stringify2.default)(item) },
      (0, _values2.default)(item).map(function (val) {
        return _react2.default.createElement(
          _Table2.default.Cell,
          null,
          defaultValueRenderer(val)
        );
      })
    );
  },
  renderDetails: null,
  columns: null,
  onSortChanged: function onSortChanged() {
    return null;
  },
  getId: function getId(item) {
    if (_lodash2.default.isString(item)) {
      return item;
    }
    if (_lodash2.default.isFunction(item.get)) {
      return item.get('id');
    }
    return item.id || (0, _stringify2.default)(item);
  },
  loading: false
};
exports.default = SimpleTable;