"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = exports.BaseSearchToSelectModal = exports.searchName = void 0;

var _react = _interopRequireWildcard(require("react"));

var _propTypes = _interopRequireDefault(require("prop-types"));

var _reactIntl = require("react-intl");

var _immutable = _interopRequireDefault(require("immutable"));

var _get = _interopRequireDefault(require("lodash/get"));

var _isEqual = _interopRequireDefault(require("lodash/isEqual"));

var _cspaceLayout = require("cspace-layout");

var _CheckboxInput = _interopRequireDefault(require("cspace-input/lib/components/CheckboxInput"));

var _SearchForm = _interopRequireDefault(require("./SearchForm"));

var _Pager = _interopRequireDefault(require("./Pager"));

var _AcceptSelectionButton = _interopRequireDefault(require("./AcceptSelectionButton"));

var _BackButton = _interopRequireDefault(require("../navigation/BackButton"));

var _CancelButton = _interopRequireDefault(require("../navigation/CancelButton"));

var _SearchButton = _interopRequireDefault(require("./SearchButton"));

var _SearchClearButton = _interopRequireDefault(require("./SearchClearButton"));

var _SearchResultSummary = _interopRequireDefault(require("./SearchResultSummary"));

var _SearchToSelectTitleBar = _interopRequireDefault(require("./SearchToSelectTitleBar"));

var _SelectBar = _interopRequireDefault(require("./SelectBar"));

var _SearchResultTableContainer = _interopRequireDefault(require("../../containers/search/SearchResultTableContainer"));

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

var _SearchToSelectModal = _interopRequireDefault(require("../../../styles/cspace-ui/SearchToSelectModal.css"));

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

function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (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; }

const searchName = 'searchToSelect';
exports.searchName = searchName;
const messages = (0, _reactIntl.defineMessages)({
  editSearch: {
    "id": "searchToSelectModal.editSearch",
    "defaultMessage": "Revise search"
  },
  label: {
    "id": "searchToSelectModal.label",
    "defaultMessage": "Select records"
  }
});
const listType = 'common'; // FIXME: Make default page size configurable

const defaultPageSize = 20;

const stopPropagation = event => {
  event.stopPropagation();
};

const propTypes = {
  acceptButtonClassName: _propTypes.default.string,
  acceptButtonLabel: _propTypes.default.node,
  allowedRecordTypes: _propTypes.default.arrayOf(_propTypes.default.string),
  allowedServiceTypes: _propTypes.default.arrayOf(_propTypes.default.string),
  config: _propTypes.default.shape({
    listTypes: _propTypes.default.object,
    recordTypes: _propTypes.default.object
  }),
  intl: _reactIntl.intlShape,
  isOpen: _propTypes.default.bool,
  keywordValue: _propTypes.default.string,
  defaultRecordTypeValue: _propTypes.default.string,
  defaultVocabularyValue: _propTypes.default.string,
  recordTypeValue: _propTypes.default.string,
  vocabularyValue: _propTypes.default.string,
  advancedSearchCondition: _propTypes.default.instanceOf(_immutable.default.Map),
  preferredAdvancedSearchBooleanOp: _propTypes.default.string,
  preferredPageSize: _propTypes.default.number,
  perms: _propTypes.default.instanceOf(_immutable.default.Map),
  selectedItems: _propTypes.default.instanceOf(_immutable.default.Map),
  singleSelect: _propTypes.default.bool,
  titleMessage: _propTypes.default.objectOf(_propTypes.default.string),
  getAuthorityVocabCsid: _propTypes.default.func,
  buildRecordFieldOptionLists: _propTypes.default.func,
  deleteOptionList: _propTypes.default.func,
  onAdvancedSearchConditionCommit: _propTypes.default.func,
  onKeywordCommit: _propTypes.default.func,
  onRecordTypeCommit: _propTypes.default.func,
  onVocabularyCommit: _propTypes.default.func,
  onAccept: _propTypes.default.func,
  onCloseButtonClick: _propTypes.default.func,
  onCancelButtonClick: _propTypes.default.func,
  onClearButtonClick: _propTypes.default.func,
  onItemSelectChange: _propTypes.default.func,
  customizeSearchDescriptor: _propTypes.default.func,
  clearSearchResults: _propTypes.default.func,
  parentSelector: _propTypes.default.func,
  renderAcceptPending: _propTypes.default.func,
  search: _propTypes.default.func,
  setAllItemsSelected: _propTypes.default.func,
  setPreferredPageSize: _propTypes.default.func,
  shouldShowCheckbox: _propTypes.default.func
};
const defaultProps = {
  defaultVocabularyValue: 'all',
  selectedItems: _immutable.default.Map(),
  renderAcceptPending: () => /*#__PURE__*/_react.default.createElement("p", null),
  shouldShowCheckbox: () => true
};

