import React, {memo, useState} from 'react';
import {LayoutChangeEvent, View, Animated, I18nManager} from 'react-native';
import {Route} from 'react-native-tab-view';
import {
  RNTabBarProps,
  TabBarProps,
  TabViewRoute,
} from '@components/TabView/interfaces';
import TabBarItem from '@components/TabView/components/TabBarItem';

import {styles} from './styles';

export type GetTabWidth = (index: number) => number;

const getTranslateX = ({
  position,
  routes,
  tabWidth,
  gap,
}: {
  position: Animated.AnimatedInterpolation<number>;
  routes: Route[];
  tabWidth: number;
  gap?: number;
}) => {
  const inputRange = routes.map((_, i) => i);

  // every index contains widths at all previous indices
  const outputRange = routes.reduce<number[]>((acc, _, i) => {
    if (i === 0) {
      return [0];
    }
    return [...acc, acc[i - 1] + tabWidth + (gap ?? 0)];
  }, []);

  const translateX = position.interpolate({
    inputRange,
    outputRange,
    extrapolate: 'clamp',
  });

  return Animated.multiply(translateX, I18nManager.isRTL ? -1 : 1);
};

function TabBar<T extends TabViewRoute>({
  style,
  handleTabPress,
  ...rest
}: TabBarProps<T> & RNTabBarProps) {
  const {jumpTo, navigationState, position, gap} = rest;
  const [containerWidth, setContainerWidth] = useState(0);
  const lineIndicatorWidth = 100 / navigationState.routes.length;
  const tabWidth = containerWidth / navigationState.routes.length;
  const selectedTabRoute = navigationState.routes.at(navigationState.index);

  const handlePress = (key: string) => () => {
    jumpTo(key);
    selectedTabRoute &&
      handleTabPress?.(key, selectedTabRoute.key, selectedTabRoute.module);
  };

  const handleContainerLayout = (event: LayoutChangeEvent) => {
    setContainerWidth(event.nativeEvent.layout.width);
  };

  const translateX =
    navigationState.routes.length > 1
      ? getTranslateX({position, routes: navigationState.routes, tabWidth, gap})
      : 0;

  return (
    <View style={[styles.container, style]} onLayout={handleContainerLayout}>
      {navigationState.routes.map((route, index) => (
        <TabBarItem
          key={route.key}
          selected={route.key === selectedTabRoute?.key}
          style={{width: tabWidth}}
          label={route.title}
          onPress={handlePress(route.key)}
          badge={route.badge}
          variant="tabs"
          index={index}
          {...rest}
        />
      ))}
      <Animated.View
        style={[
          styles.lineIndicator,
          {transform: [{translateX}], width: `${lineIndicatorWidth}%`},
        ]}
      />
    </View>
  );
}

export default memo(TabBar);
