// Copyright 2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only

import React, { useState } from 'react';
import { action } from '@storybook/addon-actions';
import lodash from 'lodash';
import type { Meta } from '@storybook/react';
import type { PropsType } from './Lightbox.dom.tsx';
import { Lightbox } from './Lightbox.dom.tsx';
import type { MediaItemType } from '../types/MediaItem.std.ts';
import {
  AUDIO_MP3,
  IMAGE_JPEG,
  VIDEO_MP4,
  VIDEO_QUICKTIME,
  stringToMIMEType,
  type MIMEType,
} from '../types/MIME.std.ts';

import { fakeAttachment } from '../test-helpers/fakeAttachment.std.ts';

const { noop } = lodash;

const { i18n } = window.SignalContext;

export default {
  title: 'Components/Lightbox',
  argTypes: {},
  args: {},
} satisfies Meta<PropsType>;

type OverridePropsMediaItemType = Partial<MediaItemType> & {
  caption?: string;
  objectURL?: string;
  contentType?: MIMEType;
};

function createMediaItem(
  overrideProps: OverridePropsMediaItemType
): MediaItemType {
  return {
    attachment: fakeAttachment({
      caption: overrideProps.caption || '',
      contentType: overrideProps.contentType ?? IMAGE_JPEG,
      fileName: overrideProps.objectURL,
      url: overrideProps.objectURL,
    }),
    type: 'media',
    index: 0,
    message: {
      conversationId: '1234',
      type: 'incoming',
      id: 'image-msg',
      receivedAt: 0,
      receivedAtMs: Date.now(),
      sentAt: Date.now(),

      // Unused for now
      source: undefined,
      sourceServiceId: undefined,
      isErased: false,
      readStatus: undefined,
      sendStateByConversationId: undefined,
      errors: undefined,
    },
    ...overrideProps,
  };
}

const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => {
  // oxlint-disable-next-line react-hooks/rules-of-hooks
  const [selectedIndex, setSelectedIndex] = useState(0);
  const media = overrideProps.media || [];
  return {
    closeLightbox: action('closeLightbox'),
    i18n,
    isViewOnce: Boolean(overrideProps.isViewOnce),
    media,
    saveAttachment: action('saveAttachment'),
    selectedIndex,
    playbackDisabled: false,
    toggleForwardMessagesModal: action('toggleForwardMessagesModal'),
    onMediaPlaybackStart: noop,
    onPrevAttachment: () => {
      setSelectedIndex(Math.max(0, selectedIndex - 1));
    },
    onNextAttachment: () => {
      setSelectedIndex(Math.min(media.length - 1, selectedIndex + 1));
    },
    onSelectAttachment: setSelectedIndex,
  };
};

export function Multimedia(): React.JSX.Element {
  const props = createProps({
    media: [
      {
        type: 'media',
        attachment: fakeAttachment({
          contentType: IMAGE_JPEG,
          fileName: 'tina-rolf-269345-unsplash.jpg',
          url: '/fixtures/tina-rolf-269345-unsplash.jpg',
          caption:
            'Still from The Lighthouse, starring Robert Pattinson and Willem Defoe.',
        }),
        index: 0,
        message: {
          conversationId: '1234',
          type: 'incoming',
          id: 'image-msg',
          receivedAt: 1,
          receivedAtMs: Date.now(),
          sentAt: Date.now(),
          // Unused for now
          source: undefined,
          sourceServiceId: undefined,
          isErased: false,
          readStatus: undefined,
          sendStateByConversationId: undefined,
          errors: undefined,
        },
      },
      {
        type: 'media',
        attachment: fakeAttachment({
          contentType: VIDEO_MP4,
          fileName: 'pixabay-Soap-Bubble-7141.mp4',
          url: '/fixtures/pixabay-Soap-Bubble-7141.mp4',
        }),
        index: 1,
        message: {
          conversationId: '1234',
          type: 'incoming',
          id: 'video-msg',
          receivedAt: 2,
          receivedAtMs: Date.now(),
          sentAt: Date.now(),
          // Unused for now
          source: undefined,
          sourceServiceId: undefined,
          isErased: false,
          readStatus: undefined,
          sendStateByConversationId: undefined,
          errors: undefined,
        },
      },
      createMediaItem({
        contentType: IMAGE_JPEG,
        index: 2,
        objectURL: '/fixtures/kitten-1-64-64.jpg',
      }),
      createMediaItem({
        contentType: IMAGE_JPEG,
        index: 3,
        objectURL: '/fixtures/kitten-2-64-64.jpg',
      }),
    ],
  });

  return <Lightbox {...props} />;
}

export function MissingMedia(): React.JSX.Element {
  const props = createProps({
    media: [
      {
        type: 'media',
        attachment: fakeAttachment({
          contentType: IMAGE_JPEG,
          fileName: 'tina-rolf-269345-unsplash.jpg',
          url: '/fixtures/tina-rolf-269345-unsplash.jpg',
        }),
        index: 0,
        message: {
          conversationId: '1234',
          type: 'incoming',
          id: 'image-msg',
          receivedAt: 3,
          receivedAtMs: Date.now(),
          sentAt: Date.now(),

          // Unused for now
          source: undefined,
          sourceServiceId: undefined,
          isErased: false,
          readStatus: undefined,
          sendStateByConversationId: undefined,
          errors: undefined,
        },
      },
    ],
  });

  return <Lightbox {...props} />;
}

