import React, { useMemo } from "react";
import { Animated, Dimensions } from "react-native";

import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation";

import { useConfiguration } from "../utils";
import { usePlugins } from "@applicaster/zapp-react-native-redux/hooks";
import { isBottomTabVisible } from "../../Screen/navigationHandler";

import {
  useSafeAreaFrame,
  useSafeAreaInsets,
} from "react-native-safe-area-context";
import {
  isAndroidPlatform,
  isAndroidVersionAtLeast,
} from "@applicaster/zapp-react-native-utils/reactUtils";
import { getTabBarHeight } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/getTabBarHeight";
import { PROGRESS_BAR_HEIGHT } from "./utils";
import { useIsTablet as getIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
import { useAppSelector } from "@applicaster/zapp-react-native-redux";

export type ModalAnimationContextT = {
  yTranslate: React.MutableRefObject<Animated.AnimatedInterpolation<number>>;
  offsetAnimatedValueRef: React.MutableRefObject<Animated.Value>;
  offset: React.MutableRefObject<number>;
  heightAboveMinimised: number;
  gestureTranslationRef: React.MutableRefObject<Animated.Value>;
  minimisedHeight: number;
};

export const ReactContext = React.createContext<ModalAnimationContextT>({
  yTranslate: React.createRef<Animated.Value | null>(),
  offsetAnimatedValueRef: React.createRef<Animated.Value>(),
  offset: React.createRef<number>(),
  heightAboveMinimised: 0,
  gestureTranslationRef: React.createRef<Animated.Value>(),
  minimisedHeight: 60,
});

const SAFE_AREA_BREAKING_API_VERSION = 35;

export const isOldAndroidDevice =
  isAndroidPlatform() &&
  !isAndroidVersionAtLeast(SAFE_AREA_BREAKING_API_VERSION);

const bottomTabBarHeight = getTabBarHeight();

const Provider = ({ children }: { children: React.ReactNode }) => {
  const { height } = Dimensions.get("window");

  const yTranslate = React.useRef(
    new Animated.Value(height).interpolate<number>({
      inputRange: [0, height],
      outputRange: [0, height],
    })
  );

  const { minimised_height: minimisedHeight } = useConfiguration();

  const {
    videoModalState: { visible, mode },
    currentRoute,
    screenData,
  } = useNavigation();

  const isTabletPortrait = useAppSelector(
    (state) => state.appData.isTabletPortrait
  );

  const plugins = usePlugins();

  const bottomTabsVisible = isBottomTabVisible(
    currentRoute,
    screenData,
    plugins
  );

  const frame = useSafeAreaFrame();
  const insets = useSafeAreaInsets();

  const [heightAboveMinimised, setHeightAboveMinimised] = React.useState(0);

  // memoizing heightAboveMinimised value
  const offset = React.useRef(heightAboveMinimised);

  // Used for memoizing modal y position after start/end of transition
  const offsetAnimatedValueRef = React.useRef(
    new Animated.Value(-offset.current)
  );

  // Used for gesture handling
  const gestureTranslationRef = React.useRef(new Animated.Value(0));

  const videoModalStateRef = React.useRef({ visible, mode });

  React.useEffect(() => {
    videoModalStateRef.current = { visible, mode };
  }, [visible, mode]);

  const translateY = useMemo(() => {
    const maxRange = heightAboveMinimised;

    const combined: Animated.AnimatedAddition<number> = Animated.add(
      offsetAnimatedValueRef.current,
      gestureTranslationRef.current
    );

    return combined.interpolate({
      inputRange: [0, maxRange],
      outputRange: [0, maxRange],
      extrapolate: "clamp",
    });
  }, [visible, heightAboveMinimised]);

  offset.current = heightAboveMinimised;
  yTranslate.current = translateY;

  React.useEffect(() => {
    const collapsedHeight =
      minimisedHeight +
      (bottomTabsVisible ? bottomTabBarHeight : 0) +
      (isOldAndroidDevice ? 0 : insets.bottom) + // insets.bottom is added to properly display docked modal
      PROGRESS_BAR_HEIGHT;

    const heightAboveMinimised = frame.height - collapsedHeight;

    const isLandscape = frame.width > frame.height;

    const isTablet = getIsTablet();

    const shouldIgnoreLandscape = isTablet ? isTabletPortrait : true;

    if (
      heightAboveMinimised !== offset.current &&
      videoModalStateRef.current.mode !== "PIP" &&
      videoModalStateRef.current.mode !== "FULLSCREEN"
    ) {
      if (isLandscape && shouldIgnoreLandscape) return;
      setHeightAboveMinimised(heightAboveMinimised);
      offset.current = heightAboveMinimised;
    }
  }, [frame.height, insets.bottom, bottomTabsVisible, minimisedHeight]);

  return (
    <ReactContext.Provider
      value={useMemo(
        () => ({
          yTranslate,
          offsetAnimatedValueRef,
          offset,
          heightAboveMinimised,
          minimisedHeight,
          gestureTranslationRef,
        }),
        [minimisedHeight, heightAboveMinimised]
      )}
    >
      {children}
    </ReactContext.Provider>
  );
};

export const withModalAnimationProvider = (Component) => {
  const WithProvider = (props) => {
    return (
      <Provider>
        <Component {...props} />
      </Provider>
    );
  };

  return WithProvider;
};
