import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
import _defineProperty from '@babel/runtime/helpers/defineProperty';
import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
import 'core-js/modules/es.symbol.js';
import 'core-js/modules/es.array.concat.js';
import 'core-js/modules/es.array.filter.js';
import 'core-js/modules/es.array.map.js';
import 'core-js/modules/es.object.get-own-property-descriptor.js';
import 'core-js/modules/es.object.get-own-property-descriptors.js';
import 'core-js/modules/es.object.keys.js';
import 'core-js/modules/es.object.to-string.js';
import 'core-js/modules/web.dom-collections.for-each.js';
import * as React from 'react';
import PropTypes from 'prop-types';
import Rule from './Rule.js';
import RuleBuilderHeader from './RuleBuilderHeader.js';
import { generateRuleGroup, addRule, filterRulesById, findRulePathById, getRuleByPath, updateRuleAtPath } from './utils.js';
import { RuleGroupPropType, RuleBuilderColumnsPropType } from './RuleBuilderPropTypes.js';

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; }
var propTypes = {
  /**
   * the rules passed into the component. The RuleBuilder is a controlled component, so
   * this works the same as passing defaultValue to a controlled input component.
   */
  defaultRules: RuleGroupPropType,
  /**
   * An array of columns of the table to be used in the column dropdown.
   * The id and name are required, but each column can also include an optional array
   * of operands (ie. `[{id: 'LT', name: 'Less than'}]`) or a renderField function to change
   * the input for that column. ie. `({value, onChange}) => <input type="date" defaultValue={value} onChange={(e) => onChange(e.target.value)} />`
   * the onChange event expects only one argument. The new value to be assigned to this rule's value property.
   */
  columns: RuleBuilderColumnsPropType.isRequired,
  /**
   * The onChange callback called on any updates to the RuleBuilder tree structure.
   * Example Structure:
   * {
   *   id: '14p5ho3pcu',
   *   groupLogic: 'ALL',
   *   rules: [
   *     {
   *       id: 'rsiru4rjba',
   *       columnId: 'column2',
   *       operand: 'EQ',
   *       value: '45',
   *     },
   *     {
   *       id: 'i34imt0geh',
   *       groupLogic: 'ANY',
   *       rules: [
   *         {
   *           id: 'ewc2z5kyfu',
   *           columnId: 'column2',
   *           operand: 'GTOET',
   *           value: '46',
   *         },
   *       ],
   *     }
   *   ]
   * }
   * @param {object} tree RuleBuilder Tree object
   */
  onChange: PropTypes.func,
  i18n: PropTypes.shape({
    addRule: PropTypes.string,
    addGroup: PropTypes.string
  }),
  testId: PropTypes.string
};
var defaultProps = {
  defaultRules: generateRuleGroup(),
  onChange: function onChange() {},
  i18n: {
    addRule: 'Add rule',
    addGroup: 'Add group'
  },
  testId: 'rule-builder-editor'
};
var RuleBuilderEditor = function RuleBuilderEditor(_ref) {
  var defaultRules = _ref.defaultRules,
    columns = _ref.columns,
    onChange = _ref.onChange,
    i18n = _ref.i18n,
    testId = _ref.testId;
  var _React$useState = React.useState(defaultRules),
    _React$useState2 = _slicedToArray(_React$useState, 2),
    tree = _React$useState2[0],
    setTree = _React$useState2[1];
  var mergedI18n = React.useMemo(function () {
    return _objectSpread(_objectSpread({}, defaultProps.i18n), i18n !== null && i18n !== void 0 ? i18n : {});
  }, [i18n]);
  var handleAddRule = React.useCallback(function (ruleId) {
    var isGroup = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
    return function () {
      var newTree = _objectSpread(_objectSpread({}, tree), {}, {
        rules: addRule(tree.rules, ruleId, isGroup)
      });
      setTree(newTree);
      onChange(newTree);
    };
  }, [onChange, tree]);
  var handleRemoveRule = React.useCallback(function (ruleId) {
    return function () {
      var newTree = _objectSpread(_objectSpread({}, tree), {}, {
        rules: filterRulesById(_toConsumableArray(tree.rules), ruleId)
      });
      setTree(newTree);
      onChange(newTree);
    };
  }, [onChange, tree]);
  var handleChange = React.useCallback(function (changed, isRoot) {
    var newTree;
    if (!isRoot) {
      var path = findRulePathById(tree.rules, changed.id);
      var rule = getRuleByPath(tree.rules, path);
      newTree = _objectSpread(_objectSpread({}, tree), {}, {
        rules: updateRuleAtPath(tree.rules, _objectSpread(_objectSpread({}, rule), changed), path)
      });
    } else {
      newTree = _objectSpread(_objectSpread({}, tree), changed);
    }
    setTree(newTree);
    onChange(newTree);
  }, [onChange, tree]);
  return /*#__PURE__*/React.createElement("div", {
    "data-testid": testId
  }, /*#__PURE__*/React.createElement(RuleBuilderHeader, {
    id: tree.id,
    groupLogic: tree.groupLogic,
    onAddRule: handleAddRule,
    onChange: handleChange,
    i18n: mergedI18n,
    testId: "".concat(testId, "-header")
  }), tree.rules.map(function (rule) {
    return /*#__PURE__*/React.createElement(Rule, {
      rule: _objectSpread({}, rule),
      key: rule.id,
      onAddRule: handleAddRule,
      onRemoveRule: handleRemoveRule,
      onChange: handleChange,
      columns: columns,
      i18n: mergedI18n,
      testId: "".concat(testId, "-rule-").concat(rule.id)
    });
  }));
};
RuleBuilderEditor.propTypes = propTypes;
RuleBuilderEditor.defaultProps = defaultProps;
RuleBuilderEditor.__docgenInfo = {
  "description": "",
  "methods": [],
  "displayName": "RuleBuilderEditor",
  "props": {
    "defaultRules": {
      "defaultValue": {
        "value": "generateRuleGroup()",
        "computed": true
      },
      "description": "the rules passed into the component. The RuleBuilder is a controlled component, so\nthis works the same as passing defaultValue to a controlled input component.",
      "type": {
        "name": "custom",
        "raw": "RuleGroupPropType"
      },
      "required": false
    },
    "onChange": {
      "defaultValue": {
        "value": "() => {}",
        "computed": false
      },
      "description": "The onChange callback called on any updates to the RuleBuilder tree structure.\nExample Structure:\n{\n  id: '14p5ho3pcu',\n  groupLogic: 'ALL',\n  rules: [\n    {\n      id: 'rsiru4rjba',\n      columnId: 'column2',\n      operand: 'EQ',\n      value: '45',\n    },\n    {\n      id: 'i34imt0geh',\n      groupLogic: 'ANY',\n      rules: [\n        {\n          id: 'ewc2z5kyfu',\n          columnId: 'column2',\n          operand: 'GTOET',\n          value: '46',\n        },\n      ],\n    }\n  ]\n}\n@param {object} tree RuleBuilder Tree object",
      "type": {
        "name": "func"
      },
      "required": false
    },
    "i18n": {
      "defaultValue": {
        "value": "{\n  addRule: 'Add rule',\n  addGroup: 'Add group',\n}",
        "computed": false
      },
      "description": "",
      "type": {
        "name": "shape",
        "value": {
          "addRule": {
            "name": "string",
            "required": false
          },
          "addGroup": {
            "name": "string",
            "required": false
          }
        }
      },
      "required": false
    },
    "testId": {
      "defaultValue": {
        "value": "'rule-builder-editor'",
        "computed": false
      },
      "description": "",
      "type": {
        "name": "string"
      },
      "required": false
    },
    "columns": {
      "description": "An array of columns of the table to be used in the column dropdown.\nThe id and name are required, but each column can also include an optional array\nof operands (ie. `[{id: 'LT', name: 'Less than'}]`) or a renderField function to change\nthe input for that column. ie. `({value, onChange}) => <input type=\"date\" defaultValue={value} onChange={(e) => onChange(e.target.value)} />`\nthe onChange event expects only one argument. The new value to be assigned to this rule's value property.",
      "type": {
        "name": "custom",
        "raw": "RuleBuilderColumnsPropType.isRequired"
      },
      "required": false
    }
  }
};
var RuleBuilderEditor$1 = RuleBuilderEditor;

export { RuleBuilderEditor$1 as default };