export function SingleImage(): React.JSX.Element {
  return (
    <Lightbox
      {...createProps({
        media: [
          createMediaItem({
            objectURL: '/fixtures/tina-rolf-269345-unsplash.jpg',
          }),
        ],
      })}
    />
  );
}

export function ImageWithCaptionNormalImage(): React.JSX.Element {
  return (
    <Lightbox
      {...createProps({
        media: [
          createMediaItem({
            caption:
              'This lighthouse is really cool because there are lots of rocks and there is a tower that has a light and the light is really bright because it shines so much. The day was super duper cloudy and stormy and you can see all the waves hitting against the rocks. Wait? What is that weird red hose line thingy running all the way to the tower? Those rocks look slippery! I bet that water is really cold. I am cold now, can I get a sweater? I wonder where this place is, probably somewhere cold like Coldsgar, Frozenville.',
            objectURL: '/fixtures/tina-rolf-269345-unsplash.jpg',
          }),
        ],
      })}
    />
  );
}

export function ImageWithCaptionAllWhiteImage(): React.JSX.Element {
  return (
    <Lightbox
      {...createProps({
        media: [
          createMediaItem({
            caption:
              'This is the user-provided caption. It should be visible on light backgrounds.',
            objectURL: '/fixtures/2000x2000-white.png',
          }),
        ],
      })}
    />
  );
}

export function SingleVideo(): React.JSX.Element {
  return (
    <Lightbox
      {...createProps({
        media: [
          createMediaItem({
            contentType: VIDEO_MP4,
            objectURL: '/fixtures/pixabay-Soap-Bubble-7141.mp4',
          }),
        ],
      })}
    />
  );
}

export function SingleVideoWCaption(): React.JSX.Element {
  return (
    <Lightbox
      {...createProps({
        media: [
          createMediaItem({
            caption:
              'This is the user-provided caption. It can get long and wrap onto multiple lines.',
            contentType: VIDEO_MP4,
            objectURL: '/fixtures/pixabay-Soap-Bubble-7141.mp4',
          }),
        ],
      })}
    />
  );
}

export function UnsupportedImageType(): React.JSX.Element {
  return (
    <Lightbox
      {...createProps({
        media: [
          createMediaItem({
            contentType: stringToMIMEType('image/tiff'),
            objectURL: 'unsupported-image.tiff',
          }),
        ],
      })}
    />
  );
}

export function UnsupportedVideoType(): React.JSX.Element {
  return (
    <Lightbox
      {...createProps({
        media: [
          createMediaItem({
            contentType: VIDEO_QUICKTIME,
            objectURL: 'unsupported-video.mov',
          }),
        ],
      })}
    />
  );
}

export function UnsupportedContent(): React.JSX.Element {
  return (
    <Lightbox
      {...createProps({
        media: [
          createMediaItem({
            contentType: AUDIO_MP3,
            objectURL: '/fixtures/incompetech-com-Agnus-Dei-X.mp3',
          }),
        ],
      })}
    />
  );
}

export function CustomChildren(): React.JSX.Element {
  return (
    <Lightbox {...createProps({})} media={[]}>
      <div
        style={{
          color: 'white',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
        }}
      >
        I am middle child
      </div>
    </Lightbox>
  );
}

export function ConversationHeader(): React.JSX.Element {
  return (
    <Lightbox
      {...createProps({})}
      getConversation={() => ({
        acceptedMessageRequest: true,
        avatarUrl: '/fixtures/kitten-1-64-64.jpg',
        badges: [],
        id: '1234',
        isMe: false,
        name: 'Test',
        profileName: 'Test',
        sharedGroupNames: [],
        title: 'Test',
        type: 'direct',
      })}
      media={[
        createMediaItem({
          contentType: VIDEO_MP4,
          objectURL: '/fixtures/pixabay-Soap-Bubble-7141.mp4',
        }),
      ]}
    />
  );
}

export function ViewOnceVideo(): React.JSX.Element {
  return (
    <Lightbox
      {...createProps({
        isViewOnce: true,
        media: [
          createMediaItem({
            contentType: VIDEO_MP4,
            objectURL: '/fixtures/pixabay-Soap-Bubble-7141.mp4',
          }),
        ],
      })}
      isViewOnce
    />
  );
}

export function IncrementalVideo(): React.JSX.Element {
  const item = createMediaItem({
    contentType: VIDEO_MP4,
    objectURL: '/fixtures/pixabay-Soap-Bubble-7141.mp4',
  });

  return (
    <Lightbox
      {...createProps({
        media: [
          {
            ...item,
            attachment: {
              ...item.attachment,
              incrementalMac: 'something',
              chunkSize: 42,
              pending: true,
              totalDownloaded: 50000,
              size: 100000,
            },
          },
        ],
      })}
    />
  );
}
