"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.HoverCardComponent = exports.HOVER_CARD_SOURCE = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _react = _interopRequireWildcard(require("react"));
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
var _popup = _interopRequireDefault(require("@atlaskit/popup"));
var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
var _constants = require("../../../constants");
var _actions = require("../../../state/actions");
var _renderers = require("../../../state/renderers");
var _store = require("../../../state/store");
var _SmartLinkAnalyticsContext = require("../../../utils/analytics/SmartLinkAnalyticsContext");
var _CustomPopupContainer = _interopRequireWildcard(require("../components/CustomPopupContainer"));
var _HoverCardContent = _interopRequireDefault(require("../components/HoverCardContent"));
var _styled = require("../styled");
var _excluded = ["aria-haspopup", "aria-expanded"];
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
var HOVER_CARD_SOURCE = exports.HOVER_CARD_SOURCE = 'smartLinkPreviewHoverCard';
var HOVER_CARD_TRIGGER_WRAPPER = 'hover-card-trigger-wrapper';
var FADE_IN_DELAY = 500;
var FADE_OUT_DELAY = 300;
var RESOLVE_DELAY = 100;
var HoverCardComponent = exports.HoverCardComponent = function HoverCardComponent(_ref) {
  var _hoverPreviewOptions$;
  var children = _ref.children,
    url = _ref.url,
    _ref$id = _ref.id,
    id = _ref$id === void 0 ? '' : _ref$id,
    _ref$canOpen = _ref.canOpen,
    canOpen = _ref$canOpen === void 0 ? true : _ref$canOpen,
    _ref$closeOnChildClic = _ref.closeOnChildClick,
    closeOnChildClick = _ref$closeOnChildClic === void 0 ? false : _ref$closeOnChildClic,
    actionOptions = _ref.actionOptions,
    _ref$allowEventPropag = _ref.allowEventPropagation,
    allowEventPropagation = _ref$allowEventPropag === void 0 ? false : _ref$allowEventPropag,
    _ref$zIndex = _ref.zIndex,
    zIndex = _ref$zIndex === void 0 ? _styled.HOVER_CARD_Z_INDEX : _ref$zIndex,
    _ref$noFadeDelay = _ref.noFadeDelay,
    noFadeDelay = _ref$noFadeDelay === void 0 ? false : _ref$noFadeDelay,
    hoverPreviewOptions = _ref.hoverPreviewOptions,
    role = _ref.role,
    _ref$shouldRenderToPa = _ref.shouldRenderToParent,
    shouldRenderToParent = _ref$shouldRenderToPa === void 0 ? false : _ref$shouldRenderToPa,
    label = _ref.label,
    titleId = _ref.titleId,
    onVisibilityChange = _ref.onVisibilityChange;
  var fadeInDelay = (_hoverPreviewOptions$ = hoverPreviewOptions === null || hoverPreviewOptions === void 0 ? void 0 : hoverPreviewOptions.fadeInDelay) !== null && _hoverPreviewOptions$ !== void 0 ? _hoverPreviewOptions$ : FADE_IN_DELAY;
  var _React$useState = _react.default.useState(false),
    _React$useState2 = (0, _slicedToArray2.default)(_React$useState, 2),
    isOpen = _React$useState2[0],
    setIsOpen = _React$useState2[1];
  var fadeOutTimeoutId = (0, _react.useRef)();
  var fadeInTimeoutId = (0, _react.useRef)();
  var resolveTimeOutId = (0, _react.useRef)();
  var mousePos = (0, _react.useRef)();
  var popupOffset = (0, _react.useRef)();
  var parentSpan = (0, _react.useRef)(null);
  var renderers = (0, _renderers.useSmartLinkRenderers)();
  var linkState = (0, _store.useSmartCardState)(url);
  var handleSetIsOpen = (0, _react.useCallback)(function (isOpen) {
    setIsOpen(isOpen);
    onVisibilityChange === null || onVisibilityChange === void 0 || onVisibilityChange(isOpen);
  }, [onVisibilityChange]);
  var _useSmartCardActions = (0, _actions.useSmartCardActions)(id, url),
    loadMetadata = _useSmartCardActions.loadMetadata;
  var setMousePosition = (0, _react.useCallback)(function (event) {
    if (isOpen && canOpen) {
      return;
    }
    mousePos.current = {
      x: event.clientX,
      y: event.clientY
    };

    //If these are undefined then popupOffset is undefined and we fallback to default bottom-start placement
    if ((!isOpen || !canOpen) && parentSpan.current && mousePos.current) {
      var _parentSpan$current$g = parentSpan.current.getBoundingClientRect(),
        bottom = _parentSpan$current$g.bottom,
        left = _parentSpan$current$g.left;
      popupOffset.current = [mousePos.current.x - left + _styled.CARD_GAP_PX, mousePos.current.y - bottom + _styled.CARD_GAP_PX];
    }
  }, [canOpen, isOpen]);
  var hideCard = (0, _react.useCallback)(function () {
    if (handleSetIsOpen) {
      handleSetIsOpen(false);
    } else {
      setIsOpen(false);
    }
  }, [handleSetIsOpen]);
  var initHideCard = (0, _react.useCallback)(function () {
    if (fadeInTimeoutId.current) {
      clearTimeout(fadeInTimeoutId.current);
      // because fadeInTimeoutId.current is set by mouseOver which triggers multiple times in a hover,
      // we want to clear out the reference to signify that there's no in-progress fade in event
      fadeInTimeoutId.current = undefined;
    }
    if (resolveTimeOutId.current) {
      clearTimeout(resolveTimeOutId.current);
      // because resolveTimeOutId.current is set by mouseOver which triggers multiple times in a hover,
      // we want to clear out the reference to signify that there's no in-progress resolve event
      resolveTimeOutId.current = undefined;
    }
    if (noFadeDelay) {
      hideCard();
    } else {
      fadeOutTimeoutId.current = setTimeout(function () {
        return hideCard();
      }, FADE_OUT_DELAY);
    }
  }, [hideCard, noFadeDelay]);

  // clearing out the timeouts in order to avoid memory leaks
  // in case the component unmounts before they execute
  (0, _react.useEffect)(function () {
    return function () {
      if (fadeOutTimeoutId.current) {
        clearTimeout(fadeOutTimeoutId.current);
      }
      if (fadeInTimeoutId.current) {
        clearTimeout(fadeInTimeoutId.current);
        // because fadeInTimeoutId.current is set by mouseOver which triggers multiple times in a hover,
        // we want to clear out the reference to signify that there's no in-progress fade in event
        fadeInTimeoutId.current = undefined;
      }
      if (resolveTimeOutId.current) {
        clearTimeout(resolveTimeOutId.current);
        // because resolveTimeOutId.current is set by mouseOver which triggers multiple times in a hover,
        // we want to clear out the reference to signify that there's no in-progress resolve event
        resolveTimeOutId.current = undefined;
      }
    };
  }, []);

  // we want to initiate resolve a bit earlier for standalone cards
  // to minimize the loading state
  var initResolve = (0, _react.useCallback)(function () {
    // this check covers both non-SSR (status) & SSR case (metadataStatus)
    var isLinkUnresolved = linkState.status === 'pending' || !linkState.metadataStatus;
    if (!resolveTimeOutId.current && isLinkUnresolved) {
      resolveTimeOutId.current = setTimeout(function () {
        loadMetadata();
      }, RESOLVE_DELAY);
    }
  }, [linkState.metadataStatus, linkState.status, loadMetadata]);
  var initShowCard = (0, _react.useCallback)(function (event) {
    // clearing out fadeOutTimeoutId in case it's already counting down to hide the card
    if (fadeOutTimeoutId.current) {
      clearTimeout(fadeOutTimeoutId.current);
    }

    // starting to resolve the hover card if the store doesn't have data about the link yet
    initResolve();

    //Set mouse position in the case it's not already set by onMouseMove, as in the case of scrolling
    setMousePosition(event);
    if (!isOpen && !fadeInTimeoutId.current) {
      // setting a timeout to show a Hover Card after delay runs out
      if (noFadeDelay) {
        if (handleSetIsOpen) {
          handleSetIsOpen(true);
        } else {
          setIsOpen(true);
        }
      } else {
        fadeInTimeoutId.current = setTimeout(function () {
          if (handleSetIsOpen) {
            handleSetIsOpen(true);
          } else {
            setIsOpen(true);
          }
        }, fadeInDelay);
      }
    }
  }, [initResolve, isOpen, setMousePosition, noFadeDelay, fadeInDelay, handleSetIsOpen]);
  var onActionClick = (0, _react.useCallback)(function (actionId) {
    if (actionId === _constants.ActionName.PreviewAction || actionId === _constants.ActionName.AutomationAction) {
      hideCard();
    }
  }, [hideCard]);

  // Stop hover preview content to propagate event to parent.
  var handleChildClick = (0, _react.useCallback)(function (e, closeOnClick) {
    if (!allowEventPropagation) {
      e.stopPropagation();
    }
    if (closeOnClick) {
      hideCard();
    }
  }, [allowEventPropagation, hideCard]);
  var onContextMenuClick = (0, _react.useCallback)(function (e) {
    return handleChildClick(e, true);
  }, [handleChildClick]);
  var onChildClick = (0, _react.useCallback)(function (e) {
    return handleChildClick(e, closeOnChildClick);
  }, [closeOnChildClick, handleChildClick]);
  var content = (0, _react.useCallback)(function (_ref2) {
    var update = _ref2.update;
    var hoverCardContentProps = {
      onMouseEnter: initShowCard,
      onMouseLeave: initHideCard,
      cardState: linkState,
      onActionClick: onActionClick,
      onResolve: update,
      renderers: renderers,
      actionOptions: actionOptions,
      url: url,
      id: id,
      hoverPreviewOptions: hoverPreviewOptions
    };
    return /*#__PURE__*/_react.default.createElement(_SmartLinkAnalyticsContext.SmartLinkAnalyticsContext, {
      url: url,
      display: _constants.CardDisplay.HoverCardPreview,
      id: id,
      source: HOVER_CARD_SOURCE
    }, /*#__PURE__*/_react.default.createElement(_HoverCardContent.default, hoverCardContentProps));
  }, [initShowCard, initHideCard, linkState, onActionClick, renderers, actionOptions, url, id, hoverPreviewOptions]);
  var trigger = (0, _react.useCallback)(function (_ref3) {
    var ariaHasPopup = _ref3['aria-haspopup'],
      ariaExpanded = _ref3['aria-expanded'],
      triggerProps = (0, _objectWithoutProperties2.default)(_ref3, _excluded);
    return /*#__PURE__*/_react.default.createElement("span", {
      ref: parentSpan
    }, /*#__PURE__*/_react.default.createElement("span", (0, _extends2.default)({}, triggerProps, {
      // eslint-disable-next-line @atlassian/a11y/mouse-events-have-key-events
      onMouseOver: initShowCard
      // eslint-disable-next-line @atlassian/a11y/mouse-events-have-key-events
      ,
      onMouseLeave: initHideCard,
      onMouseMove: setMousePosition,
      onClick: onChildClick,
      onContextMenu: onContextMenuClick,
      "data-testid": HOVER_CARD_TRIGGER_WRAPPER
    }, (0, _experiments.editorExperiment)('platform_editor_preview_panel_linking_exp', true) ? {
      className: HOVER_CARD_TRIGGER_WRAPPER
    } : {}), children));
  }, [children, initHideCard, initShowCard, onChildClick, onContextMenuClick, setMousePosition]);
  var popupComponent = (0, _platformFeatureFlags.fg)('hover-card-prop-should-render-to-parent') ?
  // eslint-disable-next-line react-hooks/rules-of-hooks
  (0, _react.useMemo)(function () {
    // Within the Popup component, if shouldRenderToParent, the zIndex prop is ignored
    // as it is assumed that the custom popup container has the desired styles
    return (0, _CustomPopupContainer.createCustomPopupContainer)(shouldRenderToParent ? zIndex : undefined);
  }, [zIndex, shouldRenderToParent]) : _CustomPopupContainer.default;
  return /*#__PURE__*/_react.default.createElement(_popup.default, (0, _extends2.default)({
    testId: "hover-card",
    isOpen: isOpen && canOpen,
    onClose: hideCard,
    placement: "bottom-start",
    offset: popupOffset.current,
    autoFocus: false,
    content: content,
    trigger: trigger,
    zIndex: zIndex,
    role: role,
    titleId: titleId,
    label: label
  }, (0, _platformFeatureFlags.fg)('hover-card-prop-should-render-to-parent') ? {
    shouldRenderToParent: shouldRenderToParent
  } : {}, {
    // @ts-ignore: [PIT-1685] Fails in post-office due to backwards incompatibility issue with React 18
    popupComponent: popupComponent
  }));
};