/*
 * @Author: your name
 * @Date: 2022-04-20 10:05:31
 * @LastEditTime: 2022-04-20 19:53:00
 * @LastEditors: Please set LastEditors
 * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 * @FilePath: /YMJRN/src/common/headtableview/ScrollTabView.tsx
 */
import React, { Component, RefObject } from 'react';
import {
    View,
    Animated,
    ScrollView,
    Dimensions,
    Platform,
    StyleSheet,
    ViewStyle,
    TextStyle,
    InteractionManager,
    PanResponder,
} from 'react-native';
import SceneComponent from './SceneComponent';


interface Props {
    childrenScrollY?:(y:number) => void;
    renderScrollHeader?: (p: any) => React.ReactElement;
    renderLeftView?:(p:any) => React.ReactElement;
    rightBgView?:(p:any) => React.ReactElement;
    insetValue?: number; // 状态栏的高度，也就是TabBar距离顶部状态栏的距离
    headerHeight?: number;
    style?: ViewStyle;
    contentProps?: object;
    rightViewStyle?:object;
    LRViewStyle?:object;
}

const DEFAULT_PROPS = {
    insetValue: 0,
    contentProps: {},
};

const IS_IOS = Platform.OS === 'ios';
const dw = Dimensions.get('window').width;
const dh = Dimensions.get('window').height;

export default class ScrollHeadTabView extends Component<Props> {
    static defaultProps = DEFAULT_PROPS;

    constructor(props: Props) {
        super(props);
        const containerWidth = dw;
        const containerHeight = dh;
        const containerOffsetY = new Animated.Value(0);

        
        this.state = {
            containerOffsetY,
            containerWidth,
            containerHeight,
        };


        this._contentScrollArr = [];
        this._headScrollPanY = 0;

        this._panResponder = PanResponder.create({
            // 要求成为响应者：
            //this.refs[RefsConstant.HOME_DEV_LIST].setRefreshFunc(false);
            onStartShouldSetPanResponder: (evt, gestureState) => false,
            onStartShouldSetPanResponderCapture: (evt, gestureState) => false,
            onMoveShouldSetPanResponder: (evt, gestureState) => false,
            onMoveShouldSetPanResponderCapture: (evt, gestureState) => {
                let needMove=false;

                if(Math.abs(gestureState.dy)>0 ){
                    needMove = true;
                }

                if (this.props.locked) {
                    needMove = false;
                }

                if (Math.abs(gestureState.dy) > Math.abs(gestureState.dx)&&needMove) {
                    return true;
                }          
            },

            onPanResponderGrant: (evt, gestureState) => {
                // 开始手势操作。给用户一些视觉反馈，让他们知道发生了什么事情！
                console.log('onPanResponderGrant');
                // gestureState.{x,y} 现在会被设置为0
                if ((gestureState.dy < 0) || (gestureState.dy > 0)) {
                    let index = 0;
                    let scrollOffsetY = (this._contentScrollArr[index]&&this._contentScrollArr[index].scrollOffsetY)?this._contentScrollArr[index].scrollOffsetY:0;
                    this._headScrollPanY = Math.min(Math.abs(scrollOffsetY?scrollOffsetY:0),this.props.headerHeight);
                }
            },
            onPanResponderMove: (evt, gestureState) => {
                // 最近一次的移动距离为gestureState.move{X,Y}
                console.log('onPanResponderMove');
                console.log('滑动参数：dx='+gestureState.dx +'，dy='+gestureState.dy);
                // 从成为响应者开始时的累计手势移动距离为gestureState.d{x,y}
                if ((gestureState.dy < 0) || (gestureState.dy > 0)) {
                    let fromY = this._headScrollPanY||0;
                    this.goToScroll({x:0,y:fromY-(gestureState.dy)});
                }
            },
            //是否可以释放响应者角色让给其他组件
            onPanResponderTerminationRequest: (evt, gestureState) => true,
            onPanResponderRelease: (evt, gestureState) => {
                // 用户放开了所有的触摸点，且此时视图已经成为了响应者。
                console.log('onPanResponderRelease');
                // 一般来说这意味着一个手势操作已经成功完成。
                if ((gestureState.dy < 0) || (gestureState.dy > 0)) {
                    let index = 0;
                    let scrollOffsetY = (this._contentScrollArr[index]&&this._contentScrollArr[index].scrollOffsetY)?this._contentScrollArr[index].scrollOffsetY:0;

                    this._headScrollPanY = Math.min(Math.abs(scrollOffsetY?scrollOffsetY:0),this.props.headerHeight);
                }
                
            },
            onPanResponderTerminate: (evt, gestureState) => {
                // 另一个组件已经成为了新的响应者，所以当前手势将被取消。
                console.log('onPanResponderTerminate');
            },
            onShouldBlockNativeResponder: (evt, gestureState) => {
                // 返回一个布尔值，决定当前组件是否应该阻止原生组件成为JS响应者
                // 默认返回true。目前暂时只支持android。
                return true;
            },
        });
    }