class BaseSearchToSelectModal extends _react.Component {
  constructor() {
    super();
    this.handleAcceptButtonClick = this.handleAcceptButtonClick.bind(this);
    this.handleCancelButtonClick = this.handleCancelButtonClick.bind(this);
    this.handleCheckboxCommit = this.handleCheckboxCommit.bind(this);
    this.handleCloseButtonClick = this.handleCloseButtonClick.bind(this);
    this.handleEditSearchLinkClick = this.handleEditSearchLinkClick.bind(this);
    this.handleFormSearch = this.handleFormSearch.bind(this);
    this.handleItemClick = this.handleItemClick.bind(this);
    this.handlePageChange = this.handlePageChange.bind(this);
    this.handlePageSizeChange = this.handlePageSizeChange.bind(this);
    this.handleSortChange = this.handleSortChange.bind(this);
    this.renderCheckbox = this.renderCheckbox.bind(this);
    this.renderEditSearchLink = this.renderEditSearchLink.bind(this);
    this.renderModalButtonBar = this.renderModalButtonBar.bind(this);
    this.renderSearchResultTableHeader = this.renderSearchResultTableHeader.bind(this);
    this.renderSearchResultTableFooter = this.renderSearchResultTableFooter.bind(this);
    this.state = {
      isSearchInitiated: false,
      pageNum: 0,
      sort: null
    };
  } // eslint-disable-next-line camelcase


  UNSAFE_componentWillReceiveProps(nextProps) {
    const {
      isOpen
    } = this.props;
    const {
      isOpen: nextIsOpen
    } = nextProps;

    if (isOpen && !nextIsOpen) {
      // Closing.
      this.setState({
        isAcceptHandlerPending: false,
        isSearchInitiated: false,
        pageNum: 0,
        sort: null
      });
    }
  }

  componentDidUpdate(prevProps, prevState) {
    const {
      isOpen
    } = this.props;
    const {
      isOpen: prevIsOpen
    } = prevProps;

    if (prevIsOpen && !isOpen) {
      // Closed.
      const {
        clearSearchResults,
        onRecordTypeCommit
      } = this.props;

      if (clearSearchResults) {
        clearSearchResults(searchName);
      }

      if (onRecordTypeCommit) {
        onRecordTypeCommit('');
      }
    } else if (!prevIsOpen && isOpen) {
      // Opened.
      const {
        config,
        defaultRecordTypeValue,
        defaultVocabularyValue,
        onRecordTypeCommit,
        onVocabularyCommit
      } = this.props;

      if (onRecordTypeCommit) {
        onRecordTypeCommit(defaultRecordTypeValue);

        if (onVocabularyCommit) {
          const serviceType = (0, _get.default)(config, ['recordTypes', defaultRecordTypeValue, 'serviceConfig', 'serviceType']);

          if (serviceType === 'authority') {
            onVocabularyCommit(defaultVocabularyValue);
          }
        }
      }
    }

    const {
      isSearchInitiated,
      pageNum,
      sort
    } = this.state;
    const {
      config,
      defaultVocabularyValue,
      recordTypeValue,
      vocabularyValue,
      advancedSearchCondition,
      preferredPageSize,
      onVocabularyCommit
    } = this.props;
    const {
      recordTypeValue: prevRecordTypeValue,
      vocabularyValue: prevVocabularyValue,
      advancedSearchCondition: prevAdvancedSearchCondition,
      preferredPageSize: prevPreferredPageSize
    } = prevProps;

    if (isSearchInitiated) {
      const {
        pageNum: prevPageNum,
        sort: prevSort
      } = prevState;

      if (recordTypeValue !== prevRecordTypeValue || vocabularyValue !== prevVocabularyValue || !(0, _isEqual.default)(advancedSearchCondition, prevAdvancedSearchCondition) || preferredPageSize !== prevPreferredPageSize || pageNum !== prevPageNum || sort !== prevSort) {
        this.search();
      }
    } else if (recordTypeValue !== prevRecordTypeValue) {
      const serviceType = (0, _get.default)(config, ['recordTypes', recordTypeValue, 'serviceConfig', 'serviceType']);

      if (serviceType === 'authority') {
        onVocabularyCommit(defaultVocabularyValue);
      }
    }
  }

