import * as React from "react";
import { View, StyleSheet } from "react-native";
import * as R from "ramda";

import { ScreenLayoutContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenLayoutContext";
import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
import { ifEmptyUseFallback } from "@applicaster/zapp-react-native-utils/cellUtils";
import {
  useCurrentScreenData,
  useNavbarState,
} from "@applicaster/zapp-react-native-utils/reactHooks/screen";
import { useTheme } from "@applicaster/zapp-react-native-utils/theme";

import { useScreenConfiguration } from "../../River/useScreenConfiguration";
import {
  findMenuPlugin,
  getNavigationProps,
  routeIsPlayerScreen,
} from "@applicaster/zapp-react-native-utils/navigationUtils";
import { isApplePlatform } from "@applicaster/zapp-react-native-utils/reactUtils";
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
import { NavBarContainer } from "./NavBarContainer";

type ComponentsExtraProps = {
  Background?: Record<string, any>;
  NavBar?: Record<string, any>;
};

type Props = {
  ComponentsExtraProps?: ComponentsExtraProps;
  NavBar: React.ComponentType<any>;
  children: React.ReactNode;
};

function displayFullScreen({ currentRoute, screenData }) {
  const shouldHookBeFullScreen =
    screenData?.hookPlugin?.module?.presentFullScreen;

  return (
    routeIsPlayerScreen(currentRoute) ||
    !!screenData?.general?.present_full_screen ||
    !!shouldHookBeFullScreen
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, height: "100%", width: "100%" },
});

const isTVOS = isApplePlatform();

// eslint-disable-next-line react/display-name
export const ScreenContainer = React.memo(function ScreenContainer({
  children,
  ComponentsExtraProps,
  NavBar,
}: Props) {
  const { screenMarginBottom, resetScreenLayout } =
    React.useContext(ScreenLayoutContext);

  const { currentRoute, screenData } = useNavigation();

  const screen = useCurrentScreenData();

  const { marginBottom, backgroundColor, paddingTop, paddingBottom } =
    useScreenConfiguration(screen?.id);

  const theme = useTheme();
  const getThemeValue = React.useCallback(R.propOr(0, R.__, theme), [theme]);

  React.useEffect(() => {
    resetScreenLayout();
  }, [currentRoute]);

  const fullscreen = React.useCallback(
    displayFullScreen({ currentRoute, screenData }),
    [currentRoute, screenData]
  );

  const themeStyles = React.useMemo(
    () =>
      fullscreen
        ? {}
        : {
            marginBottom: ifEmptyUseFallback(marginBottom, screenMarginBottom),
            backgroundColor: ifEmptyUseFallback(backgroundColor, "transparent"),
            paddingTop: ifEmptyUseFallback(
              paddingTop,
              getThemeValue("component_padding_top")
            ),
            paddingBottom: ifEmptyUseFallback(
              paddingBottom,
              getThemeValue("component_padding_bottom")
            ),
          },
    [
      fullscreen,
      screenMarginBottom,
      marginBottom,
      backgroundColor,
      paddingTop,
      paddingBottom,
    ]
  );

  const viewStyles = React.useMemo(
    () => [styles.container, themeStyles],
    [themeStyles]
  );

  const navigator = useNavigation();
  const { activeRiver } = navigator;
  const { title, visible } = useNavbarState();

  const { plugins = [] } = usePickFromState([
    "appState",
    "remoteConfigurations",
    "plugins",
  ]);

  const navigationProps = getNavigationProps({
    navigator,
    title,
    category: "menu",
  });

  const menuPlugin = React.useMemo(
    () => findMenuPlugin(activeRiver?.navigations, plugins),
    [activeRiver?.navigations]
  );

  const NavBarComponent = React.useMemo(
    () => NavBar || (menuPlugin.module as React.ComponentType<any>),
    []
  );

  const [navBarReady, setNavBarReady] = React.useState(false);

  const navBarContainer = (
    <NavBarContainer isVisible={visible} onReady={setNavBarReady}>
      <NavBarComponent
        ref={ComponentsExtraProps?.NavBar?.ref}
        isVisible={visible}
        menuPlugin={menuPlugin}
        navigationProps={navigationProps}
        {...R.omit(["ref"])(ComponentsExtraProps?.NavBar)}
      />
    </NavBarContainer>
  );

  return (
    <>
      {!isTVOS ? navBarContainer : null}
      {navBarReady ? (
        /**
          Need to re-mount this component on each navigation event
          It's a hack to work around the fact that we don't support
          correct screen rendering in our navigator (shared currentRoute state)
        **/
        <View testID="screen-container" style={viewStyles}>
          {children}
        </View>
      ) : null}
      {/** Render NavBarContainer over ScreenContainer to let tvOS native
              focus manager works correctly to focus nav bar items first **/}
      {isTVOS ? navBarContainer : null}
    </>
  );
});
