import React, { useCallback, useMemo, useRef } from "react";
import * as R from "ramda";

import { FocusableList } from "@applicaster/zapp-react-native-ui-components/Components/FocusableList";
import { useConfiguration } from "@applicaster/zapp-react-native-utils/reactHooks/configuration";
import { isEmptyOrNil } from "@applicaster/zapp-react-native-utils/cellUtils";

import Tab from "./Tab";
import { Gutter } from "../Gutter";
import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
import { ImageBackground, View } from "react-native";
import { getStyles } from "./styles";
import {
  getId,
  scrollToSelectedIndex as scrollToSelectedIndexFn,
  generateFocusableId,
  applyFontConfig,
} from "./utils";

const VIEW_POSITION = 0;

const TabsComponent = ({
  entry,
  style,
  selectedEntryIndex,
  setSelectedEntry,
}: TabsProps & Partial<TabsSelectionContextType>) => {
  const configuration = useConfiguration();
  const config = applyFontConfig(configuration);
  const styles = useMemo(() => getStyles(config), [config]);

  const {
    tab_bar_gutter: horizontalGutter,
    tab_bar_background_image: bgImage,
  } = config;

  const {
    tabs,
    tabsWrapper,
    tabsBackground,
    tabsListWrapper,
    tabsListContentContainer,
  } = styles;

  const flatListRef = useRef(null);

  const entryLength = R.length(entry);

  const scrollToSelectedIndex = useMemo(
    () => scrollToSelectedIndexFn(flatListRef, config, entryLength),
    [config]
  );

  const onListElementPress = useCallback((__, { item }) => {
    setSelectedEntry && setSelectedEntry(item);
  }, []);

  const onListElementFocus = useCallback(
    (_, { index }) => {
      scrollToSelectedIndex(index, VIEW_POSITION);
    },
    [scrollToSelectedIndex]
  );

  const renderItem = useCallback(
    ({ item, index, focused }) => {
      const itemId = generateFocusableId(getId(item));

      const isSelected = R.equals(index, selectedEntryIndex);

      return (
        <Tab
          id={itemId}
          item={item}
          focused={focused}
          selected={isSelected}
          styles={styles}
          config={config}
        />
      );
    },
    [selectedEntryIndex]
  );

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

  const onLayoutChange = useCallback(() => {
    scrollToSelectedIndex(selectedEntryIndex, VIEW_POSITION);
  }, [selectedEntryIndex]);

  return (
    <View style={[tabsWrapper, style]}>
      <View style={tabs}>
        <ImageBackground
          style={tabsBackground}
          source={{ uri: !isEmptyOrNil(bgImage) ? bgImage : undefined }}
        >
          <FocusableList
            horizontal
            onScrollToIndexFailed={noop}
            onLayout={onLayoutChange}
            contentContainerStyle={tabsListContentContainer}
            ref={flatListRef}
            onListElementFocus={onListElementFocus}
            onListElementPress={onListElementPress}
            keyExtractor={getId}
            data={entry}
            renderItem={renderItem}
            withStateMemory={false}
            initialScrollIndex={selectedEntryIndex}
            extraChildrenData={selectedEntryIndex}
            ItemSeparatorComponent={renderGutter}
            style={tabsListWrapper}
            omitPropsPropagation={["initialScrollIndex"]}
          />
        </ImageBackground>
      </View>
    </View>
  );
};

export const Tabs = React.memo(TabsComponent);