  getSearchDescriptor() {
    const {
      config,
      recordTypeValue: recordType,
      vocabularyValue: vocabulary,
      keywordValue: keyword,
      advancedSearchCondition,
      preferredPageSize,
      customizeSearchDescriptor
    } = this.props;
    const {
      pageNum,
      sort
    } = this.state;
    const pageSize = preferredPageSize || defaultPageSize;
    const searchQuery = {
      p: pageNum,
      size: pageSize
    };

    if (sort) {
      searchQuery.sort = sort;
    }

    const kw = keyword ? keyword.trim() : '';

    if (kw) {
      searchQuery.kw = kw;
    }

    const fields = (0, _get.default)(config, ['recordTypes', recordType, 'fields']);
    const condition = (0, _searchHelpers.normalizeCondition)(fields, advancedSearchCondition);

    if (condition) {
      searchQuery.as = condition;
    }

    const searchDescriptor = _immutable.default.fromJS({
      recordType,
      vocabulary,
      searchQuery
    });

    if (customizeSearchDescriptor) {
      return customizeSearchDescriptor(searchDescriptor);
    }

    return searchDescriptor;
  }

  setItemSelected(index, selected) {
    const {
      config,
      singleSelect,
      setAllItemsSelected,
      onItemSelectChange
    } = this.props;

    if (onItemSelectChange) {
      const searchDescriptor = this.getSearchDescriptor();

      if (singleSelect && selected) {
        setAllItemsSelected(config, searchName, searchDescriptor, listType, false);
      }

      onItemSelectChange(config, searchName, searchDescriptor, listType, index, selected);
    }
  }

  search() {
    const {
      config,
      search
    } = this.props;

    if (search) {
      const searchDescriptor = this.getSearchDescriptor();
      search(config, searchName, searchDescriptor);
      this.setState({
        isSearchInitiated: true
      });
    }
  }

  handleAcceptButtonClick() {
    const {
      isSearchInitiated
    } = this.state;

    if (isSearchInitiated) {
      const {
        onAccept,
        selectedItems
      } = this.props;

      if (onAccept) {
        this.setState({
          isAcceptHandlerPending: true,
          isSearchInitiated: false
        });
        Promise.resolve(onAccept(selectedItems, this.getSearchDescriptor()));
      }
    } else {
      this.search();
    }
  }

  handleCancelButtonClick(event) {
    const {
      onCancelButtonClick
    } = this.props;

    if (onCancelButtonClick) {
      onCancelButtonClick(event);
    }
  }

  handleCloseButtonClick(event) {
    const {
      onCloseButtonClick
    } = this.props;

    if (onCloseButtonClick) {
      onCloseButtonClick(event);
    }
  }

  handleEditSearchLinkClick() {
    const {
      clearSearchResults
    } = this.props;

    if (clearSearchResults) {
      clearSearchResults(searchName);
    }

    this.setState({
      isSearchInitiated: false
    });
  }

  handleFormSearch() {
    this.search();
  }

  handleCheckboxCommit(path, value) {
    const index = parseInt(path[0], 10);
    this.setItemSelected(index, value);
  }

  handleItemClick(item, index) {
    const {
      selectedItems,
      shouldShowCheckbox
    } = this.props;

    if (shouldShowCheckbox(item)) {
      const itemCsid = item.get('csid');
      const selected = selectedItems ? selectedItems.has(itemCsid) : false;
      this.setItemSelected(index, !selected);
    }
  }

  handlePageChange(pageNum) {
    this.setState({
      pageNum
    });
  }

  handlePageSizeChange(pageSize) {
    const {
      setPreferredPageSize
    } = this.props;
    let normalizedPageSize;

    if (Number.isNaN(pageSize) || pageSize < 1) {
      normalizedPageSize = 0;
    } else if (pageSize > 2500) {
      normalizedPageSize = 2500;
    } else {
      normalizedPageSize = pageSize;
    }

    if (setPreferredPageSize) {
      this.setState({
        pageNum: 0
      });
      setPreferredPageSize(normalizedPageSize);
    }
  }

  handleSortChange(sort) {
    this.setState({
      sort
    });
  }

