import { useEffect, useRef, useContext, forwardRef, useMemo, createElement, useId } from 'react';
import { Animated, StyleSheet, useAnimatedValue } from 'react-native';
import { ScrollViewContext, StickyContext } from './context';
import useNodesRef from './useNodesRef';
import { splitProps, splitStyle, useTransformStyle, wrapChildren, useLayout, extendObject } from './utils';
import { error } from '@mpxjs/utils';
import useInnerProps, { getCustomEvent } from './getInnerListeners';
const _StickyHeader = forwardRef((stickyHeaderProps = {}, ref) => {
    const { textProps, innerProps: props = {} } = splitProps(stickyHeaderProps);
    const { style, bindstickontopchange, padding = [0, 0, 0, 0], 'offset-top': offsetTop = 0, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props;
    const { scrollOffset, gestureRef: scrollViewRef } = useContext(ScrollViewContext);
    const stickyContext = useContext(StickyContext);
    const { registerStickyHeader, unregisterStickyHeader } = stickyContext;
    const headerRef = useRef(null);
    const isStickOnTopRef = useRef(false);
    const id = useId();
    const { normalStyle, hasVarDec, varContextRef, hasSelfPercent, setWidth, setHeight } = useTransformStyle(style, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
    const { layoutRef, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: headerRef, onLayout });
    const { textStyle, innerStyle = {} } = splitStyle(normalStyle);
    const headerTopAnimated = useAnimatedValue(0);
    // harmony animatedValue 不支持通过 _value 访问
    const headerTopRef = useRef(0);
    useEffect(() => {
        registerStickyHeader({ key: id, updatePosition });
        return () => {
            unregisterStickyHeader(id);
        };
    }, []);
    function updatePosition() {
        if (headerRef.current) {
            if (scrollViewRef && scrollViewRef.current) {
                headerRef.current.measureLayout(scrollViewRef.current, (left, top) => {
                    Animated.timing(headerTopAnimated, {
                        toValue: top,
                        duration: 0,
                        useNativeDriver: true
                    }).start();
                    headerTopRef.current = top;
                });
            }
            else {
                error('StickyHeader measureLayout error: scrollViewRef is not a valid native component reference');
            }
        }
    }
    function onLayout(e) {
        updatePosition();
    }
    useNodesRef(props, ref, headerRef, {
        style: normalStyle
    });
    useEffect(() => {
        if (!bindstickontopchange || !scrollOffset)
            return;
        const listener = scrollOffset.addListener((state) => {
            const currentScrollValue = state.value;
            const newIsStickOnTop = currentScrollValue > headerTopRef.current;
            if (newIsStickOnTop !== isStickOnTopRef.current) {
                isStickOnTopRef.current = newIsStickOnTop;
                bindstickontopchange(getCustomEvent('stickontopchange', {}, {
                    detail: {
                        isStickOnTop: newIsStickOnTop
                    },
                    layoutRef
                }, props));
            }
        });
        return () => {
            scrollOffset.removeListener(listener);
        };
    }, [bindstickontopchange, scrollOffset]);
    const animatedStyle = useMemo(() => {
        if (scrollOffset) {
            const translateY = Animated.subtract(scrollOffset, headerTopAnimated).interpolate({
                inputRange: [0, 1],
                outputRange: [0, 1],
                extrapolateLeft: 'clamp',
                extrapolateRight: 'extend'
            });
            const finalTranslateY = offsetTop === 0
                ? translateY
                : Animated.add(translateY, Animated.subtract(scrollOffset, headerTopAnimated).interpolate({
                    inputRange: [0, 1],
                    outputRange: [0, offsetTop],
                    extrapolate: 'clamp'
                }));
            return {
                transform: [{ translateY: finalTranslateY }]
            };
        }
    }, [scrollOffset, headerTopAnimated, offsetTop]);
    const innerProps = useInnerProps(extendObject({}, props, {
        ref: headerRef,
        style: extendObject({}, styles.content, innerStyle, animatedStyle, {
            paddingTop: padding[0] || 0,
            paddingRight: padding[1] || 0,
            paddingBottom: padding[2] || 0,
            paddingLeft: padding[3] || 0
        })
    }, layoutProps), [], { layoutRef });
    return (createElement(Animated.View, innerProps, wrapChildren(props, {
        hasVarDec,
        varContext: varContextRef.current,
        textStyle,
        textProps
    })));
});
const styles = StyleSheet.create({
    content: {
        width: '100%',
        zIndex: 10,
        // harmony 需要手动设置 relative， zIndex 才生效
        position: 'relative'
    }
});
_StickyHeader.displayName = 'MpxStickyHeader';
export default _StickyHeader;
