"use strict";

var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
exports.stringify = stringify;
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _warning = _interopRequireDefault(require("rc-util/lib/warning"));
var _react = require("react");
var _FieldContext = _interopRequireWildcard(require("./FieldContext"));
var _typeUtil = require("./utils/typeUtil");
var _valueUtil = require("./utils/valueUtil");
function stringify(value) {
  try {
    return JSON.stringify(value);
  } catch (err) {
    return Math.random();
  }
}
var useWatchWarning = process.env.NODE_ENV !== 'production' ? function (namePath) {
  var fullyStr = namePath.join('__RC_FIELD_FORM_SPLIT__');
  var nameStrRef = (0, _react.useRef)(fullyStr);
  (0, _warning.default)(nameStrRef.current === fullyStr, '`useWatch` is not support dynamic `namePath`. Please provide static instead.');
} : function () {};

// ------- selector type -------

// ------- selector type end -------

function useWatch() {
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
    args[_key] = arguments[_key];
  }
  var dependencies = args[0],
    _args$ = args[1],
    _form = _args$ === void 0 ? {} : _args$;
  var options = (0, _typeUtil.isFormInstance)(_form) ? {
    form: _form
  } : _form;
  var form = options.form;
  var _useState = (0, _react.useState)(),
    _useState2 = (0, _slicedToArray2.default)(_useState, 2),
    value = _useState2[0],
    setValue = _useState2[1];
  var valueStr = (0, _react.useMemo)(function () {
    return stringify(value);
  }, [value]);
  var valueStrRef = (0, _react.useRef)(valueStr);
  valueStrRef.current = valueStr;
  var fieldContext = (0, _react.useContext)(_FieldContext.default);
  var formInstance = form || fieldContext;
  var isValidForm = formInstance && formInstance._init;

  // Warning if not exist form instance
  if (process.env.NODE_ENV !== 'production') {
    (0, _warning.default)(args.length === 2 ? form ? isValidForm : true : isValidForm, 'useWatch requires a form instance since it can not auto detect from context.');
  }
  var namePath = (0, _valueUtil.getNamePath)(dependencies);
  var namePathRef = (0, _react.useRef)(namePath);
  namePathRef.current = namePath;
  useWatchWarning(namePath);
  (0, _react.useEffect)(function () {
    // Skip if not exist form instance
    if (!isValidForm) {
      return;
    }
    var getFieldsValue = formInstance.getFieldsValue,
      getInternalHooks = formInstance.getInternalHooks;
    var _getInternalHooks = getInternalHooks(_FieldContext.HOOK_MARK),
      registerWatch = _getInternalHooks.registerWatch;
    var getWatchValue = function getWatchValue(values, allValues) {
      var watchValue = options.preserve ? allValues : values;
      return typeof dependencies === 'function' ? dependencies(watchValue) : (0, _valueUtil.getValue)(watchValue, namePathRef.current);
    };
    var cancelRegister = registerWatch(function (values, allValues) {
      var newValue = getWatchValue(values, allValues);
      var nextValueStr = stringify(newValue);

      // Compare stringify in case it's nest object
      if (valueStrRef.current !== nextValueStr) {
        valueStrRef.current = nextValueStr;
        setValue(newValue);
      }
    });

    // TODO: We can improve this perf in future
    var initialValue = getWatchValue(getFieldsValue(), getFieldsValue(true));

    // React 18 has the bug that will queue update twice even the value is not changed
    // ref: https://github.com/facebook/react/issues/27213
    if (value !== initialValue) {
      setValue(initialValue);
    }
    return cancelRegister;
  },
  // We do not need re-register since namePath content is the same
  // eslint-disable-next-line react-hooks/exhaustive-deps
  [isValidForm]);
  return value;
}
var _default = exports.default = useWatch;