import { __assign } from "tslib";
import { jsx as _jsx } from "react/jsx-runtime";
import cx from 'classnames';
import { Subject } from 'rxjs';
import { usePopoverContext } from './Context';
import Portal from '../portal';
import { useWindowEventHandler } from '../utils/component/WindowEventHandler';
import findPositionedParent from '../utils/dom/findPositionedParent';
import { INVISIBLE_POSITION } from './placement';
import { useLazy } from '../utils/hooks/useLazy';
import { useAnimationFramed } from '../utils/hooks/useAnimationFramed';
import { createContext, useContext, useEffect, useImperativeHandle, useMemo, useRef, useState, } from 'react';
import { useMounted } from '../utils/hooks/useMounted';
var ContentContext = createContext({
    positionChanged$: new Subject(),
});
ContentContext.displayName = 'PopoverContentContext';
function translateToContainerCoordinates(containerRect, bb) {
    var left = containerRect.left, top = containerRect.top;
    return {
        width: bb.width,
        height: bb.height,
        top: bb.top - top,
        left: bb.left - left,
        bottom: bb.bottom - top,
        right: bb.right - left,
    };
}
function getPosition(_a, getContainer, getPositionedParent, portalRef) {
    var _b;
    var visible = _a.visible, placement = _a.placement, popover = _a.popover, cushion = _a.cushion;
    if (!visible) {
        return INVISIBLE_POSITION;
    }
    var container = getContainer();
    var parent = getPositionedParent();
    var portal = portalRef.current;
    var anchor = (_b = popover.getAnchor) === null || _b === void 0 ? void 0 : _b.call(popover);
    if (!container ||
        !parent ||
        !portal ||
        !anchor ||
        !(anchor instanceof HTMLElement)) {
        return INVISIBLE_POSITION;
    }
    var parentRect = parent.getBoundingClientRect();
    var content = portal.container;
    var contentRect = content.getBoundingClientRect();
    var anchorRect = anchor.getBoundingClientRect();
    var relativeRect = translateToContainerCoordinates(parentRect, anchorRect);
    var position = placement({
        relativeRect: relativeRect,
        anchor: anchor,
        anchorRect: anchorRect,
        content: content,
        contentRect: contentRect,
        containerRect: parentRect,
        container: parent,
        cushion: cushion,
    });
    return position;
}
function PopoverContent(_a) {
    var children = _a.children;
    var ctx = usePopoverContext();
    var parentPositionChanged$ = useContext(ContentContext).positionChanged$;
    var contentCtx = useMemo(function () { return ({
        positionChanged$: new Subject(),
    }); }, []);
    var _b = useState(INVISIBLE_POSITION), position = _b[0], setPosition = _b[1];
    var contextRef = useRef(ctx);
    contextRef.current = ctx;
    var containerSelector = ctx.containerSelector, portalRef = ctx.portalRef;
    var getContainer = useLazy(function () { return document.querySelector(containerSelector); }, [containerSelector]);
    var getPositionedParent = useLazy(function () {
        var container = getContainer();
        return container && findPositionedParent(container);
    }, [getContainer]);
    var mounted = useMounted();
    var adjustPosition = useAnimationFramed(function () {
        if (!mounted.current) {
            return;
        }
        var position = getPosition(contextRef.current, getContainer, getPositionedParent, portalRef);
        setPosition(position);
    });
    useImperativeHandle(ctx.contentRef, function () { return ({
        adjustPosition: adjustPosition,
    }); }, [adjustPosition]);
    useWindowEventHandler('resize', adjustPosition);
    useWindowEventHandler('scroll', adjustPosition, {
        capture: true,
    });
    useEffect(function () {
        ctx.popover.positionUpdated();
        contentCtx.positionChanged$.next();
    }, [ctx.popover, position, contentCtx]);
    useEffect(function () {
        var $ = parentPositionChanged$.subscribe(function () {
            adjustPosition();
        });
        return function () { return $.unsubscribe(); };
    }, [parentPositionChanged$, adjustPosition]);
    return (_jsx(Portal, __assign({ ref: portalRef, visible: ctx.visible, selector: containerSelector, className: cx('zent-popover-v2', position.className, ctx.className), style: __assign(__assign({}, position.style), ctx.style) }, { children: _jsx(ContentContext.Provider, __assign({ value: contentCtx }, { children: children }), void 0) }), void 0));
}
export default PopoverContent;
