import usePopper from "./usePopper";
import useRootClose from "./useRootClose";
import mergeOptionsWithPopperConfig from "./mergeOptionsWithPopperConfig";
import { children, createComputed, createEffect, createMemo, createSignal, getOwner, runWithOwner, Show, } from "solid-js";
import { createStore, reconcile } from "solid-js/store";
import { Portal } from "solid-js/web";
import useWaitForDOMRef from "./useWaitForDOMRef";
/**
 * Built on top of `Popper.js`, the overlay component is
 * great for custom tooltip overlays.
 */
export const Overlay = (props) => {
    const [rootElement, attachRef] = createSignal();
    const [arrowElement, attachArrowRef] = createSignal();
    const [exited, setExited] = createSignal(!props.show);
    const owner = getOwner();
    const container = useWaitForDOMRef({
        get ref() {
            return props.container;
        },
    });
    const [popperOptions, setPopperOptions] = createStore({});
    const popperVisible = createMemo(() => !!(props.show || (props.transition && !exited())));
    /** sync popper options with props */
    createComputed(() => {
        setPopperOptions(reconcile(mergeOptionsWithPopperConfig({
            enabled: popperVisible(),
            placement: props.placement,
            enableEvents: popperVisible(),
            containerPadding: props.containerPadding || 5,
            flip: props.flip,
            offset: props.offset,
            arrowElement: arrowElement(),
            popperConfig: props.popperConfig ?? {},
        })));
    });
    const popper = usePopper(props.target, rootElement, popperOptions);
    createComputed(() => {
        if (props.show) {
            if (exited())
                setExited(false);
        }
        else if (!props.transition && !exited()) {
            setExited(true);
        }
    });
    const handleHidden = (...args) => {
        setExited(true);
        if (props.onExited) {
            props.onExited(...args);
        }
    };
    createEffect(() => {
        if (rootElement()) {
            useRootClose(rootElement, props.onHide, {
                get disabled() {
                    return !props.rootClose || props.rootCloseDisabled || !props.show;
                },
                get clickTrigger() {
                    return props.rootCloseEvent;
                },
            });
        }
    });
    const wrapperProps = createMemo(() => ({
        ...popper()?.attributes.popper,
        style: popper()?.styles.popper,
        ref: attachRef,
    }));
    const arrowProps = createMemo(() => ({
        ...popper()?.attributes.arrow,
        style: popper()?.styles.arrow,
        ref: attachArrowRef,
    }));
    const metadata = createMemo(() => ({
        popper: popper(),
        placement: props.placement,
        show: !!props.show,
    }));
    const resolvedChildren = children(() => props.children);
    const InnerChild = () => runWithOwner(owner, () => (<>
        {resolvedChildren()(wrapperProps, arrowProps, metadata)}
      </>));
    let Transition;
    return (<Show when={container() && popperVisible()}>
      <Portal mount={container()}>
        {(Transition = props.transition) ? (<Transition appear in={props.show} onExit={props.onExit} onExiting={props.onExiting} onExited={handleHidden} onEnter={props.onEnter} onEntering={props.onEntering} onEntered={props.onEntered}>
            <InnerChild />
          </Transition>) : (<InnerChild />)}
      </Portal>
    </Show>);
};
export default Overlay;
