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

import {
  useSafeAreaInsets,
  useSafeAreaFrame,
} from "react-native-safe-area-context";
import {
  useGetBottomTabBarHeight,
  useNavigation,
} from "@applicaster/zapp-react-native-utils/reactHooks";
import { isLive } from "@applicaster/zapp-react-native-utils/playerUtils";

import { PROGRESS_BAR_HEIGHT } from "./utils";
import { useConfiguration } from "../utils";

export enum PlayerAnimationStateEnum {
  minimize = "minimize",
  maximaze = "maximaze",
  drag_player = "drag_player",
  drag_scroll = "drag_scroll",
}

type PlayerAnimationStateT = number | PlayerAnimationStateEnum | null;

export type ModalAnimationContextT = {
  isActiveGesture: boolean;
  playerAnimationState: PlayerAnimationStateT;
  setPlayerAnimationState: (value: PlayerAnimationStateT) => void;
  startComponentsAnimation: boolean;
  setStartComponentsAnimation: (value: boolean) => void;
  resetPlayerAnimationState: () => void;
  minimisedHeight: number;
  animatedValues: {
    lastScrollY: Animated.Value;
    dragScrollY: Animated.Value;
    dragVideoPlayerY: Animated.Value;
    translateYOffset: Animated.Value;
  };
  lastScrollYValue: React.MutableRefObject<number>;
  scrollPosition: React.MutableRefObject<number>;
  modalSnapPoints: number[];
  lastSnap: number;
  setLastSnap: (value: number) => void;
  tabletLandscapePlayerTopPosition: number;
  setTabletLandscapePlayerTopPosition: (value: number) => void;
  startComponentsAnimationDistance: number;
  progressBarHeight: number;
};

const ReactContext = React.createContext<ModalAnimationContextT>({
  isActiveGesture: false,
  playerAnimationState: null,
  setPlayerAnimationState: () => null,
  startComponentsAnimation: false,
  setStartComponentsAnimation: () => null,
  resetPlayerAnimationState: () => null,
  minimisedHeight: 60,
  animatedValues: {
    lastScrollY: new Animated.Value(0),
    dragScrollY: new Animated.Value(0),
    dragVideoPlayerY: new Animated.Value(0),
    translateYOffset: new Animated.Value(0),
  },
  lastScrollYValue: null,
  scrollPosition: null,
  modalSnapPoints: [0, 0],
  lastSnap: 0,
  setLastSnap: () => null,
  tabletLandscapePlayerTopPosition: 0,
  setTabletLandscapePlayerTopPosition: () => null,
  startComponentsAnimationDistance: 0,
  progressBarHeight: 0,
});

export function useModalAnimationContext() {
  return useContext<ModalAnimationContextT>(ReactContext);
}

const Provider = ({ children }: { children: React.ReactNode }) => {
  const [playerAnimationState, setPlayerAnimationState] =
    React.useState<PlayerAnimationStateT>(null);

  const [
    tabletLandscapePlayerTopPosition,
    setTabletLandscapePlayerTopPosition,
  ] = React.useState<number>(0);

  const [startComponentsAnimation, setStartComponentsAnimation] =
    React.useState<boolean>(false);

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

  const isLiveItem = isLive(item);
  const { minimised_height: minimisedHeight } = useConfiguration();

  const resetPlayerAnimationState = React.useCallback(() => {
    setPlayerAnimationState(null);
    setStartComponentsAnimation(false);
  }, []);

  // Animated values
  const lastScrollY = React.useRef(new Animated.Value(0)).current;
  const dragScrollY = React.useRef(new Animated.Value(0)).current;
  const translateYOffset = React.useRef(new Animated.Value(0)).current;
  const dragVideoPlayerY = React.useRef(new Animated.Value(0)).current;

  const { height: safeAreaFrameHeight } = useSafeAreaFrame();
  const [height, setHeight] = React.useState<number>(safeAreaFrameHeight);
  const progressBarHeight = isLiveItem ? 0 : PROGRESS_BAR_HEIGHT;
  const { bottom: bottomSafeArea } = useSafeAreaInsets();
  const bottomTabBarHeight = useGetBottomTabBarHeight();
  const startComponentsAnimationDistance = Math.round((height * 60) / 100);

  React.useEffect(() => {
    if (visible && mode === "MAXIMIZED" && height !== safeAreaFrameHeight) {
      setHeight(safeAreaFrameHeight);
    }
  }, [height, safeAreaFrameHeight, mode, visible]);

  /*
    If bottomTabBarHeight is equal 0 it means an app does not use bottomTabBar.
    Because of this we need to minus bottom SafeArea offset.
  */
  const minValue =
    height -
    minimisedHeight -
    (bottomTabBarHeight || bottomSafeArea) -
    progressBarHeight;

  const modalSnapPoints = React.useMemo(() => [0, minValue], [minValue]);
  // Last snap state which will helps us to make smooth responder to scrollview animation
  const [lastSnap, setLastSnap] = React.useState<number>(modalSnapPoints[0]);
  // Extracted animated values which we will use for calculations
  const lastScrollYValue = React.useRef<number>(0);
  const scrollPosition = React.useRef<number>(0);

  return (
    <ReactContext.Provider
      value={{
        startComponentsAnimation,
        setStartComponentsAnimation,
        isActiveGesture: playerAnimationState !== null,
        playerAnimationState,
        setPlayerAnimationState,
        resetPlayerAnimationState,
        minimisedHeight,
        animatedValues: {
          lastScrollY,
          dragScrollY,
          dragVideoPlayerY,
          translateYOffset,
        },
        lastScrollYValue,
        scrollPosition,
        modalSnapPoints,
        lastSnap,
        setLastSnap,
        tabletLandscapePlayerTopPosition,
        setTabletLandscapePlayerTopPosition,
        startComponentsAnimationDistance,
        progressBarHeight,
      }}
    >
      {children}
    </ReactContext.Provider>
  );
};

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

  return WithProvider;
};
