import * as React from "react";
import {
  Dimensions,
  Platform,
  StyleSheet,
  View,
  ViewStyle,
} from "react-native";
import { Edge, SafeAreaView } from "react-native-safe-area-context";
import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
import { PlayerDetails } from "./PlayerDetails";
import { playerDimensionsHack } from "./utils";
import { useDelayedPlayerDetails } from "./hooks";

import {
  AnimatedScrollModal,
  AnimatedVideoPlayerComponent,
  AnimationComponent,
  ComponentAnimationType,
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";

const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = Dimensions.get("screen");

type DimensionsT = {
  width: number | string;
  height: number | string | undefined;
  aspectRatio?: number;
};

type Configuration = {
  [key: string]: any;
  tablet_landscape_sidebar_width?: string;
  tablet_landscape_player_container_background_color?: string;
};

type Props = {
  entry: ZappEntry;
  style: ViewStyle & DimensionsT;
  containerStyle?: ViewStyle;
  inline?: boolean;
  docked?: boolean;
  pip?: boolean;
  isModal?: boolean;
  fullscreen?: boolean;
  isTabletPortrait?: boolean;
  children: (playerDimensions: DimensionsT) => React.ReactNode;
  configuration: Configuration;
};

const defaultStyles = StyleSheet.create({
  playerContainer: { position: "relative", alignSelf: "center", zIndex: 200 },
  playerDetails: { flex: 1, paddingTop: 20 },
  flex: { flex: 1 },
});

const orientationStyles = StyleSheet.create({
  landscape: { flexDirection: "row" },
  portrait: { flexDirection: "column" },
});

const directionStyles = (isTabletLandscape: boolean): ViewStyle => {
  if (isTabletLandscape) {
    return orientationStyles.landscape;
  }

  return orientationStyles.portrait;
};

const getScreenAspectRatio = () => {
  const longEdge = Math.max(SCREEN_WIDTH, SCREEN_HEIGHT);
  const shortEdge = Math.min(SCREEN_WIDTH, SCREEN_HEIGHT);

  return longEdge / shortEdge;
};

const safeAreaStyles = (
  configuration: Configuration,
  isTablet: boolean
): ViewStyle => {
  const tablet_landscape_player_container_background_color =
    configuration?.tablet_landscape_player_container_background_color;

  return {
    backgroundColor: isTablet
      ? tablet_landscape_player_container_background_color
      : "transparent",
  };
};

const getEdges = (isTablet: boolean, isInlineModal: boolean) => {
  if (isTablet) {
    return ["top"];
  }

  if (!isInlineModal && Platform.OS === "android") {
    return [];
  }

  return ["top"];
};

const getTabletWidth = (
  configuration: Configuration,
  dimensions: DimensionsT
) => {
  const tablet_landscape_sidebar_width =
    configuration?.tablet_landscape_sidebar_width;

  const { width } = dimensions;

  const sidebarWidth = Number(tablet_landscape_sidebar_width?.replace("%", ""));

  if (tablet_landscape_sidebar_width?.includes("%")) {
    return Number(width) * (1 - sidebarWidth / 100);
  }

  if (Number.isNaN(sidebarWidth)) {
    return Number(width) * 0.65;
  }

  return Number(width) - sidebarWidth;
};

const PlayerWrapperComponent = (props: Props) => {
  const {
    entry,
    style,
    containerStyle,
    inline,
    docked,
    isModal,
    children,
    isTabletPortrait,
    configuration,
    pip,
  } = props;

  const isTablet = useIsTablet();

  const isInlineModal = inline && isModal;

  // Mounting the PlayerDetails component is a resource-intensive process.
  // Therefore, for performance reasons, we mount it with a delay to make the rotation process as smooth as possible.
  // The flow is as follows: the rotation occurs first, and then, after a short delay, we mount the PlayerDetails component.
  // This helps to avoid blocking the rotation and any animations related to the rotation.
  const isShowPlayerDetails = useDelayedPlayerDetails({
    isInline: isInlineModal,
    isDocked: docked,
    isPip: pip,
  });

  const isTabletLandscape = !isTV() && isTablet && !isTabletPortrait;

  const tabletWidth = getTabletWidth(configuration, style);

  const baseDimensions: DimensionsT = React.useMemo(
    () => ({
      width:
        isInlineModal && !docked && isTabletLandscape ? tabletWidth : "100%",
      height: undefined,
    }),
    [isInlineModal, tabletWidth, docked]
  );

  const playerDimensions: DimensionsT = React.useMemo(
    () => ({
      ...baseDimensions,
      width: isInlineModal && docked ? undefined : baseDimensions.width,
      aspectRatio: !isInlineModal && !pip ? getScreenAspectRatio() : 16 / 9,
    }),
    [baseDimensions, isInlineModal, pip]
  );

  const containerDimensions: DimensionsT = React.useMemo(
    () => ({
      ...baseDimensions,
      aspectRatio:
        isInlineModal && docked ? undefined : playerDimensions.aspectRatio,
    }),
    [baseDimensions, isInlineModal, docked, playerDimensions.aspectRatio]
  );

  const WrapperView = React.useMemo(() => (isTV() ? View : SafeAreaView), []);

  const childrenStyles = React.useMemo(
    () => ({ ...playerDimensions, ...playerDimensionsHack }),
    [containerDimensions, playerDimensionsHack]
  );

  return (
    <WrapperView
      edges={getEdges(isTablet, isInlineModal) as readonly Edge[]}
      style={[
        safeAreaStyles(configuration, isTablet),
        style,
        playerDimensionsHack,
      ]}
    >
      <AnimationComponent
        animationType={ComponentAnimationType.moveUpComponent}
        additionalData={{ saveArea: true }}
        style={[directionStyles(isTabletLandscape), defaultStyles.flex]}
      >
        <View
          testID={`${entry?.id}-player-container`}
          style={[
            defaultStyles.playerContainer,
            containerDimensions,
            containerStyle,
            playerDimensionsHack,
          ]}
        >
          <AnimationComponent
            animationType={ComponentAnimationType.moveUpComponent}
            style={isTabletLandscape ? defaultStyles.flex : undefined}
            additionalData={{
              useLayoutMeasure: isTabletLandscape,
              disableAnimatedComponent: !isTabletLandscape,
              resetAnimationValue: isTabletLandscape && docked,
            }}
          >
            <AnimatedVideoPlayerComponent>
              {children(childrenStyles)}
            </AnimatedVideoPlayerComponent>
          </AnimationComponent>
        </View>

        <AnimatedScrollModal>
          {isShowPlayerDetails && (
            <AnimationComponent
              animationType={ComponentAnimationType.componentFade}
              style={defaultStyles.flex}
            >
              <PlayerDetails
                configuration={configuration}
                style={defaultStyles.playerDetails}
                entry={entry}
                isTabletLandscape={isTabletLandscape}
                isTablet={isTablet}
              />
            </AnimationComponent>
          )}
        </AnimatedScrollModal>
      </AnimationComponent>
    </WrapperView>
  );
};

export const PlayerWrapper = PlayerWrapperComponent;
