'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 _reactIntl = require('react-intl');

var _reactRouterDom = require('react-router-dom');

var _immutable = require('immutable');

var _immutable2 = _interopRequireDefault(_immutable);

var _SearchResultItemLink = require('./SearchResultItemLink');

var _SearchResultItemLink2 = _interopRequireDefault(_SearchResultItemLink);

var _searchHelpers = require('../../helpers/searchHelpers');

var _SearchResultTraverser = require('../../../styles/cspace-ui/SearchResultTraverser.css');

var _SearchResultTraverser2 = _interopRequireDefault(_SearchResultTraverser);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: 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 messages = (0, _reactIntl.defineMessages)({
  result: {
    'id': 'searchResultTraverser.result',
    'defaultMessage': 'Search result {current, number} of {total, number}'
  },
  resultPending: {
    'id': 'searchResultTraverser.resultPending',
    'defaultMessage': 'Search result \u2026 of \u2026'
  },
  prev: {
    'id': 'searchResultTraverser.prev',
    'defaultMessage': 'Previous'
  },
  next: {
    'id': 'searchResultTraverser.next',
    'defaultMessage': 'Next'
  }
});

var propTypes = {
  config: _propTypes2.default.object,
  csid: _propTypes2.default.string,
  searchName: _propTypes2.default.string,
  searchDescriptor: _propTypes2.default.instanceOf(_immutable2.default.Map),
  searchState: _propTypes2.default.instanceOf(_immutable2.default.Map),
  nextPageSearchDescriptor: _propTypes2.default.object,
  nextPageSearchState: _propTypes2.default.instanceOf(_immutable2.default.Map),
  prevPageSearchDescriptor: _propTypes2.default.object,
  prevPageSearchState: _propTypes2.default.instanceOf(_immutable2.default.Map),
  search: _propTypes2.default.func
};

