import { useContext, useState, createContext } from 'react';
import useBreakpointIsAtLeast from "../breakpoint/useBreakpointIsAtLeast/index.js";
export const TooltipContext = createContext([]);

/**
 * Hook to create standard tooltip object that can be provided to both
 * `TooltipDisplay` and `TooltipTrigger` to coordinate tooltip activation and
 * content.
 *
 * You can pass in a configuration object to use to configure various aspects
 * of the tooltip. For example, if you want to reuse one display across many
 * triggers and you want to use the same component to render each tooltip's
 * content, you might provide the component type as a default value for
 * `content` and then have each trigger set its own `props` to pass to that
 * component when the trigger is active. (See the "With Element Type And Props"
 * example below.)
 *
 * You can also pass `breakpoint`, specifying at which named breakpoint the
 * tooltip should switch from the mobile "drawer" display to the desktop
 * "hover" display.
 *
 * ```js
 *
 * import { useTooltip } from '@politico/interactive-style';
 * ```
 *
 * @param {'xs'|'sm'|'md'|'lg'|'xl'} [breakpoint=md]
 *   The breakpoint at which the tooltip should switch from its mobile "drawer"
 *   display to its desktop "hover" display.
 * @param {Object} [props={}]
 *   Props to forward to the `content` element type, when appropriate. The
 *   `content` element type could either be passed to this hook or could be
 *   [provided by a `TooltipTrigger` component][trigger]. Note that if
 *   a trigger provides its own props to pass to a `content` element type,
 *   these props will be merged with the trigger's content props with the
 *   trigger taking precedence.
 *   [trigger]: ./?path=/docs/components-structure-tooltiptrigger--basic
 * @param {Object|func|string} [content]
 *   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.
 * @param {'context'|'local'} [mode]
 *   Specify the mode you want this tooltip to use to manage tooltip state.
 *   By default, the tooltip is in `context` mode, which means it will look for
 *   a `TooltipContext` to share tooltip state with a broader section of an
 *   application. You can set it to `local` mode if you want to force it to use
 *   local state only and not interact with a tooltip context. Note that even
 *   if the tooltip is in `context` mode, unless you provide a `TooltipContext`
 *   either directly or through the `TooltipSharedDisplay` component, the
 *   tooltip will manage state locally.
 * @param {Object} [displayProps]
 *   An optional object of additional props to pass to the TooltipDisplay
 *   component that will display this tooltip. Generally this should only be
 *   used if you're using a TooltipSharedDisplay, and not if you're rendering
 *   a TooltipDisplay display and can instead pass props directly to the
 *   display.
 * @returns {Object}
 */
const useTooltip = function useTooltip(opts = {}) {
  const {
    breakpoint = 'md',
    props: defaultProps = {},
    mode = 'context',
    displayProps = {},
    ...restOpts
  } = opts;
  const isDesktop = useBreakpointIsAtLeast(breakpoint);
  const [contextConfig, setContextConfig] = useContext(TooltipContext);
  const [stateConfig, setStateConfig] = useState({
    active: false
  });
  const [config, setConfig] = mode === 'context' && contextConfig ? [contextConfig, setContextConfig] : [stateConfig, setStateConfig];

  // An activation function that will trigger this tooltip with optional prop
  // overrides to customize the tooltip for the trigger.
  const activate = (activateProps = {}) => {
    const {
      content = opts.content,
      props = {},
      ...restProps
    } = activateProps;
    setConfig({
      ...restProps,
      content,
      active: true,
      props: {
        // merge props from the useTooltip hook with props from the trigger
        ...defaultProps,
        ...props
      },
      displayProps
    });
  };

  // A deactivation function that will turn the tooltip off
  const deactivate = () => {
    setConfig({
      active: false
    });
  };
  return {
    config: {
      ...restOpts,
      ...config,
      isDesktop
    },
    trigger: {
      activate,
      deactivate
    }
  };
};
export default useTooltip;