"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var _react = _interopRequireWildcard(require("react"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _reactIntl = require("react-intl");
var _reactRouterDom = require("react-router-dom");
var _immutable = _interopRequireDefault(require("immutable"));
var _SearchResultItemLink = _interopRequireDefault(require("./SearchResultItemLink"));
var _searchHelpers = require("../../helpers/searchHelpers");
var _SearchResultTraverser = _interopRequireDefault(require("../../../styles/cspace-ui/SearchResultTraverser.css"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function _extends() { _extends = Object.assign ? Object.assign.bind() : 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; }; return _extends.apply(this, arguments); }
const 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"
  }
});
const propTypes = {
  config: _propTypes.default.shape({
    listTypes: _propTypes.default.object
  }),
  csid: _propTypes.default.string,
  searchName: _propTypes.default.string,
  searchDescriptor: _propTypes.default.instanceOf(_immutable.default.Map),
  searchState: _propTypes.default.instanceOf(_immutable.default.Map),
  nextPageSearchDescriptor: _propTypes.default.instanceOf(_immutable.default.Map),
  nextPageSearchState: _propTypes.default.instanceOf(_immutable.default.Map),
  prevPageSearchDescriptor: _propTypes.default.instanceOf(_immutable.default.Map),
  prevPageSearchState: _propTypes.default.instanceOf(_immutable.default.Map),
  // eslint-disable-next-line react/forbid-prop-types
  originSearchPageState: _propTypes.default.object,
  search: _propTypes.default.func
};
class SearchResultTraverser extends _react.Component {
  componentDidMount() {
    this.initiateSearch();
  }
  componentDidUpdate() {
    this.initiateSearch();
  }
  initiateSearch() {
    const {
      config,
      csid,
      searchDescriptor,
      searchState,
      nextPageSearchDescriptor,
      nextPageSearchState,
      prevPageSearchDescriptor,
      prevPageSearchState,
      searchName,
      search
    } = this.props;
    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')) {
        const listType = (0, _searchHelpers.getListType)(config, searchDescriptor);
        const listTypeConfig = config.listTypes[listType];
        const {
          listNodeName,
          itemNodeName
        } = listTypeConfig;
        const indexesByCsid = searchState.get('indexesByCsid');
        const index = indexesByCsid.get(csid);
        const result = searchState.get('result');
        const list = result.get(listNodeName);
        const totalItems = list.get('totalItems');
        const pageNum = list.get('pageNum');
        const pageSize = list.get('pageSize');
        const currentNum = pageNum * pageSize + index + 1;
        const prevIndex = index - 1;
        const nextIndex = index + 1;
        let items = list.get(itemNodeName);
        if (items && !_immutable.default.List.isList(items)) {
          items = _immutable.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));
        }
      }
    }
  }
  renderPrevLink(items, index, currentNum, totalItems, locationState) {
    const {
      config,
      searchName,
      prevPageSearchState,
      prevPageSearchDescriptor
    } = this.props;
    const prevIndex = index - 1;
    if (prevIndex >= 0) {
      return /*#__PURE__*/_react.default.createElement(_SearchResultItemLink.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.

      const listType = (0, _searchHelpers.getListType)(config, prevPageSearchDescriptor);
      const listTypeConfig = config.listTypes[listType];
      const {
        listNodeName,
        itemNodeName
      } = listTypeConfig;
      let prevPageItems = prevPageSearchState.getIn(['result', listNodeName, itemNodeName]);
      if (prevPageItems && !_immutable.default.List.isList(prevPageItems)) {
        prevPageItems = _immutable.default.List.of(prevPageItems);
      }
      return /*#__PURE__*/_react.default.createElement(_SearchResultItemLink.default, {
        rel: "prev",
        config: config,
        item: prevPageItems.last(),
        message: messages.prev,
        state: {
          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 /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, messages.prev);
    }

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

    return /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, messages.prev);
  }
  renderNextLink(items, index, currentNum, totalItems, locationState) {
    const {
      config,
      searchName,
      nextPageSearchState,
      nextPageSearchDescriptor
    } = this.props;
    const nextIndex = index + 1;
    if (nextIndex <= items.size - 1) {
      return /*#__PURE__*/_react.default.createElement(_SearchResultItemLink.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.

      const listType = (0, _searchHelpers.getListType)(config, nextPageSearchDescriptor);
      const listTypeConfig = config.listTypes[listType];
      const {
        listNodeName,
        itemNodeName
      } = listTypeConfig;
      let nextPageItems = nextPageSearchState.getIn(['result', listNodeName, itemNodeName]);
      if (nextPageItems && !_immutable.default.List.isList(nextPageItems)) {
        nextPageItems = _immutable.default.List.of(nextPageItems);
      }
      return /*#__PURE__*/_react.default.createElement(_SearchResultItemLink.default, {
        rel: "next",
        config: config,
        item: nextPageItems.first(),
        message: messages.next,
        state: {
          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 /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, messages.next);
    }

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

    return /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, messages.next);
  }
  render() {
    const {
      config,
      csid,
      searchDescriptor,
      searchName,
      searchState,
      originSearchPageState
    } = this.props;
    if (!searchDescriptor) {
      return null;
    }
    let resultMessage;
    let prevLink;
    let nextLink;
    if (!searchState || searchState.get('isPending') || searchState.get('error')) {
      resultMessage = /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, messages.resultPending);
    } else {
      const listType = (0, _searchHelpers.getListType)(config, searchDescriptor);
      const listTypeConfig = config.listTypes[listType];
      const {
        listNodeName,
        itemNodeName
      } = listTypeConfig;
      const indexesByCsid = searchState.get('indexesByCsid');
      const index = indexesByCsid.get(csid);
      const result = searchState.get('result');
      const list = result.get(listNodeName);
      const totalItems = list.get('totalItems');
      const pageNum = list.get('pageNum');
      const pageSize = list.get('pageSize');
      const currentNum = pageNum * pageSize + index + 1;
      resultMessage = /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, _extends({}, messages.result, {
        values: {
          current: currentNum,
          total: totalItems
        }
      }));
      let items = result.getIn([listNodeName, itemNodeName]);
      if (items && !_immutable.default.List.isList(items)) {
        items = _immutable.default.List.of(items);
      }
      const locationState = {
        searchName,
        searchDescriptor: searchDescriptor.toJS(),
        originSearchPage: originSearchPageState
      };
      prevLink = this.renderPrevLink(items, index, currentNum, totalItems, locationState);
      nextLink = this.renderNextLink(items, index, currentNum, totalItems, locationState);
    }
    const searchLocation = Object.assign((0, _searchHelpers.searchDescriptorToLocation)(searchDescriptor), {
      state: {
        originSearchPage: originSearchPageState
      }
    });
    return /*#__PURE__*/_react.default.createElement("nav", {
      className: _SearchResultTraverser.default.common
    }, /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_reactRouterDom.Link, {
      rel: "search",
      to: searchLocation
    }, resultMessage)), /*#__PURE__*/_react.default.createElement("div", null, prevLink, prevLink && nextLink ? ' | ' : null, nextLink));
  }
}
exports.default = SearchResultTraverser;
SearchResultTraverser.propTypes = propTypes;