import { __assign } from 'tslib';
import { useContext, useRef, useEffect } from 'react';
import { PresenceContext } from '../../context/PresenceContext.js';
import { isPresent } from '../../components/AnimatePresence/use-presence.js';
import { LayoutGroupContext } from '../../context/LayoutGroupContext.js';
import { useVisualElementContext } from '../../context/MotionContext/index.js';
import { useIsomorphicLayoutEffect } from '../../utils/use-isomorphic-effect.js';
import { MotionConfigContext } from '../../context/MotionConfigContext.js';
import { LazyContext } from '../../context/LazyContext.js';

function useLayoutId(_a) {
    var layoutId = _a.layoutId;
    var layoutGroupId = useContext(LayoutGroupContext);
    return layoutGroupId && layoutId !== undefined
        ? layoutGroupId + "-" + layoutId
        : layoutId;
}
function useVisualElement(Component, visualState, props, createVisualElement) {
    var config = useContext(MotionConfigContext);
    var lazyContext = useContext(LazyContext);
    var parent = useVisualElementContext();
    var presenceContext = useContext(PresenceContext);
    var layoutId = useLayoutId(props);
    var visualElementRef = useRef(undefined);
    /**
     * If we haven't preloaded a renderer, check to see if we have one lazy-loaded
     */
    if (!createVisualElement)
        createVisualElement = lazyContext.renderer;
    if (!visualElementRef.current && createVisualElement) {
        visualElementRef.current = createVisualElement(Component, {
            visualState: visualState,
            parent: parent,
            props: __assign(__assign({}, props), { layoutId: layoutId }),
            presenceId: presenceContext === null || presenceContext === void 0 ? void 0 : presenceContext.id,
            blockInitialAnimation: (presenceContext === null || presenceContext === void 0 ? void 0 : presenceContext.initial) === false,
        });
    }
    var visualElement = visualElementRef.current;
    useIsomorphicLayoutEffect(function () {
        if (!visualElement)
            return;
        visualElement.setProps(__assign(__assign(__assign({}, config), props), { layoutId: layoutId }));
        visualElement.isPresent = isPresent(presenceContext);
        visualElement.isPresenceRoot =
            !parent || parent.presenceId !== (presenceContext === null || presenceContext === void 0 ? void 0 : presenceContext.id);
        /**
         * Fire a render to ensure the latest state is reflected on-screen.
         */
        visualElement.syncRender();
    });
    useEffect(function () {
        var _a;
        if (!visualElement)
            return;
        /**
         * In a future refactor we can replace the features-as-components and
         * have this loop through them all firing "effect" listeners
         */
        (_a = visualElement.animationState) === null || _a === void 0 ? void 0 : _a.animateChanges();
    });
    useIsomorphicLayoutEffect(function () { return function () { return visualElement === null || visualElement === void 0 ? void 0 : visualElement.notifyUnmount(); }; }, []);
    return visualElement;
}

export { useVisualElement };
