import React, { useContext, useEffect, useRef, useState } from 'react';
import {
  SafeAreaProvider,
  useSafeAreaInsets,
} from 'react-native-safe-area-context';
import {
  NavigationContainer as ReactNavigationContainer,
  NavigationIndependentTree,
} from '@react-navigation/native';
import {
  createStackNavigator,
  StackNavigationOptions,
  TransitionPresets,
} from '@react-navigation/stack';
import { DeviceEventEmitter } from 'react-native';
import StackScreen from './StackScreen';
import ModalScreen from './ModalScreen';
import Navigator from './Navigator';
import { getModalOptions, getStackOptions } from './utils';
import { NavigationContainerProps } from './types';
import { ApplicationContext, MiniAppContext } from '../Context';
import Localize from './Localize';
import { Colors, defaultTheme } from '../Consts';
import { HeaderLeft } from './Components/HeaderLeft';
import { HeaderRight } from './Components/HeaderRight';
import { HeaderTitle } from './Components/HeaderTitle';
import { HeaderBackground } from './Components/HeaderBackground';

const Stack = createStackNavigator();

const NavigationContainer: React.FC<NavigationContainerProps> = ({
  screen,
  theme = defaultTheme,
  options,
  maxApi,
  initialParams,
  localize = new Localize({ vi: {}, en: {} }),
  features = {
    enableBottomTabAnimation: true,
    enableHapticDialog: true,
    enableForceFoundationList: false,
    enableHapticBottomTab: true,
  },
}) => {
  const context = useContext<any>(MiniAppContext);
  const [currentContext, setCurrentContext] = useState({});

  return (
    <SafeAreaProvider>
      <MiniAppContext.Provider
        value={{
          ...context,
          ...currentContext,
          features: {
            ...context?.features,
            ...features,
          },
        }}
      >
        <Navigation
          screen={screen}
          theme={theme}
          options={options}
          maxApi={maxApi}
          setCurrentContext={setCurrentContext}
          initialParams={initialParams}
          localize={localize}
        />
      </MiniAppContext.Provider>
    </SafeAreaProvider>
  );
};

const Navigation: React.FC<any> = ({
  screen,
  theme = defaultTheme,
  options,
  maxApi,
  initialParams,
  setCurrentContext,
  localize = new Localize({ vi: {}, en: {} }),
}) => {
  const context = useContext<any>(MiniAppContext);
  const navigationRef = useRef<any>(null);
  const isReady = useRef(false);
  const navigator = useRef(new Navigator(navigationRef, isReady));
  const [showGrid, setShowGrid] = useState(false);
  const insets = useSafeAreaInsets();

  let headerBackground = context?.designSystemConfig?.config?.headerBar;
  let headerGradient = theme.colors?.gradient;

  if (theme.assets?.headerBackground) {
    headerBackground = theme.assets?.headerBackground;
  }
  if (context?.designSystemConfig?.config?.headerGradient) {
    headerGradient = context?.designSystemConfig?.config?.headerGradient;
  }

  /**
   * inject data for navigator
   */
  navigator.current.maxApi = maxApi;

  /**
   * handle mini language & listen change
   * engine only shake to enable grid view
   */
  useEffect(() => {
    const subscription = DeviceEventEmitter.addListener(
      'onChangeGrid',
      enable => {
        setShowGrid(!!enable);
      },
    );

    return () => {
      subscription?.remove?.();
    };
  }, []);

  /**
   * translate context method
   * @param data
   */
  const translate = (data?: string | { vi: string; en: string }) => {
    if (data && typeof data !== 'string') {
      return localize?.translateData(data);
    }
    return localize?.translate(data as string);
  };

  navigator.current.setCurrentContext = setCurrentContext;

  return (
    <ApplicationContext.Provider
      value={{
        navigator: navigator.current,
        theme: {
          ...theme,
          colors: {
            ...theme.colors,
            gradient: headerGradient,
          },
          assets: {
            ...theme.assets,
            headerBackground,
          },
        },
        showGrid,
        translate,
      }}
    >
      <NavigationIndependentTree>
        <ReactNavigationContainer
          theme={{
            dark: false,
            colors: {
              primary: theme.colors.primary,
              background: theme.colors.background.default,
              card: theme.colors.background.surface,
              text: theme.colors.text.default,
              border: theme.colors.border.default,
              notification: theme.colors.error.primary,
            },
            fonts: {
              regular: {
                fontFamily: 'SFProText',
                fontWeight: '400',
              },
              medium: {
                fontFamily: 'SFProText',
                fontWeight: '400',
              },
              bold: {
                fontFamily: 'SFProText',
                fontWeight: '400',
              },
              heavy: {
                fontFamily: 'SFProText',
                fontWeight: '400',
              },
            },
          }}
          ref={navigationRef}
          onReady={() => {
            isReady.current = true;
          }}
        >
          <Stack.Navigator
            initialRouteName="Stack"
            screenOptions={{
              headerMode: 'screen',
              gestureEnabled: false,
              headerTitleAlign: 'center',
              headerTintColor: theme.colors.text.default,
              headerStyle: {
                height: 52 + insets.top,
              },
            }}
          >
            <Stack.Screen
              name="Stack"
              component={StackScreen}
              initialParams={{ screen, initialParams }}
              options={{
                ...getStackOptions(),
                ...(options as StackNavigationOptions),
              }}
            />
            <Stack.Screen
              name="Dialog"
              component={StackScreen}
              options={{
                headerTitleAlign: 'left',
                headerTitle: props => <HeaderTitle {...props} />,
                presentation: 'transparentModal',
                gestureEnabled: false,
                cardStyle: {
                  backgroundColor: theme.colors.background.default,
                },
                headerLeft: (props: any) => <HeaderLeft {...props} />,
                headerBackground: (props: any) => (
                  <HeaderBackground {...props} />
                ),
                headerRight: (props: any) => <HeaderRight {...props} />,
                headerTintColor: Colors.black_17,
                ...TransitionPresets.ModalTransition,
              }}
              initialParams={{ screen }}
            />
            <Stack.Screen
              name="Modal"
              component={ModalScreen}
              options={getModalOptions()}
              initialParams={{ screen }}
            />
          </Stack.Navigator>
        </ReactNavigationContainer>
      </NavigationIndependentTree>
    </ApplicationContext.Provider>
  );
};

export { ApplicationContext, NavigationContainer };
