/*
 * @Author: your name
 * @Date: 2022-04-20 10:03:13
 * @LastEditTime: 2022-04-20 18:25:22
 * @LastEditors: Please set LastEditors
 * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 * @FilePath: /YMJRN/src/common/headtableview/TabView.tsx
 */
import React from 'react';
import ReactNative, { Animated } from 'react-native';
interface Props {
    index: number;
    isActive: boolean;
    containerOffsetY: Animated.Value;
    scrollTopCallback:(y:number) => void;
    sceneHeight: number;
    headerHeight: number;
}

const compose = (WrappedComponent) => {
    const AnimateTabView = Animated.createAnimatedComponent(WrappedComponent);

    class TabView extends React.Component<Props> {
        constructor(props: Props) {
            super(props);
            this.scrollOffsetY = 0;
            this.state = {
                bottomPadding: 0,
            };
            this.mounted = false;
        }

        componentDidMount() {
            this.mounted = true;
            this.addListener();
        }

        componentWillUnmount() {
            this.removeListener();
        }

        addListener() {
            const { containerOffsetY } = this.props;
            containerOffsetY?.addListener(this.tabViewScrollHandler);
        }

        removeListener() {
            const { containerOffsetY } = this.props;
            containerOffsetY?.removeListener(this.tabViewScrollHandler);
        }

        scrollTo(e) {
            if (this._scrollViewRef) {
                if (this._scrollViewRef?.scrollTo) {
                    this._scrollViewRef.scrollTo({ x: 0, y: e.y, animated: false });
                } else if (this._scrollViewRef?.scrollToOffset) {
                    this._scrollViewRef.scrollToOffset({ offset: e.y, animated: false });
                }
            }
        }

        // other TabView sync OffsetY
        tabViewScrollHandler = (e) => {
            const { headerHeight, isActive } = this.props;
            console.log("tabViewScrollHandler",e.value);
            if (e.value<=0) {
                this.props.scrollTopCallback&&this.props.scrollTopCallback(e.value)
            }
            if (!isActive) {
                if (e.value > headerHeight && this.scrollOffsetY < headerHeight) {
                    this.scrollTo({ y: headerHeight });
                } else {
                    this.scrollTo({ y: e.value });
                }
            }
        };

        // contentHeight changed，adjust offset
        adjustScrollOffset = () => {
            if (this.mounted) {
                this.mounted = false;
                const { containerOffsetY, headerHeight } = this.props;
                const scrollValue = containerOffsetY._value > headerHeight ? headerHeight : containerOffsetY._value;
                this.scrollTo({ y: scrollValue });
            }
        };

        // calculate the bottom occupancy height
        onContentSizeChange = (contentWidth, contentHeight) => {
            const { bottomPadding } = this.state;
            const { headerHeight, sceneHeight } = this.props;
            const remainingHeight = contentHeight - sceneHeight;

            if (bottomPadding <= 0) {
                const makePaddingBottom = sceneHeight - contentHeight;
                this.setState({ bottomPadding: makePaddingBottom });
            } else if (remainingHeight > 1) {
                // The content height exceeds the container height，adjust Tab Offset，and reduce excess occupancy bottomPadding
                this.adjustScrollOffset();
                const newBottomPadding = remainingHeight > bottomPadding ? 0 : bottomPadding - remainingHeight;
                if (newBottomPadding != bottomPadding) {
                    this.setState({ bottomPadding: newBottomPadding });
                }
            }
        };

        getScrollListener = (isActive) => {
            if (isActive) {
                return Animated.event([{ nativeEvent: { contentOffset: { y: this.props.containerOffsetY } } }], {
                    useNativeDriver: true,
                    listener: this.onScroll,
                });
            } else {
                return this.onScroll;
            }
        };

        onScroll = (e) => {
            this.scrollOffsetY = e.nativeEvent.contentOffset.y;
        };

        scrollToIndex = (e) => {
            this._scrollViewRef&&this._scrollViewRef.scrollToIndex(e);
        };

        render() {
            const { isActive, children, headerHeight, forwardedRef, contentContainerStyle, custref,...restProps } = this.props;
            const { bottomPadding } = this.state;
            const scrollListener = this.getScrollListener(isActive);
            return (
                <AnimateTabView
                    ref={(ref) => {
                        this._scrollViewRef = ref;
                        if (forwardedRef) {
                            if (forwardedRef instanceof Function) {
                                forwardedRef(ref);
                            } else if (typeof forwardedRef === 'object' && forwardedRef.hasOwnProperty('current')) {
                                forwardedRef.current = ref;
                            }
                        }
                        if (custref&&typeof(custref)=="function") {
                            custref(this);
                        }
                    }}
                    onScroll={scrollListener}
                    onContentSizeChange={this.onContentSizeChange}
                    contentContainerStyle={{
                        ...contentContainerStyle,
                        paddingTop: headerHeight,
                        paddingBottom: bottomPadding,
                    }}
                    overScrollMode="never"
                    scrollEventThrottle={16}
                    directionalLockEnabled={true}
                    showsVerticalScrollIndicator={false}
                    automaticallyAdjustContentInsets={false}
                    {...restProps}>
                    {children}
                </AnimateTabView>
            );
        }
    }

    return React.forwardRef((props, ref) => {
        return <TabView {...props} forwardedRef={ref} />;
    });
};

export const FlatList = compose(ReactNative.FlatList);
export const ScrollView = compose(ReactNative.ScrollView);
