import React, {
  forwardRef,
  useImperativeHandle,
  useMemo,
  useState,
} from "react";
import { ViewStyle } from "react-native";
import { SceneMap, TabView } from "react-native-tab-view";
import { CollapsibleHeaderTabView } from "react-native-tab-view-collapsible-header";
import { vs } from "../commons";
import { Spinner, View } from "../components";

export type TabProps = {
  children: Array<{
    component: any;
    [key: string]: any;
  }>;

  disableLazy?: boolean;
  enableSwipe?: boolean;
  isRefreshing?: boolean;

  initialPositon?: number;

  containerStyle?: ViewStyle;

  onRefreshing?: () => void;
  onChangeIndex?: (i: number) => void;

  renderHeader?: (i: number) => any;
  renderTabBar?: () => any;
  renderScrollHeader?: () => any;
};

export const Tab = forwardRef((props: TabProps, ref?: any) => {
  const {
    children,

    disableLazy,
    enableSwipe,
    isRefreshing,

    initialPositon,

    containerStyle,

    onRefreshing,
    onChangeIndex,

    renderHeader,
    renderScrollHeader,
  } = props;

  const [index, setIndex] = useState(initialPositon || 0);

  const routes = useMemo(() => {
    return children.map((item, index) => ({
      key: `tab_${index}`,
      component:
        typeof item.component === "function"
          ? item.component
          : () => item.component,
    }));
  }, [children]);

  const onIndexChange = (i: number) => {
    if (i < 0 || i >= routes.length) return;
    onChangeIndex?.(i);
    setIndex(i);
  };

  useImperativeHandle(ref, () => ({
    set: onIndexChange,
    prev: () => onIndexChange(index - 1),
    next: () => onIndexChange(index + 1),
  }));

  const renderScene = useMemo(() => {
    return SceneMap(
      routes.reduce(
        (result, item) => ({
          ...result,
          [item.key]: item.component,
        }),
        {}
      )
    );
  }, [routes]);

  const renderRefreshControl = () => {
    return <Spinner size={vs(30)} mv={vs(15)} />;
  };

  const MyTab = renderScrollHeader ? CollapsibleHeaderTabView : TabView;

  return (
    <View flex1>
      {/* tabbar */}
      {renderHeader?.(index)}

      {/* tabview */}
      <MyTab
        lazy={!disableLazy}
        swipeEnabled={!!enableSwipe}
        refreshHeight={vs(30) + vs(15) * 2}
        navigationState={{ index, routes }}
        style={[{ flexGrow: 1 }, containerStyle]}
        onIndexChange={onIndexChange}
        renderScene={renderScene}
        renderTabBar={() => null}
        {...props}
        {...(typeof isRefreshing === "boolean"
          ? {
              isRefreshing,
              onStartRefresh: onRefreshing,
              renderRefreshControl,
            }
          : {})}
      />
    </View>
  );
});
