"use strict";

var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.useCacheErrors = useCacheErrors;
exports.toArray = toArray;
exports.getFieldId = getFieldId;
exports.useForm = useForm;
exports.useFrameState = useFrameState;

var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));

var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));

var React = _interopRequireWildcard(require("react"));

var _raf = _interopRequireDefault(require("raf"));

var _rcFieldForm = require("rc-field-form");

var _scrollIntoViewIfNeeded = _interopRequireDefault(require("scroll-into-view-if-needed"));

/**
 * Always debounce error to avoid [error -> null -> error] blink
 */
function useCacheErrors(errors, changeTrigger, directly) {
  var cacheRef = React.useRef({
    errors: errors,
    visible: !!errors.length
  });

  var _React$useState = React.useState({}),
      _React$useState2 = (0, _slicedToArray2["default"])(_React$useState, 2),
      forceUpdate = _React$useState2[1];

  var update = function update() {
    var prevVisible = cacheRef.current.visible;
    var newVisible = !!errors.length;
    var prevErrors = cacheRef.current.errors;
    cacheRef.current.errors = errors;
    cacheRef.current.visible = newVisible;

    if (prevVisible !== newVisible) {
      changeTrigger(newVisible);
    } else if (prevErrors.length !== errors.length || prevErrors.some(function (prevErr, index) {
      return prevErr !== errors[index];
    })) {
      forceUpdate({});
    }
  };

  React.useEffect(function () {
    if (!directly) {
      var timeout = setTimeout(update, 10);
      return function () {
        return clearTimeout(timeout);
      };
    }
  }, [errors]);

  if (directly) {
    update();
  }

  return [cacheRef.current.visible, cacheRef.current.errors];
}

function toArray(candidate) {
  if (candidate === undefined || candidate === false) return [];
  return Array.isArray(candidate) ? candidate : [candidate];
}

function getFieldId(namePath, formName) {
  if (!namePath.length) return undefined;
  var mergedId = namePath.join('_');
  return formName ? "".concat(formName, "_").concat(mergedId) : mergedId;
}

function useForm(form) {
  var _useRcForm = (0, _rcFieldForm.useForm)(),
      _useRcForm2 = (0, _slicedToArray2["default"])(_useRcForm, 1),
      rcForm = _useRcForm2[0];

  var wrapForm = React.useMemo(function () {
    return form || (0, _extends2["default"])((0, _extends2["default"])({}, rcForm), {
      __INTERNAL__: {},
      scrollToField: function scrollToField(name) {
        var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
        var namePath = toArray(name);
        var fieldId = getFieldId(namePath, wrapForm.__INTERNAL__.name);
        var node = fieldId ? document.getElementById(fieldId) : null;

        if (node) {
          (0, _scrollIntoViewIfNeeded["default"])(node, (0, _extends2["default"])({
            scrollMode: 'if-needed',
            block: 'nearest'
          }, options));
        }
      }
    });
  }, [form, rcForm]);
  return [wrapForm];
}

function useFrameState(defaultValue) {
  var _React$useState3 = React.useState(defaultValue),
      _React$useState4 = (0, _slicedToArray2["default"])(_React$useState3, 2),
      value = _React$useState4[0],
      setValue = _React$useState4[1];

  var frameRef = React.useRef(null);
  var batchRef = React.useRef([]);
  var destroyRef = React.useRef(false);
  React.useEffect(function () {
    return function () {
      destroyRef.current = true;

      _raf["default"].cancel(frameRef.current);
    };
  }, []);

  function setFrameValue(updater) {
    if (destroyRef.current) {
      return;
    }

    if (frameRef.current === null) {
      batchRef.current = [];
      frameRef.current = (0, _raf["default"])(function () {
        frameRef.current = null;
        setValue(function (prevValue) {
          var current = prevValue;
          batchRef.current.forEach(function (func) {
            current = func(current);
          });
          return current;
        });
      });
    }

    batchRef.current.push(updater);
  }

  return [value, setFrameValue];
}