import _extends from "@babel/runtime/helpers/extends";
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
var _excluded = ["aria-haspopup", "aria-expanded"];
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
import { fg } from '@atlaskit/platform-feature-flags';
import Popup from '@atlaskit/popup';
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
import { ActionName, CardDisplay } from '../../../constants';
import { useSmartCardActions } from '../../../state/actions';
import { useSmartLinkRenderers } from '../../../state/renderers';
import { useSmartCardState as useLinkState } from '../../../state/store';
import { SmartLinkAnalyticsContext } from '../../../utils/analytics/SmartLinkAnalyticsContext';
import { createCustomPopupContainer } from '../components/CustomPopupContainer';
import HoverCardContent from '../components/HoverCardContent';
import { CARD_GAP_PX, HOVER_CARD_Z_INDEX } from '../styled';
export var 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;
export var 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 ? 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.useState(false),
    _React$useState2 = _slicedToArray(_React$useState, 2),
    isOpen = _React$useState2[0],
    setIsOpen = _React$useState2[1];
  var fadeOutTimeoutId = useRef();
  var fadeInTimeoutId = useRef();
  var resolveTimeOutId = useRef();
  var mousePos = useRef();
  var popupOffset = useRef();
  var parentSpan = useRef(null);
  var renderers = useSmartLinkRenderers();
  var linkState = useLinkState(url);
  var handleSetIsOpen = useCallback(function (isOpen) {
    setIsOpen(isOpen);
    onVisibilityChange === null || onVisibilityChange === void 0 || onVisibilityChange(isOpen);
  }, [onVisibilityChange]);
  var _useSmartCardActions = useSmartCardActions(id, url),
    loadMetadata = _useSmartCardActions.loadMetadata,
    register = _useSmartCardActions.register;
  var setMousePosition = 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 + CARD_GAP_PX, mousePos.current.y - bottom + CARD_GAP_PX];
    }
  }, [canOpen, isOpen]);
  var hideCard = useCallback(function () {
    if (handleSetIsOpen) {
      handleSetIsOpen(false);
    } else {
      setIsOpen(false);
    }
  }, [handleSetIsOpen]);
  var initHideCard = 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
  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 = 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 () {
        if (fg('navx-2478-sl-fix-hover-card-unresolved-view')) {
          if (linkState.status === 'pending') {
            // Link hasn't been registered yet. Register and resolve link.
            register();
          } else {
            // Link has been already been partially resolved. Load metadata.
            loadMetadata();
          }
        } else {
          loadMetadata();
        }
      }, RESOLVE_DELAY);
    }
  }, [linkState.metadataStatus, linkState.status, loadMetadata, register]);
  var initShowCard = 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 = useCallback(function (actionId) {
    if (actionId === ActionName.PreviewAction || actionId === ActionName.AutomationAction) {
      hideCard();
    }
  }, [hideCard]);

  // Stop hover preview content to propagate event to parent.
  var handleChildClick = useCallback(function (e, closeOnClick) {
    if (!allowEventPropagation) {
      e.stopPropagation();
    }
    if (closeOnClick) {
      hideCard();
    }
  }, [allowEventPropagation, hideCard]);
  var onContextMenuClick = useCallback(function (e) {
    return handleChildClick(e, true);
  }, [handleChildClick]);
  var onChildClick = useCallback(function (e) {
    return handleChildClick(e, closeOnChildClick);
  }, [closeOnChildClick, handleChildClick]);
  var content = 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.createElement(SmartLinkAnalyticsContext, {
      url: url,
      display: CardDisplay.HoverCardPreview,
      id: id,
      source: HOVER_CARD_SOURCE
    }, /*#__PURE__*/React.createElement(HoverCardContent, hoverCardContentProps));
  }, [initShowCard, initHideCard, linkState, onActionClick, renderers, actionOptions, url, id, hoverPreviewOptions]);
  var handleKeyDown = useCallback(function (e) {
    if (e.key === ' ') {
      e.preventDefault();
      initShowCard(e);
    }
  }, [initShowCard]);
  var trigger = useCallback(function (_ref3) {
    var _ariaHasPopup = _ref3['aria-haspopup'],
      _ariaExpanded = _ref3['aria-expanded'],
      triggerProps = _objectWithoutProperties(_ref3, _excluded);
    return /*#__PURE__*/React.createElement("span", {
      ref: parentSpan
    }, /*#__PURE__*/React.createElement("span", _extends({}, 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,
      onKeyDown: fg('fix_hover_card_on_focus_a11y') ? handleKeyDown : undefined,
      onClick: onChildClick,
      onContextMenu: onContextMenuClick,
      "data-testid": HOVER_CARD_TRIGGER_WRAPPER
    }, editorExperiment('platform_editor_preview_panel_linking_exp', true) ? {
      className: HOVER_CARD_TRIGGER_WRAPPER
    } : {}), children));
  }, [children, initHideCard, initShowCard, onChildClick, onContextMenuClick, setMousePosition, handleKeyDown]);
  var popupComponent = useMemo(
  // Within the Popup component, if shouldRenderToParent, the zIndex prop is ignored
  // as it is assumed that the custom popup container has the desired styles
  function () {
    return createCustomPopupContainer(shouldRenderToParent ? zIndex : undefined);
  }, [zIndex, shouldRenderToParent]);
  return /*#__PURE__*/React.createElement(Popup, {
    testId: "hover-card",
    isOpen: isOpen && canOpen,
    onClose: fg('fix_hover_card_on_focus_a11y') ? initHideCard : hideCard,
    placement: "bottom-start",
    offset: popupOffset.current,
    autoFocus: false,
    content: content,
    trigger: trigger,
    zIndex: zIndex,
    role: role,
    titleId: titleId,
    label: label,
    shouldRenderToParent: shouldRenderToParent
    // @ts-ignore: [PIT-1685] Fails in post-office due to backwards incompatibility issue with React 18
    ,
    popupComponent: popupComponent
  });
};