import * as React from "react";
import { useEvent, useGetKey, useGetSet, useInViewEffect } from "../../hooks";
import { useDebugEvents } from "../../utils";
import { mergeDefaults } from "../../utils/mergeDefaults";
import { useComposedRefs } from "../../utils/mergeRefs";
import { TooltipSymbol } from "../Tooltip";

const noop = () => {};
export const ScrollAwareContainer = React.forwardRef(
  function ScrollAwareContainer(
    args: {
      as: React.ElementType;
      className: string;
      children: React.ReactNode;
      onEnter: () => void;
      onLeave: () => void;
      once: boolean;
      rootMargin: string;
      threshold: number;
    },
    ref: React.ForwardedRef<HTMLDivElement>,
  ) {
    const {
      as,
      className,
      children,
      onEnter,
      onLeave,
      once,
      rootMargin,
      threshold,
      ...rest
    } = mergeDefaults(args, {
      as: "div",
      onEnter: noop,
      onLeave: noop,
      once: false,
      rootMargin: "0px",
      threshold: 0.5,
    });
    const [inViewRef] = useInViewEffect(onEnter, onLeave, {
      once,
      rootMargin,
      threshold,
    });
    const props = useDebugEvents(rest);
    const Comp = as;
    const finalRef = useComposedRefs(ref, inViewRef);
    return (
      <Comp className={className} ref={finalRef} {...props}>
        {children}
      </Comp>
    );
  },
);

export const Container = React.forwardRef(function Container(
  args: {
    as: React.ElementType;
    className: string;
    children: React.ReactNode;
  },
  ref: React.ForwardedRef<HTMLDivElement>,
) {
  const { as, className, children, ...rest } = mergeDefaults(args, {
    as: "div",
  });
  const props = useDebugEvents(rest);
  const Comp = as;
  return (
    <Comp ref={ref} className={className} {...props}>
      {children}
    </Comp>
  );
});
Container[TooltipSymbol] = true;

export const ConditionalContainer = React.forwardRef(
  function ConditionalContainer(
    args: {
      as: React.ElementType;
      className: string;
      children: (() => React.ReactNode) | React.ReactNode;
      isShowing: boolean;
      preview?: true;
      ["data-id"]: string;
    },
    ref: React.ForwardedRef<HTMLDivElement>,
  ) {
    const { as, className, children, isShowing, preview, ...rest } =
      mergeDefaults(args, {
        as: "div",
      });
    const key = useGetKey(rest);
    const [{ forceShow }, setState] = useGetSet(
      key,
      { forceShow: false },
      true,
    );
    const props = useDebugEvents(rest);
    const Comp = as;
    const show = React.useCallback(() => {
      setState(
        { forceShow: true },
        process.env.PREVIEW ? `onChange` : undefined,
      );
    }, [setState]);
    const hide = React.useCallback(() => {
      setState(
        { forceShow: false },
        process.env.PREVIEW ? `onChange` : undefined,
      );
    }, [setState]);
    const id = rest["data-id"];
    useEvent(id, "open", show);
    useEvent(id, "close", hide);
    return preview || forceShow || isShowing ? (
      <Comp ref={ref} className={className} {...props}>
        {typeof children === "function" ? children() : children}
      </Comp>
    ) : null;
  },
);
ConditionalContainer[TooltipSymbol] = true;