    componentDidMount() {
        // Fix（ViewPager version > 5.X）initialPage does not work on Android with Hermes
        
    }

    componentDidUpdate(prevProps) {
        
    }

    componentWillUnmount() {
        
    }


    goToScroll = (positon={x:0,y:0}) => {
        this.props.childrenScrollY&&this.props.childrenScrollY(positon.y);
        let index = 0;
        let scrollOffsetY = (this._contentScrollArr[index]&&this._contentScrollArr[index].scrollOffsetY)?this._contentScrollArr[index].scrollOffsetY:0;

        
        if (positon.y > this.props.headerHeight && this.scrollOffsetY < this.props.headerHeight) {
            this._contentScrollArr[index]&&this._contentScrollArr[index].scrollTo&&this._contentScrollArr[index].scrollTo({y:this.props.headerHeight});;
        } else {
            this._contentScrollArr[index]&&this._contentScrollArr[index].scrollTo&&this._contentScrollArr[index].scrollTo({y:positon.y});;
        }
    };
    
    //渲染关联视图
    renderLeftView = () => {
        const { renderScrollHeader, headerHeight ,renderLeftView} = this.props;
        const { containerOffsetY, containerWidth } = this.state;
        if (!renderLeftView) return null;
        
        return (
            <Animated.View
                style={{
                    // position: 'absolute',
                    // zIndex: 10,
                    // top: 0,
                    opacity:containerOffsetY.interpolate({
                        inputRange: [0, headerHeight,headerHeight+10],
                        outputRange: [0, 1,1],
                    }),
                    transform: [
                        {
                            translateY: containerOffsetY.interpolate({
                                inputRange: [0, headerHeight,headerHeight+10],
                                outputRange: [headerHeight, 0,0],
                            }),
                        },
                    ],
                }}
                >
                {renderLeftView()}
            </Animated.View>
        );
    };

    //渲染关联视图
    renderRightView = () => {
        const { containerOffsetY, containerWidth } = this.state;
        const { rightViewStyle,headerHeight,rightBgView} = this.props;

        return <Animated.View style={[rightViewStyle,{
            // transform: [
            //     {
            //         translateY: containerOffsetY.interpolate({
            //             inputRange: [0, headerHeight,headerHeight+10],
            //             outputRange: [0, 0,0],
            //         }),
            //     },
            // ],
        }]}>
                {rightBgView&&<Animated.View
                style={{
                    position:"absolute",
                    top:0,
                    left:0,
                    opacity:containerOffsetY.interpolate({
                        inputRange: [0, headerHeight/2,headerHeight,headerHeight+10],
                        outputRange: [0, 1,1,1],
                    }),
                    transform: [
                        {
                            translateY: containerOffsetY.interpolate({
                                inputRange: [0, headerHeight,headerHeight+10],
                                outputRange: [headerHeight, 0,0],
                            }),
                        },
                    ],
                }}
                >
                {rightBgView()}    
                </Animated.View>}
                {this.renderScrollableContent()}
            </Animated.View>
    };

