"use strict";

exports.__esModule = true;
exports.default = void 0;

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

var _clsx = _interopRequireDefault(require("clsx"));

var _utils = require("../utils");

var _useTouch = _interopRequireDefault(require("../hooks/use-touch"));

var _useScrollParent = require("../hooks/use-scroll-parent");

var _useEventListener = _interopRequireDefault(require("../hooks/use-event-listener"));

var _loading = _interopRequireDefault(require("../loading"));

var _hooks = require("../hooks");

var _ConfigProviderContext = _interopRequireDefault(require("../config-provider/ConfigProviderContext"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }

function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }

function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }

var DEFAULT_HEAD_HEIGHT = 50;
var TEXT_STATUS = ['pulling', 'loosing', 'success'];

var PullRefresh = function PullRefresh(props) {
  var _useContext = (0, _react.useContext)(_ConfigProviderContext.default),
      prefixCls = _useContext.prefixCls,
      createNamespace = _useContext.createNamespace,
      locale = _useContext.locale;

  var _createNamespace = createNamespace('pull-refresh', prefixCls),
      bem = _createNamespace[0];

  var disabled = props.disabled,
      animationDuration = props.animationDuration;
  var root = (0, _react.useRef)();

  var _useSetState = (0, _hooks.useSetState)({
    refreshing: false,
    status: 'normal',
    distance: 0,
    duration: 0
  }),
      state = _useSetState[0],
      updateState = _useSetState[1];

  var track = (0, _react.useRef)();
  var reachTop = (0, _react.useRef)(null);
  var touch = (0, _useTouch.default)();

  var getHeadStyle = function getHeadStyle() {
    if (props.headHeight !== DEFAULT_HEAD_HEIGHT) {
      return {
        height: props.headHeight + "px"
      };
    }

    return null;
  };

  var isTouchable = (0, _react.useCallback)(function () {
    return state.status !== 'loading' && state.status !== 'success' && !disabled;
  }, [state.status, disabled]);

  var ease = function ease(distance) {
    var pullDistance = +(props.pullDistance || props.headHeight);

    if (distance > pullDistance) {
      if (distance < pullDistance * 2) {
        distance = pullDistance + (distance - pullDistance) / 2;
      } else {
        distance = pullDistance * 1.5 + (distance - pullDistance * 2) / 4;
      }
    }

    return Math.round(distance);
  };

  var setStatus = function setStatus(distance, isLoading) {
    var pullDistance = +(props.pullDistance || props.headHeight);
    var newState = {
      distance: distance
    };

    if (isLoading) {
      newState.status = 'loading';
    } else if (distance === 0) {
      newState.status = 'normal';
    } else if (distance < pullDistance) {
      newState.status = 'pulling';
    } else {
      newState.status = 'loosing';
    }

    updateState(newState);
  };

  var getStatusText = function getStatusText() {
    if (state.status === 'normal') {
      return '';
    }

    return props[state.status + "Text"] || locale.vanPullRefresh[state.status];
  };

  var renderStatus = function renderStatus() {
    var status = state.status,
        distance = state.distance;

    if (typeof props[state.status + "Text"] === 'function') {
      return props[state.status + "Text"]({
        distance: distance
      });
    }

    var nodes = [];

    if (TEXT_STATUS.includes(status)) {
      nodes.push( /*#__PURE__*/_react.default.createElement("div", {
        key: "text",
        className: (0, _clsx.default)(bem('text'))
      }, getStatusText()));
    }

    if (status === 'loading') {
      nodes.push( /*#__PURE__*/_react.default.createElement(_loading.default, {
        key: "loading",
        className: (0, _clsx.default)(bem('loading'))
      }, getStatusText()));
    }

    return nodes;
  };

  var showSuccessTip = function showSuccessTip() {
    updateState({
      status: 'success'
    });
    setTimeout(function () {
      setStatus(0);
    }, +props.successDuration);
  };

  var onRefresh = /*#__PURE__*/function () {
    var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
      return regeneratorRuntime.wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              _context.prev = 0;
              updateState({
                refreshing: true
              });
              _context.next = 4;
              return props.onRefresh();

            case 4:
              updateState({
                refreshing: false
              });
              _context.next = 10;
              break;

            case 7:
              _context.prev = 7;
              _context.t0 = _context["catch"](0);
              updateState({
                refreshing: false
              });

            case 10:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, null, [[0, 7]]);
    }));

    return function onRefresh() {
      return _ref.apply(this, arguments);
    };
  }();

  var checkPosition = function checkPosition(event) {
    var scrollTarget = (0, _useScrollParent.getScrollParent)(event.target);
    reachTop.current = (0, _utils.getScrollTop)(scrollTarget) === 0;

    if (reachTop.current) {
      updateState({
        duration: 0
      });
      touch.start(event);
    }
  };

  var onTouchStart = function onTouchStart(event) {
    if (isTouchable()) {
      checkPosition(event.nativeEvent);
    }
  };

  var onTouchMove = (0, _react.useCallback)(function (event) {
    if (isTouchable()) {
      if (!reachTop.current) {
        checkPosition(event);
      }

      touch.move(event);

      if (reachTop.current && touch.deltaY >= 0 && touch.isVertical()) {
        setStatus(ease(touch.deltaY));
        (0, _utils.preventDefault)(event);
      } else {
        /**
         * IN THIS CASE:
         * if component don't rerender after event.preventDefault
         * ios will hold `preventDefault` behavior when touchmoving
         * it will cause window unscrollable
         */
        setStatus(0);
      }
    }
  }, [reachTop.current, touch.deltaY, isTouchable]);

  var onTouchEnd = function onTouchEnd() {
    if (reachTop.current && touch.deltaY && isTouchable()) {
      updateState({
        duration: +animationDuration
      });

      if (state.status === 'loosing') {
        setStatus(+props.headHeight, true);
        onRefresh();
      } else {
        setStatus(0);
      }
    }
  };

  (0, _useEventListener.default)('touchmove', onTouchMove, {
    target: track.current,
    depends: [reachTop.current, isTouchable(), touch.deltaY]
  });
  (0, _hooks.useUpdateEffect)(function () {
    updateState({
      duration: +animationDuration
    });

    if (state.refreshing) {
      setStatus(+props.headHeight, true);
    } else if (props.successText) {
      showSuccessTip();
    } else {
      setStatus(0, false);
    }
  }, [state.refreshing]);
  var trackStyle = (0, _react.useMemo)(function () {
    return {
      transitionDuration: state.duration + "ms",
      transform: state.distance ? "translate3d(0," + state.distance + "px, 0)" : ''
    };
  }, [state.duration, state.distance]);
  return /*#__PURE__*/_react.default.createElement("div", {
    ref: root,
    className: (0, _clsx.default)(props.className, bem()),
    style: props.style
  }, /*#__PURE__*/_react.default.createElement("div", {
    ref: track,
    className: (0, _clsx.default)(bem('track')),
    style: trackStyle,
    onTouchStart: onTouchStart,
    onTouchEnd: onTouchEnd,
    onTouchCancel: onTouchEnd
  }, /*#__PURE__*/_react.default.createElement("div", {
    className: (0, _clsx.default)(bem('head')),
    style: getHeadStyle()
  }, renderStatus()), props.children));
};

PullRefresh.defaultProps = {
  headHeight: 50,
  animationDuration: 300,
  successDuration: 500
};
var _default = PullRefresh;
exports.default = _default;