  renderCheckbox({
    rowData,
    rowIndex
  }) {
    const {
      shouldShowCheckbox
    } = this.props;

    if (shouldShowCheckbox(rowData)) {
      const {
        selectedItems
      } = this.props;
      const itemCsid = rowData.get('csid');
      const selected = selectedItems ? selectedItems.has(itemCsid) : false;
      return /*#__PURE__*/_react.default.createElement(_CheckboxInput.default, {
        embedded: true,
        name: `${rowIndex}`,
        value: selected,
        onCommit: this.handleCheckboxCommit // Prevent click on the checkbox from propagating to the row, which would cause
        // double-toggling of the selected state.
        ,
        onClick: stopPropagation
      });
    }

    return null;
  }

  renderSearchForm() {
    const {
      allowedRecordTypes,
      allowedServiceTypes,
      config,
      intl,
      keywordValue,
      recordTypeValue,
      vocabularyValue,
      perms,
      preferredAdvancedSearchBooleanOp,
      advancedSearchCondition,
      getAuthorityVocabCsid,
      buildRecordFieldOptionLists,
      deleteOptionList,
      onAdvancedSearchConditionCommit,
      onKeywordCommit,
      onRecordTypeCommit,
      onVocabularyCommit
    } = this.props;
    let recordTypeInputReadOnly = true;
    let recordTypeInputRootType;

    if (allowedServiceTypes) {
      // Allow the record type to be changed.
      recordTypeInputReadOnly = false; // Don't show the All Records option.

      recordTypeInputRootType = '';
    } else if (allowedRecordTypes) {
      recordTypeInputReadOnly = allowedRecordTypes.length < 2;
    }

    return /*#__PURE__*/_react.default.createElement(_SearchForm.default, {
      config: config,
      intl: intl,
      recordTypeValue: recordTypeValue,
      vocabularyValue: vocabularyValue,
      keywordValue: keywordValue,
      advancedSearchCondition: advancedSearchCondition,
      perms: perms,
      preferredAdvancedSearchBooleanOp: preferredAdvancedSearchBooleanOp,
      recordTypeInputReadOnly: recordTypeInputReadOnly,
      recordTypeInputRootType: recordTypeInputRootType,
      recordTypeInputRecordTypes: allowedRecordTypes,
      recordTypeInputServiceTypes: allowedServiceTypes,
      getAuthorityVocabCsid: getAuthorityVocabCsid,
      buildRecordFieldOptionLists: buildRecordFieldOptionLists,
      deleteOptionList: deleteOptionList,
      onAdvancedSearchConditionCommit: onAdvancedSearchConditionCommit,
      onKeywordCommit: onKeywordCommit,
      onRecordTypeCommit: onRecordTypeCommit,
      onVocabularyCommit: onVocabularyCommit,
      onSearch: this.handleFormSearch
    });
  }

