'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.BaseSearchToRelateModal = exports.searchName = undefined;

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

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

var _propTypes2 = _interopRequireDefault(_propTypes);

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

var _immutable = require('immutable');

var _immutable2 = _interopRequireDefault(_immutable);

var _get = require('lodash/get');

var _get2 = _interopRequireDefault(_get);

var _isEqual = require('lodash/isEqual');

var _isEqual2 = _interopRequireDefault(_isEqual);

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

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

var _CheckboxInput2 = _interopRequireDefault(_CheckboxInput);

var _SearchForm = require('./SearchForm');

var _SearchForm2 = _interopRequireDefault(_SearchForm);

var _Pager = require('./Pager');

var _Pager2 = _interopRequireDefault(_Pager);

var _BackButton = require('../navigation/BackButton');

var _BackButton2 = _interopRequireDefault(_BackButton);

var _CancelButton = require('../navigation/CancelButton');

var _CancelButton2 = _interopRequireDefault(_CancelButton);

var _RelateButton = require('../record/RelateButton');

var _RelateButton2 = _interopRequireDefault(_RelateButton);

var _SearchButton = require('./SearchButton');

var _SearchButton2 = _interopRequireDefault(_SearchButton);

var _SearchResultSummary = require('./SearchResultSummary');

var _SearchResultSummary2 = _interopRequireDefault(_SearchResultSummary);

var _SearchToRelateTitleBar = require('./SearchToRelateTitleBar');

var _SearchToRelateTitleBar2 = _interopRequireDefault(_SearchToRelateTitleBar);

var _SelectBar = require('./SelectBar');

var _SelectBar2 = _interopRequireDefault(_SelectBar);

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

var _SearchResultTableContainer2 = _interopRequireDefault(_SearchResultTableContainer);

var _configHelpers = require('../../helpers/configHelpers');

var _permissionHelpers = require('../../helpers/permissionHelpers');

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

var _SearchToRelateModal = require('../../../styles/cspace-ui/SearchToRelateModal.css');

var _SearchToRelateModal2 = _interopRequireDefault(_SearchToRelateModal);

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

const messages = (0, _reactIntl.defineMessages)({
  editSearch: {
    'id': 'searchToRelateModal.editSearch',
    'defaultMessage': 'Revise search'
  },
  label: {
    'id': 'searchToRelateModal.label',
    'defaultMessage': 'Relate'
  },
  relate: {
    'id': 'searchToRelateModal.relate',
    'defaultMessage': 'Relate selected'
  },
  relating: {
    'id': 'searchToRelateModal.relating',
    'defaultMessage': 'Relating...'
  }
});

const searchName = exports.searchName = 'searchToRelate';

const listType = 'common';
// FIXME: Make default page size configurable
const defaultPageSize = 20;

const isSingleSubject = subjects => Array.isArray(subjects) && subjects.length === 1;

const propTypes = {
  allowedServiceTypes: _propTypes2.default.arrayOf(_propTypes2.default.string),
  config: _propTypes2.default.object,
  intl: _reactIntl.intlShape,
  isOpen: _propTypes2.default.bool,
  keywordValue: _propTypes2.default.string,
  defaultRecordTypeValue: _propTypes2.default.string,
  recordTypeValue: _propTypes2.default.string,
  vocabularyValue: _propTypes2.default.string,
  advancedSearchCondition: _propTypes2.default.object,
  preferredPageSize: _propTypes2.default.number,
  perms: _propTypes2.default.instanceOf(_immutable2.default.Map),
  selectedItems: _propTypes2.default.instanceOf(_immutable2.default.Map),
  subjects: _propTypes2.default.oneOfType([_propTypes2.default.arrayOf(_propTypes2.default.shape({
    /* eslint-disable react/no-unused-prop-types */
    csid: _propTypes2.default.string,
    recordType: _propTypes2.default.string
    /* eslint-enable react/no-unused-prop-types */
  })), _propTypes2.default.func]),
  onAdvancedSearchConditionCommit: _propTypes2.default.func,
  onKeywordCommit: _propTypes2.default.func,
  onRecordTypeCommit: _propTypes2.default.func,
  onVocabularyCommit: _propTypes2.default.func,
  onCloseButtonClick: _propTypes2.default.func,
  onCancelButtonClick: _propTypes2.default.func,
  onItemSelectChange: _propTypes2.default.func,
  onRelationsCreated: _propTypes2.default.func,
  clearSearchResults: _propTypes2.default.func,
  createRelations: _propTypes2.default.func,
  parentSelector: _propTypes2.default.func,
  search: _propTypes2.default.func,
  setAllItemsSelected: _propTypes2.default.func,
  setPreferredPageSize: _propTypes2.default.func
};

