import React, {useCallback} from 'react';
import {View} from 'react-native';
import {useNavigation} from '@react-navigation/native';
import {useTapDebounce} from '@hooks/useTapDebounce';
import {PictureAsset, VideoAsset} from '@modules/chats/interfaces';
import {Screens} from '@shared/constants';

import {styles} from './styles';
import {ImageRenderer} from './components/ImageRenderer';
import {VideoRenderer} from './components/VideoRenderer';
import {ImageSize} from './components/tileStyles';

interface ImageMessageDisplayerProps {
  attachments: (PictureAsset | VideoAsset)[];
  messageId: string;
  senderId: number;
  channel: string;
}

// Picks the right tile renderer based on the asset format. The two
// renderers share the same call signature so swapping is a one-liner.
const Tile = ({
  attachment,
  size,
  messageId,
  remaining,
  onPress,
}: {
  attachment: PictureAsset | VideoAsset;
  size: ImageSize;
  messageId: string;
  remaining?: number;
  onPress: (attachmentId: number) => void;
}) => {
  const isVideo = attachment.metadata.format === 'video';
  const Renderer = isVideo ? VideoRenderer : ImageRenderer;
  return (
    <Renderer
      // since we recycle views we want the renderer to reset and load
      // everything from a fresh state, otherwise we can get wrong or
      // missing images when scrolling
      key={attachment.id}
      attachmentId={attachment.id}
      messageId={messageId}
      size={size}
      remaining={remaining}
      onPress={onPress}
    />
  );
};

export const ImageMessageDisplayer = ({
  attachments,
  messageId,
  senderId,
  channel,
}: ImageMessageDisplayerProps) => {
  const navigation = useNavigation();
  const scheduleTap = useTapDebounce();

  const onPress = useCallback(
    (assetId: number) => {
      scheduleTap(() =>
        navigation.navigate(Screens.CHATS_IMAGE_VIEWER, {
          messageId,
          initialAssetId: assetId,
          senderId,
          channel,
        }),
      );
    },
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [messageId, senderId, channel, scheduleTap],
  );

  if (attachments.length === 1) {
    return (
      <Tile
        attachment={attachments[0]}
        size="big"
        messageId={messageId}
        onPress={onPress}
      />
    );
  }
  if (attachments.length === 2) {
    return (
      <View style={styles.imagesContainer}>
        {attachments.map(attachment => (
          <Tile
            key={attachment.id}
            attachment={attachment}
            size="medium"
            messageId={messageId}
            onPress={onPress}
          />
        ))}
      </View>
    );
  }
  if (attachments.length >= 3) {
    const firstThreeAttachments = attachments.slice(0, 3);
    const remainingAttachmentsQuantity =
      attachments.length === 3 ? 0 : attachments.length - 2;

    return (
      <View style={styles.imagesContainer}>
        {firstThreeAttachments.map((attachment, index) => (
          <Tile
            key={attachment.id}
            attachment={attachment}
            size="small"
            messageId={messageId}
            remaining={index === 2 ? remainingAttachmentsQuantity : 0}
            onPress={onPress}
          />
        ))}
      </View>
    );
  }
  return null;
};
