import { __assign } from "tslib";
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import cx from 'classnames';
import { createRef, forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState, } from 'react';
import { Waypoint } from '../waypoint';
import { useCallbackRef } from '../utils/hooks/useCallbackRef';
import isBrowser from '../utils/isBrowser';
import { useResizeObserver } from '../utils/hooks/useResizeObserver';
import { WindowResizeHandler } from '../utils/component/WindowResizeHandler';
import { getViewportHeight } from '../utils/dom/getViewportSize';
export var Affix = forwardRef(function (_a, affixRef) {
    var className = _a.className, placeholderClassName = _a.placeholderClassName, children = _a.children, offsetTop = _a.offsetTop, offsetBottom = _a.offsetBottom, getAffixContainer = _a.getAffixContainer, _b = _a.zIndex, zIndex = _b === void 0 ? 10 : _b, onPin = _a.onPin, onUnpin = _a.onUnpin;
    var _c = useState(1), position = _c[0], setPosition = _c[1];
    var _d = useState(), width = _d[0], setWidth = _d[1];
    var _e = useState(), height = _e[0], setHeight = _e[1];
    var placeholderRef = useRef(createRef());
    var onPinCallbackRef = useCallbackRef(onPin);
    var onUnpinCallbackRef = useCallbackRef(onUnpin);
    var useTop = typeof offsetTop === 'number';
    var useBottom = typeof offsetBottom === 'number';
    var _f = useState(null), container = _f[0], setContainer = _f[1];
    var _g = useState(0), containerTop = _g[0], setContainerTop = _g[1];
    var _h = useState(0), containerBottom = _h[0], setContainerBottom = _h[1];
    var _j = useState(0), windowHeight = _j[0], setWindowHeight = _j[1];
    var containerBoundingRectChange = useCallback(function (container) {
        var rect = container.getBoundingClientRect();
        useTop && setContainerTop(rect.top);
        useBottom && setContainerBottom(rect.bottom);
    }, [useTop, useBottom]);
    var setSize = useCallback(function (entries) {
        var _a = entries[0], borderBoxSize = _a.borderBoxSize, contentRect = _a.contentRect;
        if (borderBoxSize && borderBoxSize.length > 0) {
            var _b = borderBoxSize[0], width_1 = _b.inlineSize, height_1 = _b.blockSize;
            setWidth(width_1);
            setHeight(height_1);
        }
        else {
            var width_2 = contentRect.width, height_2 = contentRect.height;
            setWidth(width_2);
            setHeight(height_2);
        }
    }, []);
    var _k = useResizeObserver(setSize), observe = _k.observe, disconnect = _k.disconnect;
    var pin = useCallback(function (expectedPosition) {
        return function (_a) {
            var _b, _c;
            var currentPosition = _a.currentPosition;
            if (currentPosition !== expectedPosition) {
                return;
            }
            var node = (_b = placeholderRef.current) === null || _b === void 0 ? void 0 : _b.current;
            if (node) {
                setWidth(node.offsetWidth);
                setHeight(node.offsetHeight);
            }
            observe(node);
            setPosition(currentPosition);
            (_c = onPinCallbackRef.current) === null || _c === void 0 ? void 0 : _c.call(onPinCallbackRef);
        };
    }, [onPinCallbackRef, observe]);
    var unpin = useCallback(function (expectedPrevPosition) {
        return function (_a) {
            var _b;
            var currentPosition = _a.currentPosition, previousPosition = _a.previousPosition;
            if (previousPosition !== expectedPrevPosition) {
                return;
            }
            setWidth(undefined);
            setHeight(undefined);
            disconnect();
            setPosition(currentPosition);
            (_b = onUnpinCallbackRef.current) === null || _b === void 0 ? void 0 : _b.call(onUnpinCallbackRef);
        };
    }, [onUnpinCallbackRef, disconnect]);
    var _l = useMemo(function () { return [pin(0), unpin(0)]; }, [pin, unpin]), pinTop = _l[0], unpinTop = _l[1];
    var _m = useMemo(function () { return [pin(2), unpin(2)]; }, [pin, unpin]), pinBottom = _m[0], unpinBottom = _m[1];
    var placeholderStyle = useMemo(function () {
        if (position === 1) {
            return {};
        }
        return {
            height: height,
        };
    }, [height, position]);
    var containerStyle = useMemo(function () {
        if (position === 0 ||
            position === 2) {
            var styles = {
                position: 'fixed',
                zIndex: zIndex,
                width: width,
            };
            if (container) {
                if (position === 0) {
                    styles.top = offsetTop + containerTop;
                }
                else {
                    styles.bottom = offsetBottom + (windowHeight - containerBottom);
                }
            }
            else {
                if (position === 0) {
                    styles.top = offsetTop;
                }
                else {
                    styles.bottom = offsetBottom;
                }
            }
            return styles;
        }
        return { position: 'static' };
    }, [
        container,
        offsetBottom,
        offsetTop,
        containerTop,
        containerBottom,
        windowHeight,
        position,
        width,
        zIndex,
    ]);
    var updatePosition = useCallback(function () {
        container && containerBoundingRectChange(container);
    }, [container, containerBoundingRectChange]);
    useEffect(function () {
        var containerNode = getAffixContainer === null || getAffixContainer === void 0 ? void 0 : getAffixContainer();
        if (containerNode) {
            setContainer(containerNode);
            containerBoundingRectChange(containerNode);
            setWindowHeight(getViewportHeight());
        }
    }, [getAffixContainer, containerBoundingRectChange]);
    var onWindowResize = useCallback(function () {
        setWindowHeight(getViewportHeight());
    }, []);
    useImperativeHandle(affixRef, function () { return ({
        updatePosition: updatePosition,
    }); });
    var ancestor = useMemo(function () {
        return container !== null && container !== void 0 ? container : (isBrowser ? window : undefined);
    }, [container]);
    return (_jsxs(_Fragment, { children: [useTop && (_jsx(Waypoint, { scrollableAncestor: ancestor, onEnter: unpinTop, onLeave: pinTop, topOffset: offsetTop }, void 0)), _jsx("div", __assign({ className: cx('zent-affix-placeholder', placeholderClassName), style: placeholderStyle, ref: placeholderRef.current, "data-zv": 'v10.0.11' }, { children: _jsx("div", __assign({ className: cx('zent-affix', className), style: containerStyle, "data-zv": 'v10.0.11' }, { children: children }), void 0) }), void 0), useBottom && (_jsx(Waypoint, { scrollableAncestor: ancestor, onEnter: unpinBottom, onLeave: pinBottom, bottomOffset: offsetBottom }, void 0)), container && (_jsx(WindowResizeHandler, { onResize: onWindowResize, disableThrottle: true }, void 0))] }, void 0));
});
Affix.displayName = 'ZentAffix';
export default Affix;
