import { useCallback, useEffect, useState } from 'react';
import { useDispatch } from 'react-redux';
import useKey from 'react-use/lib/useKey';

import { Lightbox } from './Lightbox';

import { updateLightBoxOptions } from '../../state/ducks/modalDialog';
import { useSelectedConversationKey } from '../../state/selectors/selectedConversation';
import { MIME } from '../../types';
import { AttachmentTypeWithPath } from '../../types/Attachment';
import { saveAttachmentToDisk } from '../../util/attachmentsUtil';

export interface MediaItemType {
  objectURL?: string;
  thumbnailObjectUrl?: string;
  contentType: MIME.MIMEType;
  index: number;
  attachment: AttachmentTypeWithPath;
  messageTimestamp: number;
  messageSender: string;
  messageId: string;
}

type Props = {
  media: Array<MediaItemType>;
  selectedIndex?: number;
};

export const LightboxGallery = (props: Props) => {
  const { media, selectedIndex = -1 } = props;
  const [currentIndex, setCurrentIndex] = useState(-1);
  const selectedConversation = useSelectedConversationKey();

  const dispatch = useDispatch();

  // just run once, when the component is mounted. It's to show the lightbox on the specified index at start.
  useEffect(() => {
    setCurrentIndex(selectedIndex);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const selectedMedia = media[currentIndex];
  const firstIndex = 0;
  const lastIndex = media.length - 1;

  const hasPrevious = currentIndex > firstIndex;
  const hasNext = currentIndex < lastIndex;

  const onPrevious = useCallback(() => {
    setCurrentIndex(Math.max(currentIndex - 1, 0));
  }, [currentIndex]);

  const onNext = useCallback(() => {
    setCurrentIndex(Math.min(currentIndex + 1, lastIndex));
  }, [currentIndex, lastIndex]);

  const handleSave = useCallback(() => {
    if (!selectedConversation) {
      return;
    }
    const mediaItem = media[currentIndex];
    void saveAttachmentToDisk({ ...mediaItem, conversationId: selectedConversation });
  }, [currentIndex, media, selectedConversation]);

  useKey(
    'ArrowRight',
    () => {
      onNext?.();
    },
    undefined,
    [currentIndex]
  );
  useKey(
    'ArrowLeft',
    () => {
      onPrevious?.();
    },
    undefined,
    [currentIndex]
  );

  useKey(
    'Escape',
    () => {
      dispatch(updateLightBoxOptions(null));
    },
    undefined,
    [currentIndex]
  );
  if (!selectedConversation) {
    return null;
  }

  // just to avoid to render the first element during the first render when the user selected another item
  if (currentIndex === -1) {
    return null;
  }
  const objectURL = selectedMedia?.objectURL || 'images/alert-outline.svg';
  const { attachment } = selectedMedia;

  const caption = attachment?.caption;
  return (
    <Lightbox
      onPrevious={hasPrevious ? onPrevious : undefined}
      onNext={hasNext ? onNext : undefined}
      onSave={handleSave}
      objectURL={objectURL}
      caption={caption}
      contentType={selectedMedia.contentType}
    />
  );
};