import React, {useMemo, useState} from 'react';
import {
  FlatList,
  StyleProp,
  ViewStyle,
  ListRenderItem,
  View,
  FlatListProps,
} from 'react-native';
import {Divider, Spinner} from '@components/_HuGo';
import {navigate} from '@navigation/navigator';
import {useInstanceProp} from '@redux/selectors';
import {Screens} from '@shared/constants';
import {
  canOpenVisualizer,
  checkEqualStrings,
  handleFileView,
  replaceForwardSlashes,
} from '@shared/utils';
import {useTheme} from '@shared/theme';

import EmptyList, {EmptyListProps} from './components/EmptyList';
import File from './components/File';
import {FileListSk} from './components/FileListSk';
import Folder from './components/Folder';
import {File as FileType, FileHierarchies} from './interfaces';
import {styles} from './styles';

const keyExtractor = (item: FileType) => `${item.id}`;

interface Props {
  clickFileCallback?: (value: FileType) => void;
  containerStyle?: StyleProp<ViewStyle>;
  emptyComponent?: EmptyListProps;
  folderId?: number;
  files?: FileType[];
  getSubtitle?: (folderId: number) => string;
  isLoading?: boolean;
  isLoadingMore?: boolean;
  ListFooterComponent?: FlatListProps<FileType>['ListFooterComponent'];
  ListHeaderComponent?: FlatListProps<FileType>['ListHeaderComponent'];
  onEndReached?: () => void;
  onPressFile?: (value: FileType, funcValue: () => void) => void;
  onPressFolder?: (id: number, name: string) => void;
  searchTerm?: string;
  withPreview?: boolean;
  withDivider?: boolean;
  withBorder?: boolean;
}

export function FileList({
  clickFileCallback,
  containerStyle,
  emptyComponent,
  folderId,
  files,
  getSubtitle,
  isLoading,
  isLoadingMore,
  ListFooterComponent,
  ListHeaderComponent,
  onEndReached,
  onPressFile,
  onPressFolder,
  searchTerm,
  withPreview,
  withDivider,
  withBorder,
}: Props) {
  const {theme} = useTheme();
  const hideFileDownload = useInstanceProp('hideFileDownload');
  const [openedFileName, setOpenedFileName] = useState('');
  const data = useMemo(
    () =>
      files?.map(file =>
        file.name ? {...file, name: replaceForwardSlashes(file.name)} : file,
      ) || [],
    [files],
  );

  const onFilePress = (item: FileType) => () => {
    if (onPressFile) {
      setOpenedFileName(item.name);
      onPressFile(item, () => setOpenedFileName(''));
    } else {
      canOpenVisualizer(item) || hideFileDownload
        ? navigate(Screens.FILE_VISUALIZER, {file: item})
        : handleFileView(item, setOpenedFileName);
      clickFileCallback?.(item);
    }
  };

  const renderItem: ListRenderItem<FileType> = ({item, index}) => {
    const isFirstItem = index === 0;
    const isLastItem = index === data.length - 1;
    const itemStyle = withBorder
      ? [
          {borderColor: theme.border.neutral.default},
          styles.borderContainer,
          isFirstItem && styles.firstItemContainer,
          isLastItem && !ListFooterComponent && styles.lastItemContainer,
        ]
      : undefined;
    return item.type === (FileHierarchies.Folder as string) ? (
      <Folder
        item={item}
        onPress={onPressFolder}
        searchTerm={searchTerm}
        style={itemStyle}
      />
    ) : (
      <File
        getSubtitle={getSubtitle}
        item={item}
        loading={checkEqualStrings(openedFileName, item.name)}
        onPress={onFilePress(item)}
        searchTerm={searchTerm}
        showParentName={
          !!searchTerm && folderId !== item.parentId && !!item.parentName
        }
        style={itemStyle}
        withPreview={withPreview}
      />
    );
  };

  const renderItemSeparator = () =>
    withDivider ? (
      <Divider
        style={[
          styles.divider,
          {backgroundColor: theme.background.elements.default},
        ]}
      />
    ) : null;

  return (
    <FlatList
      bounces={!!data.length}
      contentContainerStyle={[!withDivider && styles.noDivider, containerStyle]}
      data={data}
      ItemSeparatorComponent={renderItemSeparator}
      keyExtractor={keyExtractor}
      ListFooterComponent={
        isLoadingMore ? (
          <View style={styles.spinnerContainer}>
            <Spinner />
          </View>
        ) : (
          ListFooterComponent
        )
      }
      ListEmptyComponent={
        isLoading ? (
          <FileListSk withDivider={withDivider} />
        ) : emptyComponent ? (
          <EmptyList {...emptyComponent} />
        ) : null
      }
      ListHeaderComponent={ListHeaderComponent}
      onEndReached={onEndReached}
      renderItem={renderItem}
      showsVerticalScrollIndicator={false}
      style={{backgroundColor: theme.background.layout.default}}
    />
  );
}

export * from './components/FileListSk';
export * from './interfaces';
