import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
import _extends from "@babel/runtime/helpers/extends";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
import _createClass from "@babel/runtime/helpers/createClass";
import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
import _inherits from "@babel/runtime/helpers/inherits";
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
import React, { Component } from "react";
import { Utils } from "@react-awesome-query-builder/core";
import PropTypes from "prop-types";
import RuleContainer from "../containers/RuleContainer";
import Draggable from "../containers/Draggable";
import OperatorWrapper from "../rule/OperatorWrapper";
import FieldWrapper from "../rule/FieldWrapper";
import Widget from "../rule/Widget";
import OperatorOptions from "../rule/OperatorOptions";
import { useOnPropsChanged } from "../../utils/reactUtils";
import { Col, dummyFn, WithConfirmFn, getRenderFromConfig } from "../utils";
import classNames from "classnames";
var _Utils$ConfigUtils = Utils.ConfigUtils,
  getFieldConfig = _Utils$ConfigUtils.getFieldConfig,
  getOperatorConfig = _Utils$ConfigUtils.getOperatorConfig,
  getFieldWidgetConfig = _Utils$ConfigUtils.getFieldWidgetConfig,
  getFieldId = _Utils$ConfigUtils.getFieldId;
var isEmptyRuleProperties = Utils.RuleUtils.isEmptyRuleProperties;
var Rule = /*#__PURE__*/function (_Component) {
  function Rule(props) {
    var _this;
    _classCallCheck(this, Rule);
    _this = _callSuper(this, Rule, [props]);
    useOnPropsChanged(_this);
    _this.removeSelf = _this.removeSelf.bind(_this);
    _this.setLock = _this.setLock.bind(_this);
    _this.onPropsChanged(props);
    return _this;
  }
  _inherits(Rule, _Component);
  return _createClass(Rule, [{
    key: "onPropsChanged",
    value: function onPropsChanged(nextProps) {
      var _this2 = this;
      var prevProps = this.props;
      var configChanged = !this.Icon || (prevProps === null || prevProps === void 0 ? void 0 : prevProps.config) !== (nextProps === null || nextProps === void 0 ? void 0 : nextProps.config);
      var keysForMeta = ["selectedField", "selectedFieldSrc", "selectedFieldType", "selectedOperator", "config", "reordableNodesCnt", "isLocked", "parentField", "parentFieldCanReorder"];
      var needUpdateMeta = !this.meta || keysForMeta.map(function (k) {
        return nextProps[k] !== prevProps[k];
      }).filter(function (ch) {
        return ch;
      }).length > 0;
      if (needUpdateMeta) {
        this.meta = this.getMeta(nextProps);
      }
      if (configChanged) {
        var config = nextProps.config;
        var _config$settings = config.settings,
          renderIcon = _config$settings.renderIcon,
          renderButton = _config$settings.renderButton,
          renderButtonGroup = _config$settings.renderButtonGroup,
          renderSwitch = _config$settings.renderSwitch,
          renderBeforeWidget = _config$settings.renderBeforeWidget,
          renderAfterWidget = _config$settings.renderAfterWidget,
          renderRuleError = _config$settings.renderRuleError;
        this.Icon = getRenderFromConfig(config, renderIcon);
        this.Btn = getRenderFromConfig(config, renderButton);
        this.BtnGrp = getRenderFromConfig(config, renderButtonGroup);
        this.Switch = getRenderFromConfig(config, renderSwitch);
        this.BeforeWidget = getRenderFromConfig(config, renderBeforeWidget);
        this.AfterWidget = getRenderFromConfig(config, renderAfterWidget);
        this.RuleError = getRenderFromConfig(config, renderRuleError);
      }
      this.doRemove = function () {
        _this2.props.removeSelf();
      };
    }
  }, {
    key: "getMeta",
    value: function getMeta(_ref) {
      var selectedField = _ref.selectedField,
        selectedFieldType = _ref.selectedFieldType,
        selectedOperator = _ref.selectedOperator,
        config = _ref.config,
        reordableNodesCnt = _ref.reordableNodesCnt,
        isLocked = _ref.isLocked,
        parentField = _ref.parentField,
        parentFieldCanReorder = _ref.parentFieldCanReorder;
      var keepInputOnChangeFieldSrc = config.settings.keepInputOnChangeFieldSrc;
      var selectedFieldId = getFieldId(selectedField, config);
      var selectedFieldConfig = getFieldConfig(config, selectedField);
      var isSelectedGroup = selectedFieldConfig && selectedFieldConfig.type === "!struct";
      var isOkWithoutField = keepInputOnChangeFieldSrc && selectedFieldType;
      var isFieldSelected = !!selectedField || isOkWithoutField;
      var isFieldAndOpSelected = isFieldSelected && selectedOperator;
      var selectedOperatorConfig = getOperatorConfig(config, selectedOperator, selectedField);
      var selectedOperatorHasOptions = selectedOperatorConfig && selectedOperatorConfig.options != null;
      var selectedFieldWidgetConfig = getFieldWidgetConfig(config, selectedField, selectedOperator, null, null) || {};
      var hideOperator = selectedFieldWidgetConfig.hideOperator;
      var showDragIcon = config.settings.canReorder && reordableNodesCnt > 1 && !isLocked;
      if (parentField) {
        showDragIcon = showDragIcon && parentFieldCanReorder;
      }
      var showOperator = isFieldSelected && !hideOperator;
      var showOperatorLabel = isFieldSelected && hideOperator && selectedFieldWidgetConfig.operatorInlineLabel;
      var showWidget = isFieldAndOpSelected && !isSelectedGroup;
      var showOperatorOptions = isFieldAndOpSelected && selectedOperatorHasOptions;
      return {
        selectedFieldId: selectedFieldId,
        selectedFieldWidgetConfig: selectedFieldWidgetConfig,
        showDragIcon: showDragIcon,
        showOperator: showOperator,
        showOperatorLabel: showOperatorLabel,
        showWidget: showWidget,
        showOperatorOptions: showOperatorOptions
      };
    }
  }, {
    key: "setLock",
    value: function setLock(lock) {
      this.props.setLock(lock);
    }
  }, {
    key: "removeSelf",
    value: function removeSelf() {
      var _this$props = this.props,
        confirmFn = _this$props.confirmFn,
        config = _this$props.config;
      var _config$settings2 = config.settings,
        renderConfirm = _config$settings2.renderConfirm,
        confirmOptions = _config$settings2.removeRuleConfirmOptions;
      if (confirmOptions && !this.isEmptyCurrentRule()) {
        renderConfirm.call(config.ctx, _objectSpread(_objectSpread({}, confirmOptions), {}, {
          onOk: this.doRemove,
          onCancel: null,
          confirmFn: confirmFn
        }), config.ctx);
      } else {
        this.doRemove();
      }
    }
  }, {
    key: "_buildWidgetProps",
    value: function _buildWidgetProps(_ref2, _ref3) {
      var selectedField = _ref2.selectedField,
        selectedFieldSrc = _ref2.selectedFieldSrc,
        selectedFieldType = _ref2.selectedFieldType,
        selectedOperator = _ref2.selectedOperator,
        operatorOptions = _ref2.operatorOptions,
        value = _ref2.value,
        valueType = _ref2.valueType,
        valueSrc = _ref2.valueSrc,
        asyncListValues = _ref2.asyncListValues,
        valueError = _ref2.valueError,
        fieldError = _ref2.fieldError,
        parentField = _ref2.parentField;
      var selectedFieldId = _ref3.selectedFieldId;
      return {
        field: selectedField,
        fieldSrc: selectedFieldSrc,
        fieldType: selectedFieldType,
        fieldId: selectedFieldId,
        operator: selectedOperator,
        operatorOptions: operatorOptions,
        value: value,
        valueType: valueType,
        valueSrc: valueSrc,
        asyncListValues: asyncListValues,
        valueError: valueError,
        fieldError: fieldError,
        parentField: parentField
      };
    }
  }, {
    key: "isEmptyCurrentRule",
    value: function isEmptyCurrentRule() {
      var config = this.props.config;
      var ruleData = this._buildWidgetProps(this.props, this.meta);
      return isEmptyRuleProperties(ruleData, config);
    }
  }, {
    key: "renderField",
    value: function renderField() {
      var _this$props2 = this.props,
        config = _this$props2.config,
        isLocked = _this$props2.isLocked,
        parentField = _this$props2.parentField,
        groupId = _this$props2.groupId,
        id = _this$props2.id,
        selectedFieldSrc = _this$props2.selectedFieldSrc,
        selectedField = _this$props2.selectedField,
        selectedFieldType = _this$props2.selectedFieldType,
        setField = _this$props2.setField,
        setFuncValue = _this$props2.setFuncValue,
        setFieldSrc = _this$props2.setFieldSrc,
        fieldError = _this$props2.fieldError;
      var immutableFieldsMode = config.settings.immutableFieldsMode;
      var selectedFieldId = this.meta.selectedFieldId;
      // tip: don't allow function inside !group (yet)

      return /*#__PURE__*/React.createElement(FieldWrapper, {
        key: "field",
        classname: classNames(selectedFieldSrc == "func" ? "rule--field--func" : "rule--field"),
        config: config,
        canSelectFieldSource: !parentField,
        selectedField: selectedField,
        selectedFieldSrc: selectedFieldSrc,
        selectedFieldType: selectedFieldType,
        selectedFieldId: selectedFieldId,
        fieldError: fieldError,
        setField: !immutableFieldsMode ? setField : dummyFn,
        setFuncValue: !immutableFieldsMode ? setFuncValue : dummyFn,
        setFieldSrc: !immutableFieldsMode ? setFieldSrc : dummyFn,
        parentField: parentField,
        readonly: immutableFieldsMode || isLocked,
        id: id,
        groupId: groupId
      });
    }
  }, {
    key: "renderOperator",
    value: function renderOperator() {
      var _this$props3 = this.props,
        config = _this$props3.config,
        isLocked = _this$props3.isLocked;
      var _this$meta = this.meta,
        selectedFieldId = _this$meta.selectedFieldId,
        selectedFieldWidgetConfig = _this$meta.selectedFieldWidgetConfig,
        showOperator = _this$meta.showOperator,
        showOperatorLabel = _this$meta.showOperatorLabel;
      var immutableOpsMode = config.settings.immutableOpsMode;
      return /*#__PURE__*/React.createElement(OperatorWrapper, {
        key: "operator",
        config: config,
        selectedField: this.props.selectedField,
        selectedFieldSrc: this.props.selectedFieldSrc,
        selectedFieldType: this.props.selectedFieldType,
        selectedFieldId: selectedFieldId,
        selectedOperator: this.props.selectedOperator,
        setOperator: !immutableOpsMode ? this.props.setOperator : dummyFn,
        showOperator: showOperator,
        showOperatorLabel: showOperatorLabel,
        selectedFieldWidgetConfig: selectedFieldWidgetConfig,
        readonly: immutableOpsMode || isLocked,
        id: this.props.id,
        groupId: this.props.groupId
      });
    }
  }, {
    key: "renderWidget",
    value: function renderWidget() {
      var _this$props4 = this.props,
        config = _this$props4.config,
        isLocked = _this$props4.isLocked;
      var showWidget = this.meta.showWidget;
      var immutableValuesMode = config.settings.immutableValuesMode;
      if (!showWidget) return null;
      var widget = /*#__PURE__*/React.createElement(Widget, _extends({
        key: "values"
      }, this._buildWidgetProps(this.props, this.meta), {
        config: config,
        setValue: !immutableValuesMode ? this.props.setValue : dummyFn,
        setValueSrc: !immutableValuesMode ? this.props.setValueSrc : dummyFn,
        setFuncValue: !immutableValuesMode ? this.props.setFuncValue : dummyFn,
        readonly: immutableValuesMode || isLocked,
        id: this.props.id,
        groupId: this.props.groupId
      }));
      return /*#__PURE__*/React.createElement(Col, {
        key: "widget-for-" + this.props.selectedOperator,
        className: "rule--value"
      }, widget);
    }
  }, {
    key: "renderOperatorOptions",
    value: function renderOperatorOptions() {
      var config = this.props.config;
      var showOperatorOptions = this.meta.showOperatorOptions;
      var _config$settings3 = config.settings,
        immutableOpsMode = _config$settings3.immutableOpsMode,
        immutableValuesMode = _config$settings3.immutableValuesMode;
      if (!showOperatorOptions) return null;
      var opOpts = /*#__PURE__*/React.createElement(OperatorOptions, {
        key: "operatorOptions",
        selectedField: this.props.selectedField,
        selectedOperator: this.props.selectedOperator,
        operatorOptions: this.props.operatorOptions,
        setOperatorOption: !immutableOpsMode ? this.props.setOperatorOption : dummyFn,
        config: config,
        readonly: immutableValuesMode
      });
      return /*#__PURE__*/React.createElement(Col, {
        key: "op-options-for-" + this.props.selectedOperator,
        className: "rule--operator-options"
      }, opOpts);
    }
  }, {
    key: "renderBeforeWidget",
    value: function renderBeforeWidget() {
      var BeforeWidget = this.BeforeWidget;
      if (!BeforeWidget) return null;
      return /*#__PURE__*/React.createElement(Col, {
        key: "before-widget-for-" + this.props.selectedOperator,
        className: "rule--before-widget"
      }, /*#__PURE__*/React.createElement(BeforeWidget, this.props));
    }
  }, {
    key: "renderAfterWidget",
    value: function renderAfterWidget() {
      var AfterWidget = this.AfterWidget;
      if (!AfterWidget) return null;
      return /*#__PURE__*/React.createElement(Col, {
        key: "after-widget-for-" + this.props.selectedOperator,
        className: "rule--after-widget"
      }, /*#__PURE__*/React.createElement(AfterWidget, this.props));
    }
  }, {
    key: "renderError",
    value: function renderError() {
      var _this$props5 = this.props,
        config = _this$props5.config,
        valueError = _this$props5.valueError,
        fieldError = _this$props5.fieldError;
      var showErrorMessage = config.settings.showErrorMessage;
      var RuleError = this.RuleError;
      var oneError = [fieldError].concat(_toConsumableArray((valueError === null || valueError === void 0 ? void 0 : valueError.toArray()) || [])).filter(function (e) {
        return !!e;
      }).shift() || null;
      return showErrorMessage && oneError && /*#__PURE__*/React.createElement("div", {
        className: "rule--error"
      }, RuleError ? /*#__PURE__*/React.createElement(RuleError, {
        error: oneError
      }) : oneError);
    }
  }, {
    key: "renderDrag",
    value: function renderDrag() {
      var handleDraggerMouseDown = this.props.handleDraggerMouseDown;
      var showDragIcon = this.meta.showDragIcon;
      var Icon = this.Icon;
      var icon = /*#__PURE__*/React.createElement(Icon, {
        type: "drag"
      });
      return showDragIcon && /*#__PURE__*/React.createElement("div", {
        key: "rule-drag-icon",
        onMouseDown: handleDraggerMouseDown,
        className: "qb-drag-handler rule--drag-handler"
      }, icon);
    }
  }, {
    key: "renderDel",
    value: function renderDel() {
      var _this$props6 = this.props,
        config = _this$props6.config,
        isLocked = _this$props6.isLocked;
      var _config$settings4 = config.settings,
        deleteLabel = _config$settings4.deleteLabel,
        immutableGroupsMode = _config$settings4.immutableGroupsMode,
        canDeleteLocked = _config$settings4.canDeleteLocked;
      var Icon = this.Icon;
      var Btn = this.Btn;
      return !immutableGroupsMode && (!isLocked || isLocked && canDeleteLocked) && /*#__PURE__*/React.createElement(Btn, {
        key: "rule-del",
        type: "delRule",
        onClick: this.removeSelf,
        label: deleteLabel,
        config: config,
        renderIcon: Icon
      });
    }
  }, {
    key: "renderLock",
    value: function renderLock() {
      var _this$props7 = this.props,
        config = _this$props7.config,
        isLocked = _this$props7.isLocked,
        isTrueLocked = _this$props7.isTrueLocked,
        id = _this$props7.id;
      var _config$settings5 = config.settings,
        lockLabel = _config$settings5.lockLabel,
        lockedLabel = _config$settings5.lockedLabel,
        showLock = _config$settings5.showLock;
      var Switch = this.Switch;
      return showLock && !(isLocked && !isTrueLocked) && /*#__PURE__*/React.createElement(Switch, {
        key: "rule-lock",
        type: "lock",
        id: id,
        value: isLocked,
        setValue: this.setLock,
        label: lockLabel,
        checkedLabel: lockedLabel,
        hideLabel: true,
        config: config
      });
    }
  }, {
    key: "render",
    value: function render() {
      var _this$meta2 = this.meta,
        showOperatorOptions = _this$meta2.showOperatorOptions,
        selectedFieldWidgetConfig = _this$meta2.selectedFieldWidgetConfig;
      var _this$props8 = this.props,
        valueSrc = _this$props8.valueSrc,
        value = _this$props8.value,
        config = _this$props8.config;
      var canShrinkValue = (valueSrc === null || valueSrc === void 0 ? void 0 : valueSrc.first()) == "value" && !showOperatorOptions && value.size == 1 && selectedFieldWidgetConfig.fullWidth;
      var BtnGrp = this.BtnGrp;
      var parts = [this.renderField(), this.renderOperator(), this.renderBeforeWidget(), this.renderWidget(), this.renderAfterWidget(), this.renderOperatorOptions()];
      var body = /*#__PURE__*/React.createElement("div", {
        key: "rule-body",
        className: classNames("rule--body", canShrinkValue && "can--shrink--value")
      }, parts);
      var error = this.renderError();
      var drag = this.renderDrag();
      var lock = this.renderLock();
      var del = this.renderDel();
      return /*#__PURE__*/React.createElement(React.Fragment, null, drag, /*#__PURE__*/React.createElement("div", {
        key: "rule-body-wrapper",
        className: "rule--body--wrapper"
      }, body, error), /*#__PURE__*/React.createElement("div", {
        key: "rule-header-wrapper",
        className: "rule--header"
      }, /*#__PURE__*/React.createElement(BtnGrp, {
        key: "rule-header-group",
        config: config
      }, lock, del)));
    }
  }]);
}(Component);
Rule.propTypes = {
  id: PropTypes.string.isRequired,
  groupId: PropTypes.string,
  selectedField: PropTypes.any,
  selectedFieldSrc: PropTypes.string,
  selectedFieldType: PropTypes.string,
  selectedOperator: PropTypes.string,
  operatorOptions: PropTypes.object,
  config: PropTypes.object.isRequired,
  value: PropTypes.any,
  //depends on widget
  valueSrc: PropTypes.any,
  valueType: PropTypes.any,
  asyncListValues: PropTypes.array,
  isDraggingMe: PropTypes.bool,
  isDraggingTempo: PropTypes.bool,
  parentField: PropTypes.string,
  //from RuleGroup
  valueError: PropTypes.any,
  fieldError: PropTypes.string,
  isLocked: PropTypes.bool,
  isTrueLocked: PropTypes.bool,
  //path: PropTypes.instanceOf(Immutable.List),
  //actions
  handleDraggerMouseDown: PropTypes.func,
  setField: PropTypes.func,
  setFieldSrc: PropTypes.func,
  setOperator: PropTypes.func,
  setOperatorOption: PropTypes.func,
  setLock: PropTypes.func,
  removeSelf: PropTypes.func,
  setValue: PropTypes.func,
  setValueSrc: PropTypes.func,
  setFuncValue: PropTypes.func,
  reordableNodesCnt: PropTypes.number,
  totalRulesCnt: PropTypes.number,
  parentReordableNodesCnt: PropTypes.number,
  parentFieldCanReorder: PropTypes.bool
};
export default RuleContainer(Draggable("rule")(WithConfirmFn(Rule)));