const defaultProps = {
  selectedItems: _immutable2.default.Map()
};

class BaseSearchToRelateModal extends _react.Component {
  constructor() {
    super();

    this.shouldShowCheckbox = this.shouldShowCheckbox.bind(this);
    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.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
    };
  }

  componentWillReceiveProps(nextProps) {
    const isOpen = this.props.isOpen;
    const nextIsOpen = nextProps.isOpen;


    if (isOpen && !nextIsOpen) {
      // Closing.

      this.setState({
        isRelating: false,
        isSearchInitiated: false,
        pageNum: 0,
        sort: null
      });
    }
  }

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


    if (prevIsOpen && !isOpen) {
      // Closed.

      var _props = this.props;
      const clearSearchResults = _props.clearSearchResults,
            onRecordTypeCommit = _props.onRecordTypeCommit;


      if (clearSearchResults) {
        clearSearchResults(searchName);
      }

      if (onRecordTypeCommit) {
        onRecordTypeCommit('');
      }
    } else if (!prevIsOpen && isOpen) {
      // Opened.

      var _props2 = this.props;
      const defaultRecordTypeValue = _props2.defaultRecordTypeValue,
            onRecordTypeCommit = _props2.onRecordTypeCommit;


      if (onRecordTypeCommit) {
        onRecordTypeCommit(defaultRecordTypeValue);

        // TODO: If search to relate is ever used on authorities, need to set the default vocabulary
        // if this is an authority record type, and vocabularyValue is not provided.
      }
    }

    var _state = this.state;
    const isSearchInitiated = _state.isSearchInitiated,
          pageNum = _state.pageNum,
          sort = _state.sort;


    if (isSearchInitiated) {
      var _props3 = this.props;
      const recordTypeValue = _props3.recordTypeValue,
            vocabularyValue = _props3.vocabularyValue,
            advancedSearchCondition = _props3.advancedSearchCondition,
            preferredPageSize = _props3.preferredPageSize;
      const prevRecordTypeValue = prevProps.recordTypeValue,
            prevVocabularyValue = prevProps.vocabularyValue,
            prevAdvancedSearchCondition = prevProps.advancedSearchCondition,
            prevPreferredPageSize = prevProps.preferredPageSize;
      const prevPageNum = prevState.pageNum,
            prevSort = prevState.sort;


      if (recordTypeValue !== prevRecordTypeValue || vocabularyValue !== prevVocabularyValue || !(0, _isEqual2.default)(advancedSearchCondition, prevAdvancedSearchCondition) || preferredPageSize !== prevPreferredPageSize || pageNum !== prevPageNum || sort !== prevSort) {
        this.search();
      }
    }
  }

  getSearchDescriptor() {
    var _props4 = this.props;
    const config = _props4.config,
          recordType = _props4.recordTypeValue,
          vocabulary = _props4.vocabularyValue,
          keyword = _props4.keywordValue,
          advancedSearchCondition = _props4.advancedSearchCondition,
          preferredPageSize = _props4.preferredPageSize,
          subjects = _props4.subjects;
    var _state2 = this.state;
    const pageNum = _state2.pageNum,
          sort = _state2.sort;


    const pageSize = preferredPageSize || defaultPageSize;

    const searchQuery = {
      p: pageNum,
      size: pageSize
    };

    if (isSingleSubject(subjects)) {
      searchQuery.mkRtSbj = subjects[0].csid;
    }

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

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

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

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

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

    return _immutable2.default.fromJS({
      recordType,
      vocabulary,
      searchQuery
    });
  }

  relate() {
    var _props5 = this.props;
    const selectedItems = _props5.selectedItems,
          createRelations = _props5.createRelations,
          onRelationsCreated = _props5.onRelationsCreated;


    if (createRelations) {
      let subjects = this.props.subjects;


      if (typeof subjects === 'function') {
        subjects = subjects();
      }

      if (subjects && subjects.length > 0) {
        const searchDescriptor = this.getSearchDescriptor();

        this.setState({
          isRelating: true,
          isSearchInitiated: false
        });

        const objects = selectedItems.valueSeq().map(item => ({
          csid: item.get('csid'),
          recordType: searchDescriptor.get('recordType')
        })).toJS();

        Promise.all(subjects.map(subject => createRelations(subject, objects, 'affects'))).then(() => {
          if (onRelationsCreated) {
            onRelationsCreated();
          }
        });
      }
    }
  }

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


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

      search(config, searchName, searchDescriptor);

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

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


    if (isSearchInitiated) {
      this.relate();
    } else {
      this.search();
    }
  }

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


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

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


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

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


    if (clearSearchResults) {
      clearSearchResults(searchName);
    }

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

  handleFormSearch() {
    this.search();
  }

  handleCheckboxCommit(path, value) {
    const index = parseInt(path[0], 10);
    const checked = value;

    var _props7 = this.props;
    const config = _props7.config,
          onItemSelectChange = _props7.onItemSelectChange;


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

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

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

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


    let normalizedPageSize;

    if (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
    });
  }

  shouldShowCheckbox(item) {
    if (item.get('workflowState') === 'locked') {
      return false;
    }

    if (item.get('related') === 'true') {
      return false;
    }

    var _props8 = this.props;
    const config = _props8.config,
          perms = _props8.perms,
          subjects = _props8.subjects;


    if (isSingleSubject(subjects) && item.get('csid') === subjects[0].csid) {
      return false;
    }

    return (0, _permissionHelpers.canRelate)((0, _configHelpers.getRecordTypeNameByUri)(config, item.get('uri')), perms);
  }

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


      const itemCsid = rowData.get('csid');
      const selected = selectedItems ? selectedItems.has(itemCsid) : false;

      return _react2.default.createElement(_CheckboxInput2.default, {
        embedded: true,
        name: `${rowIndex}`,
        value: selected,
        onCommit: this.handleCheckboxCommit
      });
    }

    return null;
  }

  renderSearchForm() {
    var _props9 = this.props;
    const allowedServiceTypes = _props9.allowedServiceTypes,
          config = _props9.config,
          intl = _props9.intl,
          keywordValue = _props9.keywordValue,
          recordTypeValue = _props9.recordTypeValue,
          vocabularyValue = _props9.vocabularyValue,
          perms = _props9.perms,
          advancedSearchCondition = _props9.advancedSearchCondition,
          onAdvancedSearchConditionCommit = _props9.onAdvancedSearchConditionCommit,
          onKeywordCommit = _props9.onKeywordCommit,
          onRecordTypeCommit = _props9.onRecordTypeCommit,
          onVocabularyCommit = _props9.onVocabularyCommit;


    let recordTypeInputReadOnly = true;
    let recordTypeInputRootType;

    if (allowedServiceTypes) {
      // Allow the record type to be changed.

      recordTypeInputReadOnly = false;

      // Don't show the All Records option.

      recordTypeInputRootType = '';
    }

    return _react2.default.createElement(_SearchForm2.default, {
      config: config,
      intl: intl,
      recordTypeValue: recordTypeValue,
      vocabularyValue: vocabularyValue,
      keywordValue: keywordValue,
      advancedSearchCondition: advancedSearchCondition,
      perms: perms,
      recordTypeInputReadOnly: recordTypeInputReadOnly,
      recordTypeInputRootType: recordTypeInputRootType,
      recordTypeInputServiceTypes: allowedServiceTypes,
      onAdvancedSearchConditionCommit: onAdvancedSearchConditionCommit,
      onKeywordCommit: onKeywordCommit,
      onRecordTypeCommit: onRecordTypeCommit,
      onVocabularyCommit: onVocabularyCommit,
      onSearch: this.handleFormSearch
    });
  }

  renderEditSearchLink() {
    return _react2.default.createElement(
      'button',
      { onClick: this.handleEditSearchLinkClick },
      _react2.default.createElement(_reactIntl.FormattedMessage, messages.editSearch)
    );
  }

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


    if (searchError) {
      return null;
    }

    const searchDescriptor = this.getSearchDescriptor();

    return _react2.default.createElement(
      'header',
      null,
      _react2.default.createElement(_SearchResultSummary2.default, {
        config: config,
        listType: listType,
        searchDescriptor: searchDescriptor,
        searchError: searchError,
        searchResult: searchResult,
        renderEditLink: this.renderEditSearchLink,
        onPageSizeChange: this.handlePageSizeChange
      }),
      _react2.default.createElement(_SelectBar2.default, {
        config: config,
        listType: listType,
        searchDescriptor: searchDescriptor,
        searchName: searchName,
        searchResult: searchResult,
        selectedItems: selectedItems,
        setAllItemsSelected: setAllItemsSelected,
        showCheckboxFilter: this.shouldShowCheckbox
      })
    );
  }

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


    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, isNaN(totalItems) ? 0 : Math.ceil(totalItems / pageSize) - 1);

      return _react2.default.createElement(
        'footer',
        null,
        _react2.default.createElement(_Pager2.default, {
          currentPage: pageNum,
          lastPage: lastPage,
          pageSize: pageSize,
          onPageChange: this.handlePageChange,
          onPageSizeChange: this.handlePageSizeChange
        })
      );
    }

    return null;
  }

  renderSearchResultTable() {
    var _props11 = this.props;
    const config = _props11.config,
          recordTypeValue = _props11.recordTypeValue;


    const searchDescriptor = this.getSearchDescriptor();

    return _react2.default.createElement(_SearchResultTableContainer2.default, {
      config: config,
      linkItems: false,
      listType: listType,
      recordType: recordTypeValue,
      searchName: searchName,
      searchDescriptor: searchDescriptor,
      showCheckboxColumn: true,
      renderCheckbox: this.renderCheckbox,
      renderHeader: this.renderSearchResultTableHeader,
      renderFooter: this.renderSearchResultTableFooter,
      onSortChange: this.handleSortChange
    });
  }

  renderModalButtonBar() {
    const selectedItems = this.props.selectedItems;
    var _state3 = this.state;
    const isRelating = _state3.isRelating,
          isSearchInitiated = _state3.isSearchInitiated;


    const cancelButton = _react2.default.createElement(_CancelButton2.default, {
      disabled: isRelating,
      onClick: this.handleCancelButtonClick
    });

    let acceptButton;
    let backButton;

    if (isSearchInitiated) {
      acceptButton = _react2.default.createElement(_RelateButton2.default, {
        disabled: isRelating || !selectedItems || selectedItems.size < 1,
        label: _react2.default.createElement(_reactIntl.FormattedMessage, messages.relate),
        onClick: this.handleAcceptButtonClick
      });

      backButton = _react2.default.createElement(_BackButton2.default, {
        disabled: isRelating,
        label: _react2.default.createElement(_reactIntl.FormattedMessage, messages.editSearch),
        onClick: this.handleEditSearchLinkClick
      });
    } else {
      acceptButton = _react2.default.createElement(_SearchButton2.default, {
        disabled: isRelating,
        type: 'button',
        onClick: this.handleAcceptButtonClick
      });
    }

    return _react2.default.createElement(
      'div',
      null,
      cancelButton,
      backButton,
      acceptButton
    );
  }

  render() {
    var _props12 = this.props;
    const config = _props12.config,
          intl = _props12.intl,
          isOpen = _props12.isOpen,
          recordTypeValue = _props12.recordTypeValue,
          parentSelector = _props12.parentSelector;
    var _state4 = this.state;
    const isRelating = _state4.isRelating,
          isSearchInitiated = _state4.isSearchInitiated;


    let content;

    if (isRelating) {
      content = _react2.default.createElement(
        'p',
        null,
        _react2.default.createElement(_reactIntl.FormattedMessage, messages.relating)
      );
    } else if (isSearchInitiated) {
      content = this.renderSearchResultTable();
    } else {
      content = this.renderSearchForm();
    }

    const searchDescriptor = this.getSearchDescriptor();

    const title = _react2.default.createElement(_SearchToRelateTitleBar2.default, {
      config: config,
      isSearchInitiated: isSearchInitiated,
      recordType: recordTypeValue,
      searchDescriptor: searchDescriptor
    });

    return _react2.default.createElement(
      _cspaceLayout.Modal,
      {
        className: _SearchToRelateModal2.default.common,
        contentLabel: intl.formatMessage(messages.label),
        title: title,
        isOpen: isOpen,
        showCloseButton: !isRelating,
        closeButtonClassName: 'material-icons',
        closeButtonLabel: 'close',
        parentSelector: parentSelector,
        renderButtonBar: this.renderModalButtonBar,
        onCloseButtonClick: this.handleCloseButtonClick
      },
      content
    );
  }
}

exports.BaseSearchToRelateModal = BaseSearchToRelateModal;
BaseSearchToRelateModal.propTypes = propTypes;
BaseSearchToRelateModal.defaultProps = defaultProps;

exports.default = (0, _reactIntl.injectIntl)(BaseSearchToRelateModal);