/* eslint-disable react-native/no-unused-styles */
import * as React from "react";
import * as R from "ramda";
import { FlatList, Platform, StyleSheet, View } from "react-native";

import { Gutter } from "./Gutter";
import Tab from "./Tab";
import { getOpacityFromHexColor } from "@applicaster/zapp-react-native-utils/configurationUtils";
import { useIsRTL } from "@applicaster/zapp-react-native-utils/localizationUtils";
import { useConfiguration } from "@applicaster/zapp-react-native-utils/reactHooks/configuration";

type RenderItemProps = {
  item: ZappEntry;
  index: number;
};

type FlexAlignment = "flex-start" | "center" | "flex-end";

const CUSTOM_KEY = "other";

const getTabsFlexAlignment = (tabsAlignment: string): FlexAlignment => {
  switch (tabsAlignment) {
    case "left":
      return "flex-start";
    case "center":
      return "center";
    case "right":
      return "flex-end";
    default:
      return "flex-start";
  }
};

const getStyles = ({
  tab_bar_background_color,
  tab_bar_border_bottom_width,
  tab_bar_border_bottom_color,
  tab_bar_padding_left,
  tab_bar_padding_right,
  tab_bar_elevation,
  display_mode_tabs_alignment,
  tab_bar_shadow_color,
  tab_bar_shadow_offset_height,
  tab_bar_shadow_offset_width,
  tab_bar_shadow_radius,
}) => {
  const iosStyles = {
    shadowColor: tab_bar_shadow_color,
    shadowOffset: {
      height: tab_bar_shadow_offset_height,
      width: tab_bar_shadow_offset_width,
    },
    shadowOpacity: getOpacityFromHexColor(tab_bar_shadow_color),
    shadowRadius: tab_bar_shadow_radius,
    zIndex: 10,
  };

  const androidStyles = { elevation: tab_bar_elevation };

  return StyleSheet.create({
    container: {
      backgroundColor: tab_bar_background_color,
      borderBottomWidth: tab_bar_border_bottom_width,
      borderBottomColor: tab_bar_border_bottom_color,
      ...(Platform.OS === "ios" ? iosStyles : androidStyles),
    },
    contentContainer: {
      flexGrow: 1,
      justifyContent: getTabsFlexAlignment(display_mode_tabs_alignment),
      paddingLeft: tab_bar_padding_left,
      paddingRight: tab_bar_padding_right,
    },
    fractionalWrapper: {
      flexDirection: "row",
      paddingLeft: tab_bar_padding_left,
      paddingRight: tab_bar_padding_right,
    },
  });
};

type Props = {
  tabs: [ZappEntry];
  activeTab: ZappEntry;
  setActiveTab: (ZappEntry) => void;
  onTabsSelectorLayout: (number) => void;
};

const TabsComponent = ({
  tabs,
  activeTab,
  setActiveTab,
  onTabsSelectorLayout,
}: Props) => {
  const isRTL = useIsRTL();
  const configuration = useConfiguration();
  const scrollViewRef = React.useRef(null);
  const tabRefs = React.useRef([]);

  const {
    tab_bar_gutter,
    display_mode,
    text_label_data_key,
    text_label_custom_data_key,
  } = configuration;

  const styles = React.useMemo(() => getStyles(configuration), []);

  const scrollToItem = React.useCallback(
    (index) => {
      scrollViewRef.current.scrollToIndex({
        index: Platform.select({
          ios: isRTL ? tabs?.length - index - 1 : index,
          android: index,
        }),
        viewPosition: 0.5,
        viewOffset: tab_bar_gutter / 2,
      });
    },
    [tabs, tab_bar_gutter]
  );

  const onTabPress = React.useCallback(
    (item, index) => {
      setActiveTab(item);

      if (display_mode === "dynamic" || display_mode === "fixed") {
        scrollToItem(index);
      }
    },
    [display_mode, scrollToItem, setActiveTab]
  );

  const getTitle = React.useCallback(
    (item: ZappEntry): string => {
      const titlePath = R.split(
        ".",
        text_label_data_key === CUSTOM_KEY
          ? text_label_custom_data_key
          : text_label_data_key
      );

      return R.path(titlePath, item);
    },
    [text_label_data_key, text_label_custom_data_key]
  );

  const getSelectedItem = React.useCallback(
    (id) => {
      return R.propEq("id", id)(activeTab);
    },
    [activeTab]
  );

  const renderGutter = React.useCallback(
    () => <Gutter width={tab_bar_gutter} />,
    [tab_bar_gutter]
  );

  const renderItem = React.useCallback(
    ({ item, index, item: { id } }: RenderItemProps) => (
      <>
        <Tab
          ref={(ref) => {
            tabRefs.current[index] = ref;
          }}
          key={id}
          {...{
            title: getTitle(item),
            id,
            handleOnPress: () => {
              onTabPress(item, index);
            },
            selected: getSelectedItem(id),
            configuration,
          }}
        />
        {display_mode === "fractional" &&
          index !== tabs?.length - 1 &&
          renderGutter()}
      </>
    ),
    [tabs, display_mode, configuration, onTabPress, getTitle, getSelectedItem]
  );

  const keyExtractor = React.useCallback(R.compose(String, R.prop("id")), []);

  if (display_mode === "fractional") {
    return (
      <View style={styles.container}>
        <View style={styles.fractionalWrapper}>
          {tabs?.map((item, index) => renderItem({ item, index }))}
        </View>
      </View>
    );
  }

  return (
    <View style={styles.container} onLayout={onTabsSelectorLayout}>
      <FlatList
        extraData={activeTab}
        // removeClippedSubviews - be aware that this implementation has bugs, such as missing content
        ref={scrollViewRef}
        contentContainerStyle={styles.contentContainer}
        data={tabs}
        ItemSeparatorComponent={renderGutter}
        horizontal
        showsHorizontalScrollIndicator={false}
        renderItem={renderItem}
        keyExtractor={keyExtractor}
      />
    </View>
  );
};

export const Tabs = React.memo<Props>(TabsComponent);