var SearchResultTraverser = function (_Component) {
  _inherits(SearchResultTraverser, _Component);

  function SearchResultTraverser() {
    _classCallCheck(this, SearchResultTraverser);

    return _possibleConstructorReturn(this, (SearchResultTraverser.__proto__ || Object.getPrototypeOf(SearchResultTraverser)).apply(this, arguments));
  }

  _createClass(SearchResultTraverser, [{
    key: 'componentDidMount',
    value: function componentDidMount() {
      this.initiateSearch();
    }
  }, {
    key: 'componentDidUpdate',
    value: function componentDidUpdate() {
      this.initiateSearch();
    }
  }, {
    key: 'initiateSearch',
    value: function initiateSearch() {
      var _props = this.props,
          config = _props.config,
          csid = _props.csid,
          searchDescriptor = _props.searchDescriptor,
          searchState = _props.searchState,
          nextPageSearchDescriptor = _props.nextPageSearchDescriptor,
          nextPageSearchState = _props.nextPageSearchState,
          prevPageSearchDescriptor = _props.prevPageSearchDescriptor,
          prevPageSearchState = _props.prevPageSearchState,
          searchName = _props.searchName,
          search = _props.search;


      if (search) {
        if (searchDescriptor && !searchState) {
          // We have a search descriptor, but it's not associated with any state. This happens when
          // navigating to a record from a search, and reloading -- the search descriptor is
          // maintained in history state, but the search state is gone, since the app has been
          // reloaded. Initiate the search.

          search(config, searchName, searchDescriptor, (0, _searchHelpers.getListType)(config, searchDescriptor));
        }

        if (searchState && !searchState.get('isPending') && searchState.get('result')) {
          var listType = (0, _searchHelpers.getListType)(config, searchDescriptor);
          var listTypeConfig = config.listTypes[listType];
          var listNodeName = listTypeConfig.listNodeName,
              itemNodeName = listTypeConfig.itemNodeName;


          var indexesByCsid = searchState.get('indexesByCsid');
          var index = indexesByCsid.get(csid);

          var result = searchState.get('result');
          var list = result.get(listNodeName);

          var totalItems = list.get('totalItems');

          var pageNum = list.get('pageNum');
          var pageSize = list.get('pageSize');

          var currentNum = pageNum * pageSize + index + 1;

          var prevIndex = index - 1;
          var nextIndex = index + 1;

          var items = list.get(itemNodeName);

          if (items && !_immutable2.default.List.isList(items)) {
            items = _immutable2.default.List.of(items);
          }

          if (!prevPageSearchState && prevIndex < 0 && currentNum > 1 && prevPageSearchDescriptor) {
            // The previous page has not been retrieved, and we're on the first item of the current
            // page. Initiate the search for the previous page.

            search(config, searchName, prevPageSearchDescriptor, (0, _searchHelpers.getListType)(config, prevPageSearchDescriptor));
          }

          if (!nextPageSearchState && nextIndex > items.size - 1 && currentNum < totalItems && nextPageSearchDescriptor) {
            // The next page has not been retrieved, and we're on the last item of the current page.
            // Initiate the search for the next page.

            search(config, searchName, nextPageSearchDescriptor, (0, _searchHelpers.getListType)(config, nextPageSearchDescriptor));
          }
        }
      }
    }
  }, {
    key: 'renderPrevLink',
    value: function renderPrevLink(items, index, currentNum, totalItems, locationState) {
      var _props2 = this.props,
          config = _props2.config,
          searchName = _props2.searchName,
          prevPageSearchState = _props2.prevPageSearchState,
          prevPageSearchDescriptor = _props2.prevPageSearchDescriptor;


      var prevIndex = index - 1;

      if (prevIndex >= 0) {
        return _react2.default.createElement(_SearchResultItemLink2.default, {
          rel: 'prev',
          config: config,
          item: items.get(prevIndex),
          message: messages.prev,
          state: locationState
        });
      }

      if (prevPageSearchState && !prevPageSearchState.get('isPending') && prevPageSearchState.get('result')) {
        // We're at the beginning of the current page, but we have data for the previous page. Link
        // to the last item in its results.

        var listType = (0, _searchHelpers.getListType)(config, prevPageSearchDescriptor);
        var listTypeConfig = config.listTypes[listType];
        var listNodeName = listTypeConfig.listNodeName,
            itemNodeName = listTypeConfig.itemNodeName;


        var prevPageItems = prevPageSearchState.getIn(['result', listNodeName, itemNodeName]);

        if (prevPageItems && !_immutable2.default.List.isList(prevPageItems)) {
          prevPageItems = _immutable2.default.List.of(prevPageItems);
        }

        return _react2.default.createElement(_SearchResultItemLink2.default, {
          rel: 'prev',
          config: config,
          item: prevPageItems.last(),
          message: messages.prev,
          state: {
            searchName: searchName,
            searchDescriptor: prevPageSearchDescriptor.toJS()
          }
        });
      }

      if (currentNum > 1) {
        // We don't have data for the previous page, but there is one. Show a placeholder link.

        return _react2.default.createElement(
          'a',
          { rel: 'prev' },
          _react2.default.createElement(_reactIntl.FormattedMessage, messages.prev)
        );
      }

      // We're on the first item of all pages. Show a placeholder link.

      return _react2.default.createElement(
        'a',
        { rel: 'prev' },
        _react2.default.createElement(_reactIntl.FormattedMessage, messages.prev)
      );
    }
  }, {
    key: 'renderNextLink',
    value: function renderNextLink(items, index, currentNum, totalItems, locationState) {
      var _props3 = this.props,
          config = _props3.config,
          searchName = _props3.searchName,
          nextPageSearchState = _props3.nextPageSearchState,
          nextPageSearchDescriptor = _props3.nextPageSearchDescriptor;


      var nextIndex = index + 1;

      if (nextIndex <= items.size - 1) {
        return _react2.default.createElement(_SearchResultItemLink2.default, {
          rel: 'next',
          config: config,
          item: items.get(nextIndex),
          message: messages.next,
          state: locationState
        });
      }

      if (nextPageSearchState && !nextPageSearchState.get('isPending') && nextPageSearchState.get('result')) {
        // We're at the end of the current page, but we have data for the next page. Link to the
        // first item in its results.

        var listType = (0, _searchHelpers.getListType)(config, nextPageSearchDescriptor);
        var listTypeConfig = config.listTypes[listType];
        var listNodeName = listTypeConfig.listNodeName,
            itemNodeName = listTypeConfig.itemNodeName;


        var nextPageItems = nextPageSearchState.getIn(['result', listNodeName, itemNodeName]);

        if (nextPageItems && !_immutable2.default.List.isList(nextPageItems)) {
          nextPageItems = _immutable2.default.List.of(nextPageItems);
        }

        return _react2.default.createElement(_SearchResultItemLink2.default, {
          rel: 'next',
          config: config,
          item: nextPageItems.first(),
          message: messages.next,
          state: {
            searchName: searchName,
            searchDescriptor: nextPageSearchDescriptor.toJS()
          }
        });
      }

      if (currentNum < totalItems) {
        // We don't have data for the next page, but there is one. Show a placeholder link.

        return _react2.default.createElement(
          'a',
          { rel: 'next' },
          _react2.default.createElement(_reactIntl.FormattedMessage, messages.next)
        );
      }

      // We're on the last item of all pages. Show a placeholder link.

      return _react2.default.createElement(
        'a',
        { rel: 'next' },
        _react2.default.createElement(_reactIntl.FormattedMessage, messages.next)
      );
    }
  }, {
    key: 'render',
    value: function render() {
      var _props4 = this.props,
          config = _props4.config,
          csid = _props4.csid,
          searchDescriptor = _props4.searchDescriptor,
          searchName = _props4.searchName,
          searchState = _props4.searchState;


      if (!searchDescriptor) {
        return null;
      }

      var resultMessage = void 0;
      var prevLink = void 0;
      var nextLink = void 0;

      if (!searchState || searchState.get('isPending') || searchState.get('error')) {
        resultMessage = _react2.default.createElement(_reactIntl.FormattedMessage, messages.resultPending);
      } else {
        var listType = (0, _searchHelpers.getListType)(config, searchDescriptor);
        var listTypeConfig = config.listTypes[listType];
        var listNodeName = listTypeConfig.listNodeName,
            itemNodeName = listTypeConfig.itemNodeName;


        var indexesByCsid = searchState.get('indexesByCsid');
        var index = indexesByCsid.get(csid);

        var result = searchState.get('result');
        var list = result.get(listNodeName);

        var totalItems = list.get('totalItems');

        var pageNum = list.get('pageNum');
        var pageSize = list.get('pageSize');

        var currentNum = pageNum * pageSize + index + 1;

        resultMessage = _react2.default.createElement(_reactIntl.FormattedMessage, _extends({}, messages.result, {
          values: { current: currentNum, total: totalItems }
        }));

        var items = result.getIn([listNodeName, itemNodeName]);

        if (items && !_immutable2.default.List.isList(items)) {
          items = _immutable2.default.List.of(items);
        }

        var locationState = {
          searchName: searchName,
          searchDescriptor: searchDescriptor.toJS()
        };

        prevLink = this.renderPrevLink(items, index, currentNum, totalItems, locationState);
        nextLink = this.renderNextLink(items, index, currentNum, totalItems, locationState);
      }

      return _react2.default.createElement(
        'nav',
        { className: _SearchResultTraverser2.default.common },
        _react2.default.createElement(
          'div',
          null,
          _react2.default.createElement(
            _reactRouterDom.Link,
            { rel: 'search', to: (0, _searchHelpers.searchDescriptorToLocation)(searchDescriptor) },
            resultMessage
          )
        ),
        _react2.default.createElement(
          'div',
          null,
          prevLink,
          prevLink && nextLink ? ' | ' : null,
          nextLink
        )
      );
    }
  }]);

  return SearchResultTraverser;
}(_react.Component);

exports.default = SearchResultTraverser;


SearchResultTraverser.propTypes = propTypes;