"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 _immutable = _interopRequireDefault(require("immutable"));

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

var _SearchConditionInput = _interopRequireDefault(require("./input/SearchConditionInput"));

var _PanelContainer = require("../../containers/layout/PanelContainer");

var _searchOperators = require("../../constants/searchOperators");

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

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }

const messages = (0, _reactIntl.defineMessages)({
  title: {
    "id": "advancedSearchBuilder.title",
    "defaultMessage": "Advanced Search"
  }
});

const findAdvancedSearchClause = (searchClauses, clause) => {
  let index;
  index = searchClauses.findKey(candidateClause => candidateClause.get('path') === clause.get('path') && candidateClause.get('op') === clause.get('op'));

  if (typeof index === 'undefined') {
    if (clause.get('op') === _searchOperators.OP_GTE || clause.get('op') === _searchOperators.OP_LTE) {
      // A one-sided range search might have been converted to a gte/lte search.
      index = searchClauses.findKey(candidateClause => candidateClause.get('path') === clause.get('path') && candidateClause.get('op') === _searchOperators.OP_RANGE);
    }
  }

  return index;
};

const propTypes = {
  condition: _propTypes.default.instanceOf(_immutable.default.Map),
  config: _propTypes.default.object,
  inline: _propTypes.default.bool,
  preferredBooleanOp: _propTypes.default.string,
  readOnly: _propTypes.default.bool,
  recordType: _propTypes.default.string,
  onConditionCommit: _propTypes.default.func
};
const childContextTypes = {
  recordType: _propTypes.default.string
};

class AdvancedSearchBuilder extends _react.Component {
  getChildContext() {
    const {
      recordType
    } = this.props;
    return {
      recordType
    };
  }

  componentDidMount() {
    this.normalizeCondition();
  }

  componentDidUpdate() {
    this.normalizeCondition();
  }

  normalizeCondition() {
    const {
      condition,
      config,
      preferredBooleanOp,
      recordType,
      onConditionCommit
    } = this.props; // FIXME: Uncomment this once conditions may be added by the end user.
    // if (!condition && onConditionCommit) {
    //   const defaultCondition = get(config, ['recordTypes', recordType, 'advancedSearch']);
    //
    //   if (defaultCondition) {
    //     onConditionCommit(Immutable.fromJS(defaultCondition));
    //   }
    // }
    // FIXME: There will be no need for this once conditions may be added by the end user.
    // For now do a quick and dirty merge of the (possibly normalized) condition into the
    // default, so that fields aren't unrecoverable after normalization.

    if (onConditionCommit) {
      const defaultCondition = _immutable.default.fromJS((0, _get.default)(config, ['recordTypes', recordType, 'advancedSearch']));

      const op = condition && condition.get('op');

      if (preferredBooleanOp && (op === _searchOperators.OP_AND || op === _searchOperators.OP_OR) && op !== preferredBooleanOp) {
        onConditionCommit(condition.set('op', preferredBooleanOp));
      } else if (defaultCondition && condition) {
        if (op !== defaultCondition.get('op') || !_immutable.default.List.isList(condition.get('value')) || condition.get('value').size !== defaultCondition.get('value').size) {
          let mergedCondition = defaultCondition;
          let clauses;

          if (op === _searchOperators.OP_AND || op === _searchOperators.OP_OR) {
            mergedCondition = mergedCondition.set('op', op);
            clauses = condition.get('value');
          } else {
            if (preferredBooleanOp) {
              mergedCondition = mergedCondition.set('op', preferredBooleanOp);
            }

            clauses = _immutable.default.List([condition]);
          }

          const targetClauses = mergedCondition.get('value');
          clauses.forEach(clause => {
            const index = findAdvancedSearchClause(targetClauses, clause);

            if (typeof index !== 'undefined') {
              const targetClause = targetClauses.get(index);
              let value = clause.get('value');

              if (targetClause.get('op') === _searchOperators.OP_RANGE && !_immutable.default.List.isList(value)) {
                value = clause.get('op') === _searchOperators.OP_GTE ? _immutable.default.List([value]) : _immutable.default.List([undefined, value]);
              }

              mergedCondition = mergedCondition.setIn(['value', index, 'value'], value);
            }
          });

          if (!mergedCondition.equals(condition)) {
            onConditionCommit(mergedCondition);
          }
        }
      } else if (defaultCondition) {
        onConditionCommit(preferredBooleanOp ? defaultCondition.set('op', preferredBooleanOp) : defaultCondition);
      }
    }
  }

  render() {
    const {
      condition,
      config,
      inline,
      readOnly,
      recordType,
      onConditionCommit
    } = this.props;

    if (!condition) {
      return null;
    }

    const fieldDescriptor = (0, _get.default)(config, ['recordTypes', recordType, 'fields']);

    const searchConditionInput = _react.default.createElement(_SearchConditionInput.default, {
      condition: condition,
      fields: fieldDescriptor,
      inline: inline,
      readOnly: readOnly,
      onCommit: onConditionCommit
    });

    if (inline) {
      return searchConditionInput;
    }

    const panelHeader = _react.default.createElement("h3", null, _react.default.createElement(_reactIntl.FormattedMessage, messages.title));

    return _react.default.createElement(_PanelContainer.ConnectedPanel, {
      collapsible: true,
      header: panelHeader,
      name: "advancedSearch",
      recordType: recordType
    }, searchConditionInput);
  }

}

exports.default = AdvancedSearchBuilder;
AdvancedSearchBuilder.propTypes = propTypes;
AdvancedSearchBuilder.childContextTypes = childContextTypes;