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 _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, PureComponent } from "react";
import { Utils } from "@react-awesome-query-builder/core";
import PropTypes from "prop-types";
import treeStoreReducer from "../stores/tree";
import context from "../stores/context";
import { createStore } from "redux";
import { Provider } from "react-redux";
import * as actions from "../actions";
import { immutableEqual } from "../utils/stuff";
import { createValidationMemo } from "../utils/validationMemo";
import { liteShouldComponentUpdate, useOnPropsChanged } from "../utils/reactUtils";
import ConnectedQuery from "./Query";
var defaultRoot = Utils.DefaultUtils.defaultRoot;
var _Utils$ConfigUtils = Utils.ConfigUtils,
  createConfigMemo = _Utils$ConfigUtils.createConfigMemo,
  extendConfig = _Utils$ConfigUtils.extendConfig;
var QueryContainer = /*#__PURE__*/function (_Component) {
  function QueryContainer(props, context) {
    var _this$_reactInternals, _this$_reactInternals2;
    var _this;
    _classCallCheck(this, QueryContainer);
    _this = _callSuper(this, QueryContainer, [props, context]);
    _this.setLastTree = function (lastTree) {
      if (_this.prevTree) {
        _this.prevprevTree = _this.prevTree;
      }
      _this.prevTree = lastTree;
    };
    _this.getConfig = function () {
      return _this.config;
    };
    _this.shouldComponentUpdate = liteShouldComponentUpdate(_this, {
      value: function value(nextValue, prevValue) {
        return false;
      }
    });
    useOnPropsChanged(_this);
    var _createConfigMemo = createConfigMemo({
        reactIndex: (_this$_reactInternals = (_this$_reactInternals2 = _this._reactInternals) === null || _this$_reactInternals2 === void 0 ? void 0 : _this$_reactInternals2.index) !== null && _this$_reactInternals !== void 0 ? _this$_reactInternals : -1,
        maxSize: 2,
        // current and prev
        canCompile: true,
        extendConfig: extendConfig
      }),
      getExtendedConfig = _createConfigMemo.getExtendedConfig,
      getBasicConfig = _createConfigMemo.getBasicConfig,
      clearConfigMemo = _createConfigMemo.clearConfigMemo;
    _this.getMemoizedConfig = getExtendedConfig;
    _this.getBasicConfig = getBasicConfig;
    _this.clearConfigMemo = clearConfigMemo;
    _this.getMemoizedTree = createValidationMemo();
    var config = _this.getMemoizedConfig(props);
    var shouldCreateEmptyGroup = config.settings.shouldCreateEmptyGroup;
    var canAddDefaultRule = !shouldCreateEmptyGroup; // if prop `value` is not provided, can add default/empty rule?
    var emptyTree = defaultRoot(config, canAddDefaultRule);
    var sanitizeTree = !!props.value;
    var tree = props.value || emptyTree;
    var validatedTree = _this.getMemoizedTree(config, tree, undefined, sanitizeTree);
    var reducer = treeStoreReducer(config, validatedTree, _this.getMemoizedTree, _this.setLastTree, _this.getConfig);
    var store = createStore(reducer);
    _this.config = config;
    _this.state = {
      store: store
    };
    _this.QueryWrapper = function (pr) {
      return config.settings.renderProvider(pr, config.ctx);
    };
    return _this;
  }
  _inherits(QueryContainer, _Component);
  return _createClass(QueryContainer, [{
    key: "componentWillUnmount",
    value: function componentWillUnmount() {
      this.clearConfigMemo();
    }
  }, {
    key: "onPropsChanged",
    value: function onPropsChanged(nextProps) {
      // compare configs
      var prevProps = this.props;
      var oldConfig = this.config;
      var nextConfig = this.getMemoizedConfig(nextProps);
      var isConfigChanged = oldConfig !== nextConfig;

      // compare trees
      var storeValue = this.state.store.getState().tree;
      var isTreeChanged = !immutableEqual(nextProps.value, this.props.value) && !immutableEqual(nextProps.value, storeValue);
      var currentTree = isTreeChanged ? nextProps.value || defaultRoot(nextProps) : storeValue;
      var isTreeTrulyChanged = isTreeChanged && !immutableEqual(nextProps.value, this.prevTree) && !immutableEqual(nextProps.value, this.prevprevTree);
      this.sanitizeTree = isTreeTrulyChanged || isConfigChanged;
      var canUseOldConfig = isConfigChanged && !isTreeChanged;
      if (isConfigChanged) {
        if (prevProps.settings.renderProvider !== nextProps.settings.renderProvider) {
          this.QueryWrapper = function (props) {
            return nextConfig.settings.renderProvider(props, nextConfig.ctx);
          };
        }
        this.config = nextConfig;
      }
      if (isTreeChanged || isConfigChanged) {
        var validatedTree = this.getMemoizedTree(nextConfig, currentTree, canUseOldConfig ? oldConfig : undefined, this.sanitizeTree);
        //return Promise.resolve().then(() => {
        this.state.store.dispatch(actions.tree.setTree(nextConfig, validatedTree));
        //});
      }
    }
  }, {
    key: "render",
    value: function render() {
      // `get_children` is deprecated!
      var _this$props = this.props,
        renderBuilder = _this$props.renderBuilder,
        get_children = _this$props.get_children,
        onChange = _this$props.onChange,
        onInit = _this$props.onInit;
      var store = this.state.store;
      var config = this.config;
      var QueryWrapper = this.QueryWrapper;
      return /*#__PURE__*/React.createElement(QueryWrapper, {
        config: config
      }, /*#__PURE__*/React.createElement(Provider, {
        store: store,
        context: context
      }, /*#__PURE__*/React.createElement(ConnectedQuery, {
        config: config,
        getMemoizedTree: this.getMemoizedTree,
        getBasicConfig: this.getBasicConfig,
        sanitizeTree: this.sanitizeTree,
        onChange: onChange,
        onInit: onInit,
        renderBuilder: renderBuilder || get_children
      })));
    }
  }]);
}(Component);
QueryContainer.propTypes = {
  //config
  conjunctions: PropTypes.object.isRequired,
  fields: PropTypes.object.isRequired,
  types: PropTypes.object.isRequired,
  operators: PropTypes.object.isRequired,
  widgets: PropTypes.object.isRequired,
  settings: PropTypes.object.isRequired,
  ctx: PropTypes.object.isRequired,
  onChange: PropTypes.func,
  onInit: PropTypes.func,
  renderBuilder: PropTypes.func,
  value: PropTypes.any //instanceOf(Immutable.Map)
};
export { QueryContainer as default };