  renderEditSearchLink() {
    return /*#__PURE__*/_react.default.createElement("button", {
      type: "button",
      onClick: this.handleEditSearchLinkClick
    }, /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, messages.editSearch));
  }

  renderSearchResultTableHeader({
    searchError,
    searchResult
  }) {
    const {
      config,
      selectedItems,
      setAllItemsSelected,
      shouldShowCheckbox,
      singleSelect
    } = this.props;

    if (searchError) {
      return null;
    }

    const searchDescriptor = this.getSearchDescriptor();
    let selectBar;

    if (!singleSelect) {
      // If only a single selection is allowed, there's no need to show a count of selected records
      // or  a select all checkbox.
      selectBar = /*#__PURE__*/_react.default.createElement(_SelectBar.default, {
        config: config,
        listType: listType,
        searchDescriptor: searchDescriptor,
        searchName: searchName,
        searchResult: searchResult,
        selectedItems: selectedItems,
        setAllItemsSelected: setAllItemsSelected,
        showCheckboxFilter: shouldShowCheckbox
      });
    }

    return /*#__PURE__*/_react.default.createElement("header", null, /*#__PURE__*/_react.default.createElement(_SearchResultSummary.default, {
      config: config,
      listType: listType,
      searchDescriptor: searchDescriptor,
      searchError: searchError,
      searchResult: searchResult,
      renderEditLink: this.renderEditSearchLink,
      onPageSizeChange: this.handlePageSizeChange
    }), selectBar);
  }

  renderSearchResultTableFooter({
    searchResult
  }) {
    const {
      config
    } = this.props;

    if (searchResult) {
      const listTypeConfig = config.listTypes[listType];
      const list = searchResult.get(listTypeConfig.listNodeName);
      const totalItems = parseInt(list.get('totalItems'), 10);
      const pageSize = parseInt(list.get('pageSize'), 10);
      const pageNum = parseInt(list.get('pageNum'), 10);
      const lastPage = Math.max(0, Number.isNaN(totalItems) ? 0 : Math.ceil(totalItems / pageSize) - 1);
      return /*#__PURE__*/_react.default.createElement("footer", null, /*#__PURE__*/_react.default.createElement(_Pager.default, {
        currentPage: pageNum,
        lastPage: lastPage,
        pageSize: pageSize,
        onPageChange: this.handlePageChange,
        onPageSizeChange: this.handlePageSizeChange
      }));
    }

    return null;
  }

  renderSearchResultTable() {
    const {
      config,
      recordTypeValue
    } = this.props;
    const searchDescriptor = this.getSearchDescriptor();
    return /*#__PURE__*/_react.default.createElement(_SearchResultTableContainer.default, {
      config: config,
      linkItems: false,
      listType: listType,
      recordType: recordTypeValue,
      searchName: searchName,
      searchDescriptor: searchDescriptor,
      showCheckboxColumn: true,
      renderCheckbox: this.renderCheckbox,
      renderHeader: this.renderSearchResultTableHeader,
      renderFooter: this.renderSearchResultTableFooter,
      onItemClick: this.handleItemClick,
      onSortChange: this.handleSortChange
    });
  }

  renderModalButtonBar() {
    const {
      acceptButtonClassName,
      acceptButtonLabel,
      selectedItems,
      onClearButtonClick
    } = this.props;
    const {
      isAcceptHandlerPending,
      isSearchInitiated
    } = this.state;

    const cancelButton = /*#__PURE__*/_react.default.createElement(_CancelButton.default, {
      disabled: isAcceptHandlerPending,
      onClick: this.handleCancelButtonClick
    });

    let acceptButton;
    let backButton;
    let clearButton;

    if (isSearchInitiated) {
      acceptButton = /*#__PURE__*/_react.default.createElement(_AcceptSelectionButton.default, {
        className: acceptButtonClassName,
        disabled: isAcceptHandlerPending || !selectedItems || selectedItems.size < 1,
        label: acceptButtonLabel,
        onClick: this.handleAcceptButtonClick
      });
      backButton = /*#__PURE__*/_react.default.createElement(_BackButton.default, {
        disabled: isAcceptHandlerPending,
        label: /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, messages.editSearch),
        onClick: this.handleEditSearchLinkClick
      });
    } else {
      acceptButton = /*#__PURE__*/_react.default.createElement(_SearchButton.default, {
        disabled: isAcceptHandlerPending,
        type: "button",
        onClick: this.handleAcceptButtonClick
      });
      clearButton = /*#__PURE__*/_react.default.createElement(_SearchClearButton.default, {
        onClick: onClearButtonClick
      });
    }

    return /*#__PURE__*/_react.default.createElement("div", null, clearButton, backButton, cancelButton, acceptButton);
  }

  render() {
    const {
      config,
      intl,
      isOpen,
      recordTypeValue,
      parentSelector,
      singleSelect,
      titleMessage,
      renderAcceptPending
    } = this.props;
    const {
      isAcceptHandlerPending,
      isSearchInitiated
    } = this.state;
    let content;
    let title;

    if (isOpen) {
      if (isAcceptHandlerPending) {
        content = renderAcceptPending();
      } else if (isSearchInitiated) {
        content = this.renderSearchResultTable();
      } else {
        content = this.renderSearchForm();
      }

      const searchDescriptor = this.getSearchDescriptor();
      title = /*#__PURE__*/_react.default.createElement(_SearchToSelectTitleBar.default, {
        config: config,
        isSearchInitiated: isSearchInitiated,
        recordType: recordTypeValue,
        searchDescriptor: searchDescriptor,
        singleSelect: singleSelect,
        titleMessage: titleMessage
      });
    }

    return /*#__PURE__*/_react.default.createElement(_cspaceLayout.Modal, {
      className: _SearchToSelectModal.default.common,
      contentLabel: intl.formatMessage(messages.label),
      title: title,
      isOpen: isOpen,
      showCloseButton: !isAcceptHandlerPending,
      closeButtonClassName: "material-icons",
      closeButtonLabel: "close",
      parentSelector: parentSelector,
      renderButtonBar: this.renderModalButtonBar,
      onCloseButtonClick: this.handleCloseButtonClick
    }, content);
  }

}

exports.BaseSearchToSelectModal = BaseSearchToSelectModal;
BaseSearchToSelectModal.propTypes = propTypes;
BaseSearchToSelectModal.defaultProps = defaultProps;

var _default = (0, _reactIntl.injectIntl)(BaseSearchToSelectModal);

exports.default = _default;