import * as React from "react";
import { Animated } from "react-native";

import { isFirstComponentScreenPicker } from "@applicaster/zapp-react-native-utils/componentsUtils";
import { useRefWithInitialValue } from "@applicaster/zapp-react-native-utils/reactHooks/state/useRefWithInitialValue";
import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
import { Overlay } from "./Overlay";

import { ScreenRevealManager } from "./ScreenRevealManager";
import {
  emitScreenRevealManagerIsReadyToShow,
  emitScreenRevealManagerIsNotReadyToShow,
} from "./utils";

export const TIMEOUT = 300; // 300 ms

const HIDDEN = 0; // opacity = 0

export const SHOWN = 1; // opacity = 1

type Props = {
  componentsToRender: ZappUIComponent[];
  backgroundColor?: string;
};

export const withScreenRevealManager = (Component) => {
  return function WithScreenRevealManager(props: Props) {
    const { componentsToRender } = props;

    const [isContentReadyToBeShown, setIsContentReadyToBeShown] =
      React.useState(false);

    const [isShowOverlay, setIsShowOverlay] = React.useState(true);

    const theme = useTheme<BaseThemePropertiesTV>();

    const handleSetIsContentReadyToBeShown = React.useCallback(() => {
      setIsContentReadyToBeShown(true);
    }, []);

    const managerRef = useRefWithInitialValue<ScreenRevealManager>(
      () =>
        new ScreenRevealManager(
          componentsToRender,
          handleSetIsContentReadyToBeShown
        )
    );

    const opacityRef = useRefWithInitialValue<Animated.Value>(
      () => new Animated.Value(SHOWN)
    );

    React.useEffect(() => {
      if (!isContentReadyToBeShown) {
        emitScreenRevealManagerIsNotReadyToShow();
      } else {
        emitScreenRevealManagerIsReadyToShow();
      }
    }, [isContentReadyToBeShown]);

    React.useEffect(() => {
      if (isContentReadyToBeShown) {
        Animated.timing(opacityRef.current, {
          toValue: HIDDEN,
          duration: TIMEOUT,
          useNativeDriver: true,
        }).start(() => {
          setIsShowOverlay(false);
        });
      }
    }, [isContentReadyToBeShown]);

    if (isFirstComponentScreenPicker(componentsToRender)) {
      // for screen-picker with have additional internal ComponentsMap, no need to add this wrapper
      return <Component {...props} initialNumberToLoad={1} />;
    }

    return (
      <>
        <Component
          {...props}
          initialNumberToLoad={
            managerRef.current.numberOfComponentsWaitToLoadBeforePresent
          }
          onLoadFinishedFromScreenRevealManager={
            managerRef.current.onLoadFinished
          }
          onLoadFailedFromScreenRevealManager={managerRef.current.onLoadFailed}
        />
        {isShowOverlay ? (
          <Overlay
            opacity={opacityRef.current}
            backgroundColor={
              props.backgroundColor ?? theme.app_background_color
            }
          />
        ) : null}
      </>
    );
  };
};