    // 渲染可滑动头部
    renderHeader = () => {
        const { renderScrollHeader, headerHeight } = this.props;
        const { containerOffsetY, containerWidth } = this.state;
        if (!renderScrollHeader) return null;

        return (
            <Animated.View
                style={{
                    position: 'absolute',
                    zIndex: 10,
                    top: 0,
                    width: containerWidth,
                    transform: [
                        {
                            translateY: containerOffsetY.interpolate({
                                inputRange: [0, headerHeight],
                                outputRange: [0, -headerHeight],
                            }),
                        },
                    ],
                }}
                {...this._panResponder.panHandlers}
                >
                {renderScrollHeader()}
            </Animated.View>
        );
    };


    _shouldRenderSceneKey = (idx, currentPageKey) => {
        let numOfSibling = 0;
        return idx < currentPageKey + numOfSibling + 1 && idx > currentPageKey - numOfSibling - 1;
    };

    _keyExists = (sceneKeys, key) => {
        return sceneKeys.find((sceneKey) => key === sceneKey);
    };

    _makeSceneKey = (child, idx) => {
        return child.props.tabLabel + '_' + idx;
    };

    renderScrollableContent = () => {
        const scenes = this._composeScenes();
        if (scenes&&Array.isArray(scenes)&&scenes.length>0) {
            return scenes
        }
    };

    _creatSceneParams = (index) => {
        const { renderScrollHeader, headerHeight, insetValue } = this.props;
        const { containerOffsetY, containerHeight } = this.state;
        if (!renderScrollHeader) {
            return { isActive: 0 == index };
        }
        const params = { index, isActive: 1, containerOffsetY, headerHeight,custref:(ref)=>{
            this._contentScrollArr[index] = ref;
        },scrollTopCallback:()=>{
            this._headScrollPanY = 1;
        }};
        params.sceneHeight = headerHeight + containerHeight - insetValue;
        return params;
    };

    _composeScenes = () => {
        return this._children().map((child, idx) => {
            if(idx!=0){
                return React.cloneElement(child)
            }
            let key = this._makeSceneKey(child, idx);
            // 如果有scrollHeader，标签页必须保持update状态
            const showUpdate = this.props.renderScrollHeader
                ? true
                : this._shouldRenderSceneKey(idx, 0);
            return (
                <SceneComponent key={child.key} shouldUpdated={showUpdate} style={{ width: this.state.containerWidth }}>
                    {this._keyExists([key], key) ? (
                        React.cloneElement(child, this._creatSceneParams(idx))
                    ) : (
                        <View tabLabel={child.props.tabLabel} />
                    )}
                </SceneComponent>
            );
        });
    };

    _handleLayout = (e) => {
        const { width, height } = e.nativeEvent.layout;

        if (width && width > 0 && Math.round(width) !== Math.round(this.state.containerWidth)) {
            if (IS_IOS) {
                const containerWidthAnimatedValue = new Animated.Value(width);
                // Need to call __makeNative manually to avoid a native animated bug. See
                // https://github.com/facebook/react-native/pull/14435
                containerWidthAnimatedValue.__makeNative();
                this.setState({ containerWidth: width });
            } else {
                this.setState({ containerWidth: width });
            }
            
        }
        if (height && height > 0 && Math.round(height) !== Math.round(this.state.containerHeight)) {
            this.setState({ containerHeight: height });
        }
    };

    _children = (children = this.props.children) => {
        return React.Children.map(children, (child) => child);
    };

    render() {
        
        return (
            <View style={[styles.container, this.props.style]} onLayout={this._handleLayout}>
                {this.renderHeader()}
                <View style={[{flexDirection: 'row',},this.props.LRViewStyle]}>
                {typeof(this.props.renderLeftView)=="function"&&this.renderLeftView()}
                {typeof(this.props.renderLeftView)=="function"&&this.renderRightView()}
                </View>
                {typeof(this.props.renderLeftView)!="function"&&this.renderScrollableContent()}
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        position: 'relative',
        flex: 1,
    },
});
