import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { defineMessages, FormattedMessage } from 'react-intl';
import Immutable from 'immutable';
import { Modal } from 'cspace-layout';
import { getRecordTypeNameByUri } from '../../helpers/configHelpers';
import { canRelate } from '../../helpers/permissionHelpers';
import SearchToSelectModalContainer from '../../containers/search/SearchToSelectModalContainer';
import relateButtonStyles from '../../../styles/cspace-ui/RelateButton.css';

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

const messages = defineMessages({
  label: {
    id: 'searchToRelateModal.label',
    defaultMessage: 'Relate records',
  },
  accept: {
    id: 'searchToRelateModal.accept',
    description: 'Label of the accept selection button in the search to relate modal.',
    defaultMessage: 'Relate selected',
  },
  relating: {
    id: 'searchToRelateModal.relating',
    defaultMessage: 'Relating…',
  },
  title: {
    id: 'searchToRelateModal.title',
    defaultMessage: 'Relate {typeName} {query}',
  },
  errorTitle: {
    id: 'searchToRelateModal.errorTitle',
    defaultMessage: 'Permission Denied',
  },
});

const errorMessages = defineMessages({
  locked: {
    id: 'searchToRelateModal.error.locked',
    defaultMessage: 'Locked records are selected. Relations cannot be made to locked records.',
  },
  notPermitted: {
    id: 'searchToRelateModal.error.notPermitted',
    defaultMessage: '{selectedCount, plural, one {{name} record is} other {{name} records are}} selected. You are not permitted to create relations to {collectionName}.',
  },
});

const renderRelatingMessage = () => (
  <p><FormattedMessage {...messages.relating} /></p>
);

const propTypes = {
  config: PropTypes.shape({
    recordTypes: PropTypes.object,
  }),
  error: PropTypes.shape({
    code: PropTypes.string,
    values: PropTypes.object,
  }),
  isOpen: PropTypes.bool,
  perms: PropTypes.instanceOf(Immutable.Map),
  subjects: PropTypes.oneOfType([
    PropTypes.arrayOf(
      PropTypes.shape({
        /* eslint-disable react/no-unused-prop-types */
        csid: PropTypes.string,
        recordType: PropTypes.string,
        /* eslint-enable react/no-unused-prop-types */
      }),
    ),
    PropTypes.func,
  ]),
  createRelations: PropTypes.func,
  onCancelButtonClick: PropTypes.func,
  onCloseButtonClick: PropTypes.func,
  onRelationsCreated: PropTypes.func,
};

export default class SearchToRelateModal extends Component {
  constructor(props) {
    super(props);

    this.customizeSearchDescriptor = this.customizeSearchDescriptor.bind(this);
    this.handleAccept = this.handleAccept.bind(this);
    this.shouldShowCheckbox = this.shouldShowCheckbox.bind(this);
  }

  handleAccept(selectedItems, searchDescriptor) {
    return this.relate(selectedItems, searchDescriptor);
  }

  customizeSearchDescriptor(searchDescriptor) {
    const {
      subjects,
    } = this.props;

    if (isSingleSubject(subjects)) {
      return searchDescriptor.setIn(['searchQuery', 'mkRtSbj'], subjects[0].csid);
    }

    return searchDescriptor;
  }

  relate(selectedItems, searchDescriptor) {
    const {
      createRelations,
      onRelationsCreated,
    } = this.props;

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

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

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

        return createRelations(subjects, objects, 'affects')
          .then(() => {
            if (onRelationsCreated) {
              onRelationsCreated();
            }
          });
      }
    }

    return undefined;
  }

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

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

    const {
      config,
      perms,
      subjects,
    } = this.props;

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

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

  render() {
    const {
      error,
      subjects,
      createRelations,
      onRelationsCreated,
      ...remainingProps
    } = this.props;

    const {
      isOpen,
      onCancelButtonClick,
      onCloseButtonClick,
    } = remainingProps;

    if (isOpen && error) {
      return (
        <Modal
          isOpen
          showCancelButton={false}
          title={<h1><FormattedMessage {...messages.errorTitle} /></h1>}
          onAcceptButtonClick={onCancelButtonClick}
          onCloseButtonClick={onCloseButtonClick}
        >
          <FormattedMessage {...errorMessages[error.code]} values={error.values || {}} />
        </Modal>
      );
    }

    return (
      <SearchToSelectModalContainer
        acceptButtonClassName={relateButtonStyles.common}
        acceptButtonLabel={<FormattedMessage {...messages.accept} />}
        customizeSearchDescriptor={this.customizeSearchDescriptor}
        titleMessage={messages.title}
        renderAcceptPending={renderRelatingMessage}
        shouldShowCheckbox={this.shouldShowCheckbox}
        onAccept={this.handleAccept}
        {...remainingProps}
      />
    );
  }
}

SearchToRelateModal.propTypes = propTypes;
