'use strict';

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

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

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 }; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

var defaultValueRenderer = function defaultValueRenderer(val) {
  return _lodash2.default.isString(val) ? val : _lodash2.default.isArray(val) ? '[' + val.map(defaultValueRenderer).join(',') + ']' : JSON.stringify(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) {
  _inherits(SimpleTable, _React$Component);

  function SimpleTable() {
    var _ref;

    var _temp, _this, _ret;

    _classCallCheck(this, SimpleTable);

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

    return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = SimpleTable.__proto__ || Object.getPrototypeOf(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 _extends({}, orders, _defineProperty({}, 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: _extends({}, _this.blankSortOrders(), _defineProperty({}, 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: JSON.stringify(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: JSON.stringify(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), _possibleConstructorReturn(_this, _ret);
  }

  _createClass(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: JSON.stringify(item) },
      Object.values(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 || JSON.stringify(item);
  },
  loading: false
};
exports.default = SimpleTable;