import * as React from "react";
import * as R from "ramda";

import { StyleSheet, View } from "react-native";

import { getNavigationProps } from "@applicaster/zapp-react-native-utils/navigationUtils";
import {
  useDimensions,
  useGetBottomTabBarHeight,
  useNavbarState,
  useNavigation,
} from "@applicaster/zapp-react-native-utils/reactHooks";
import { Transitioner } from "@applicaster/zapp-react-native-ui-components/Components/Transitioner";
import { transitionConfig } from "@applicaster/zapp-react-native-ui-components/Components/Transitioner/config";
import { Screen } from "@applicaster/zapp-react-native-ui-components/Components/Screen";
import { useIsRTL } from "@applicaster/zapp-react-native-utils/localizationUtils";

import {
  getNavigationPluginModule,
  isVideoOverlayVisible,
} from "./layoutHelpers";

import {
  getMenuPlugin,
  isBottomTabVisible,
  isMenuVisible,
  SIDE_MENU_PLUGIN_ID,
} from "@applicaster/zapp-react-native-ui-components/Components/Screen/navigationHandler";
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";

import {
  MenuToggleContextType,
  useMenuToggleContext,
} from "@applicaster/zapp-react-native-ui-components/Contexts/MenuToggleContext";
import { VideoModal } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal";
import { withDimensionsProvider } from "@applicaster/zapp-react-native-utils/dimensionsProvider";
import { withModalAnimationProvider } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";

import { ZappHooksModal } from "@applicaster/zapp-react-dom-ui-components/Components/ZappHooksModal";
import { useListenEventBusEvent } from "@applicaster/zapp-react-native-utils/reactHooks/useListenEventBusEvent";
import {
  PushTopicManager,
  PushTopicManagerConsts,
  PushTopicManagerEvents,
} from "@applicaster/zapp-react-native-bridge/PushNotifications/PushTopicManager";
import { useSafeAreaInsets } from "react-native-safe-area-context";

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

const LayoutWithMenu = () => {
  const {
    plugins,
    appState: { appReady },
  } = usePickFromState(["plugins", "appState"]);

  const {
    toggleMenu,
    setToggleMenu,
    openMenu,
    setOpenMenu,
    closeMenu,
    setCloseMenu,
  } = useMenuToggleContext();

  const dimensions = useDimensions("screen", { fullDimensions: true });
  const isRTL = useIsRTL();
  const navigator = useNavigation();
  const bottomTabBarHeight = useGetBottomTabBarHeight();
  const { bottom: safeAreaBottomInset } = useSafeAreaInsets();
  const { title } = useNavbarState();

  const { activeRiver, videoModalState, isVideoModalDocked } = navigator;

  const Menu = React.useMemo(
    () =>
      getNavigationPluginModule(
        "menu",
        activeRiver,
        plugins
      ) as React.ComponentType<
        MobileNavBarPluginProps &
          MenuToggleContextType & {
            navigator: QuickBrickAppNavigator;
          }
      >,
    [activeRiver]
  );

  const isSideMenu = React.useMemo(() => {
    const menuPlugin = getMenuPlugin(navigator.screenData, plugins);

    return menuPlugin?.identifier === SIDE_MENU_PLUGIN_ID;
  }, [navigator.screenData, plugins]);

  /** BTB shown when videoModalState - visible & minimized, maximized & animation gesture is active
   * otherwise hidden if videoModalState - visible
   * also check isMenuVisible
   */
  const showMenu = React.useMemo(() => {
    const menuVisible = isMenuVisible(
      navigator.currentRoute,
      navigator.screenData,
      plugins
    );

    if (isSideMenu) {
      return menuVisible;
    }

    return menuVisible && isVideoOverlayVisible(videoModalState);
  }, [
    plugins,
    isSideMenu,
    navigator.currentRoute,
    navigator.screenData,
    videoModalState.visible,
    videoModalState.mode,
  ]);

  const showBottomTabs = React.useMemo(() => {
    const bottomTabsVisible = isBottomTabVisible(
      navigator.currentRoute,
      navigator.screenData,
      plugins
    );

    return bottomTabsVisible && isVideoOverlayVisible(videoModalState);
  }, [
    videoModalState.visible,
    videoModalState.mode,
    navigator.currentRoute,
    navigator.screenData,
  ]);

  const paddingBottom = showBottomTabs
    ? bottomTabBarHeight + safeAreaBottomInset
    : 0; // if activeRiver?.navigations has quick-brick-bottom-tabs - append bottomTabBarHeight as padding

  const contentStyle = React.useMemo(
    () =>
      StyleSheet.flatten([
        styles.container,
        {
          paddingBottom,
          opacity: videoModalState.visible && !isVideoModalDocked ? 0 : 1,
        },
      ]),
    [videoModalState.visible, isVideoModalDocked]
  );

  const menuProps = React.useMemo(() => {
    const navigationProps = getNavigationProps({
      navigator,
      title,
      category: "menu",
    }) ?? {
      selected: "",
      title: "",
      home: false,
      rules: {} as ZappNavBarRules,
      assets: {} as ZappNavBarAssets,
      styles: {},
      nav_items: [] as NavBarItem[],
    };

    const props = {
      ...navigationProps,
      dimensions: { window: dimensions },
      bottomTabBarHeight,
      isRTL,
      navigator,
    };

    return { ...props, id: navigator.currentRoute };
  }, [dimensions, isRTL, bottomTabBarHeight, navigator.currentRoute]);

  useListenEventBusEvent(
    PushTopicManagerConsts.PushTopicManagerSubscriptionID,
    PushTopicManagerConsts.PushTopicManagerSource,
    Object.keys(PushTopicManagerEvents),
    PushTopicManager.getInstance().routeEvent
  );

  React.useEffect(() => {
    // getting tags right after subscription
    PushTopicManager.getInstance().prepareTags();
  }, []);

  return (
    <>
      {appReady ? (
        <View style={styles.container}>
          <Transitioner
            transitionConfig={transitionConfig}
            contentStyle={contentStyle}
            isRTL={isRTL}
          >
            <Screen
              key={navigator.currentRoute}
              pathname={navigator.currentRoute} // required by TransitionerComponent
              screenData={navigator.data} // required by TransitionerComponent
            />
          </Transitioner>
        </View>
      ) : null}
      {showMenu ? (
        <Menu
          {...menuProps}
          setToggleMenu={setToggleMenu}
          toggleMenu={toggleMenu}
          openMenu={openMenu}
          setOpenMenu={setOpenMenu}
          closeMenu={closeMenu}
          setCloseMenu={setCloseMenu}
        />
      ) : null}
      {/* depends on active river. @TODO move below screen context */}
      {VideoModal && videoModalState.visible ? <VideoModal /> : null}
      <ZappHooksModal />
    </>
  );
};

export const Layout = R.compose(
  withDimensionsProvider,
  withModalAnimationProvider
)(LayoutWithMenu);
