import React from "react";
import { equals } from "ramda";
import { Animated, ViewProps, ViewStyle } from "react-native";

import { useScreenOrientationHandler } from "@applicaster/zapp-react-native-ui-components/Components/Screen/orientationHandler";
import { useMemoizedSafeAreaFrameWithActiveState } from "@applicaster/zapp-react-native-ui-components/Components/Screen/hooks";

import { PathnameContext } from "../../Contexts/PathnameContext";
import { ScreenDataContext } from "../../Contexts/ScreenDataContext";
import { ScreenContextProvider } from "../../Contexts/ScreenContext";

const fullWidthDimensions = {
  height: "100%",
  width: "100%",
};

type Props = {
  children: any;
  style: any;
  pointerEvents: ViewProps["pointerEvents"];
  overlayStyle: ViewStyle;
  animating: boolean;
  contentStyle: ViewStyle;
  pathname: string;
  isActive: boolean;
  screenData: NavigationScreenData;
};

export function CurrentScreenContextProvider({
  children,
  ...props
}: {
  children: any;
  pathname: string;
  isActive: boolean;
  screenData: NavigationScreenData;
}) {
  const { pathname, isActive = false, screenData } = props;

  const [initialScreenData, setInitialScreenData] = React.useState(screenData);

  React.useLayoutEffect(() => {
    const screenDataChanged = !equals(initialScreenData, screenData);

    if (isActive && screenDataChanged) {
      setInitialScreenData(screenData);
    }
  }, [initialScreenData, screenData, isActive]);

  return (
    <ScreenDataContext.Provider value={initialScreenData}>
      <PathnameContext.Provider value={pathname}>
        <ScreenContextProvider pathname={pathname}>
          {children}
        </ScreenContextProvider>
      </PathnameContext.Provider>
    </ScreenDataContext.Provider>
  );
}

const withCurrentScreenContext = (Component) =>
  function SceneComponent(props: Props) {
    return (
      <CurrentScreenContextProvider {...props}>
        <Component {...props} />
      </CurrentScreenContextProvider>
    );
  };

/**
 * Animated View container for any purpose.
 * Renders given children with given style object.
 * Optional property: pointer event (e.g. to prevent interaction with animating scene).
 * @param {React.Component} children Just about anything
 * @param {object} style             Container style
 * @param {} pointerEvents           box-none|none|box-only|auto (default)
 * @param overlayStyle
 * @param animating
 * @param contentStyle
 * @param screenUniqueId
 */
function SceneComponent({
  children,
  style,
  pointerEvents = "auto",
  overlayStyle,
  animating,
  contentStyle,
  isActive = false,
  screenData,
}: Props) {
  useScreenOrientationHandler({
    screenData,
    isActive,
  });

  // Use shared memoized frame hook - synchronized with useWaitForValidOrientation
  // to prevent race conditions during orientation changes
  // Pass isActive from props since Scene knows its active state from Transitioner
  const memoFrame = useMemoizedSafeAreaFrameWithActiveState({
    updateForInactiveScreens: false,
    isActive,
  });

  const isAnimating = animating && overlayStyle;

  const dimensions = isAnimating ? fullWidthDimensions : memoFrame;

  return (
    <Animated.View
      pointerEvents={pointerEvents}
      style={[style, contentStyle, dimensions]}
    >
      {children}
      {isAnimating ? <Animated.View style={overlayStyle} /> : null}
    </Animated.View>
  );
}

export const Scene = withCurrentScreenContext(SceneComponent);
