import React, { useEffect, useRef } from 'react';
import { BottomNavigation } from 'react-native-paper';
import { Animated, StyleSheet } from 'react-native';
import {
  CommonActions,
  NavigationHelpers,
  ParamListBase,
  TabNavigationState,
} from '@react-navigation/native';
import { EdgeInsets } from 'react-native-safe-area-context';
import { BottomTabNavigationEventMap } from '@react-navigation/bottom-tabs';
import { BottomTabDescriptorMap } from '@react-navigation/bottom-tabs/lib/typescript/src/types';
import { ROUTE } from '../types';

const hideableBottomNavigationBarStyles = StyleSheet.create({
  bar: {
    position: 'absolute',
    bottom: 0,
    left: 0,
    right: 0,
  },
});

const HideableBottomNavigationBar = ({
  navigation,
  state,
  descriptors,
  insets,
  visible = true,
  routeCallback,
}: {
  navigation: NavigationHelpers<ParamListBase, BottomTabNavigationEventMap>;
  state: TabNavigationState<ParamListBase>;
  descriptors: BottomTabDescriptorMap;
  insets: EdgeInsets;
  visible?: boolean;
  routeCallback?: (route: ROUTE) => void;
}) => {
  const visibleAnim = useRef(new Animated.Value(visible ? 0 : 1)).current;

  useEffect(() => {
    Animated.timing(visibleAnim, {
      toValue: visible ? 0 : 1,
      duration: visible ? 200 : 150,
      useNativeDriver: true,
    }).start();
  }, [visible, visibleAnim]);

  return (
    <Animated.View
      style={{
        marginBottom: insets.bottom,
        transform: [
          {
            translateY: visibleAnim.interpolate({
              inputRange: [0, 1],
              outputRange: [0, 80],
            }),
          },
        ],
        ...hideableBottomNavigationBarStyles.bar,
      }}>
      <BottomNavigation.Bar
        navigationState={state}
        safeAreaInsets={insets}
        onTabPress={({ route, preventDefault }) => {
          const event = navigation.emit({
            type: 'tabPress',
            target: route.key,
            canPreventDefault: true,
          });
          if (event.defaultPrevented) {
            preventDefault();
          } else {
            navigation.dispatch({
              ...CommonActions.navigate(route.name, route.params),
              target: state.key,
            });
            if (routeCallback) routeCallback(route.name as ROUTE);
          }
        }}
        renderIcon={({ route, focused, color }) => {
          const { options } = descriptors[route.key];
          if (options.tabBarIcon) {
            return options.tabBarIcon({
              focused,
              color,
              size: 22,
            });
          }
        }}
        getLabelText={({ route }) => {
          const { options } = descriptors[route.key];
          return options.title ?? route.name;
        }}
      />
    </Animated.View>
  );
};

export default HideableBottomNavigationBar;
