import PropTypes from 'prop-types';
import ClickAwayListener from 'react-click-away-listener';
import useTooltipEvents from './hooks/useTooltipEvents';

/**
 * **Note:** if you haven't read [the basic `Tooltip` documentation][tooltip],
 * you should read through that first. This component is the _trigger_
 * component of a tooltip, which you only need if you're using an advanced
 * tooltip.
 *
 * This component is a tooltip trigger that activates a tooltip with the
 * specified content. A wrapper element is rendered around the trigger children
 * so that the appropriate event listeners can be attached to it. That could be
 * a native DOM node (a `div` by default) or a custom element, as long as it
 * accepts and handles the `onMouseEnter`, `onMouseLeave`, `onFocus`, `onBlur`,
 * `onClick`, and `tabIndex` props appropriately.
 *
 * When this trigger is activated, either by hovering over it on desktop or by
 * clicking it on mobile, it will activate the tooltip provided in the
 * `tooltip` prop, either with the tooltip's default content or with
 * trigger-specific content parameters if those are provided. The specific
 * content to be rendered when this trigger is activated can be set with the
 * `content` prop in two different ways:
 *
 * 1. by specifying the rendered content directly as the `content` prop, or
 * 2. by specifying a React component type as the `content` prop and specifying
 *    the props that should be passed to it when it's rendered as the `props`
 *    prop.
 *
 * Note that if the tooltip has a default `content` value that is a React
 * element type then a trigger can specify props to pass to that component by
 * just specifying the `props` prop.
 *
 * Note that `TooltipTrigger` creates an extra DOM node around its children to
 * handle user interaction events. By default this renders a plain `div`, which
 * may create an unexpectedly large hover target if you put a `TooltipTrigger`
 * around, say, an `inline-block` component with a narrow width. If you want
 * a tooltip on a size-bound element, be sure to bound the size of the hover
 * target with a parent element.
 *
 * For more examples on how to use the `TooltipTrigger` component in the
 * context of an advanced tooltip, check out [the advanced tooltip
 * stories][advanced-tooltip].
 *
 * ```js
 *
 * import { TooltipTrigger } from '@politico/interactive-style';
 * ```
 *
 * [tooltip]: ./?path=/docs/components-structure-tooltip--basic-tooltip-text
 * [advanced-tooltip]: ./?path=/docs/components-structure-tooltip--advanced-tooltip-shared-component-type
 */
const TooltipTrigger = function TooltipTrigger(props) {
  const {
    active,
    as: WrapperElement,
    children,
    tooltip,
    content,
    props: childProps,
    ...forwardProps
  } = props;
  const eventHandlers = useTooltipEvents({
    tooltip,
    content,
    props: childProps
  });
  const onClickAway = () => {
    if (!tooltip) return;
    tooltip.trigger.deactivate();
  };
  if (!active) {
    return children;
  }
  return <ClickAwayListener onClickAway={onClickAway}>
      <WrapperElement {...eventHandlers} {...forwardProps}>
        {children}
      </WrapperElement>
    </ClickAwayListener>;
};
TooltipTrigger.defaultProps = {
  as: 'div',
  active: true,
  content: undefined,
  props: undefined,
  tooltip: undefined
};
TooltipTrigger.propTypes = {
  /**
   * The element type to render around the trigger children and handle the
   * trigger event listeners
   */
  as: PropTypes.elementType,
  /**
   * The children to render as the trigger of the tooltip
   */
  children: PropTypes.node.isRequired,
  /**
   * A tooltip object as provided by the `useTooltip` hook
   */
  tooltip: PropTypes.shape({
    config: PropTypes.shape({
      isDesktop: PropTypes.bool
    }),
    trigger: PropTypes.shape({
      activate: PropTypes.func,
      deactivate: PropTypes.func
    })
  }),
  /**
   * The tooltip content to use when this trigger is activated or the component
   * type to render. This can either be a pre-rendered node of content or
   * an element type.
   */
  content: PropTypes.oneOfType([PropTypes.node, PropTypes.elementType]),
  /**
   * The props to pass to the tooltip component type when this trigger is
   * activated
   */
  props: PropTypes.shape({}),
  /**
   * Whether to render the triggering mechanism
   */
  active: PropTypes.bool
};
export default TooltipTrigger;