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

import * as React from 'react';

import { action } from '@storybook/addon-actions';
import { boolean, text } from '@storybook/addon-knobs';
import { storiesOf } from '@storybook/react';

import { Colors } from '../../types/Colors';
import { pngUrl } from '../../storybook/Fixtures';
import { Message, Props as MessagesProps } from './Message';
import { AUDIO_MP3, IMAGE_PNG, MIMEType, VIDEO_MP4 } from '../../types/MIME';
import { Props, Quote } from './Quote';
import { setup as setupI18n } from '../../../js/modules/i18n';
import enMessages from '../../../_locales/en/messages.json';

const i18n = setupI18n('en', enMessages);

const story = storiesOf('Components/Conversation/Quote', module);

const defaultMessageProps: MessagesProps = {
  authorId: 'some-id',
  authorTitle: 'Person X',
  canReply: true,
  canDeleteForEveryone: true,
  canDownload: true,
  clearSelectedMessage: () => null,
  conversationId: 'conversationId',
  conversationType: 'direct', // override
  deleteMessage: () => null,
  deleteMessageForEveryone: () => null,
  direction: 'incoming',
  displayTapToViewMessage: () => null,
  downloadAttachment: () => null,
  i18n,
  id: 'messageId',
  interactionMode: 'keyboard',
  openConversation: () => null,
  openLink: () => null,
  previews: [],
  reactToMessage: () => null,
  renderEmojiPicker: () => <div />,
  replyToMessage: () => null,
  retrySend: () => null,
  scrollToQuotedMessage: () => null,
  selectMessage: () => null,
  showContactDetail: () => null,
  showContactModal: () => null,
  showExpiredIncomingTapToViewToast: () => null,
  showExpiredOutgoingTapToViewToast: () => null,
  showMessageDetail: () => null,
  showVisualAttachment: () => null,
  status: 'sent',
  text: 'This is really interesting.',
  timestamp: Date.now(),
};

const renderInMessage = ({
  attachment,
  authorColor,
  authorName,
  authorPhoneNumber,
  authorProfileName,
  authorTitle,
  isFromMe,
  referencedMessageNotFound,
  text: quoteText,
}: Props) => {
  const messageProps = {
    ...defaultMessageProps,
    authorColor,
    quote: {
      attachment,
      authorId: 'an-author',
      authorColor,
      authorName,
      authorPhoneNumber,
      authorProfileName,
      authorTitle,
      isFromMe,
      referencedMessageNotFound,
      sentAt: Date.now() - 30 * 1000,
      text: quoteText,
    },
  };

  return (
    <div style={{ overflow: 'hidden' }}>
      <Message {...messageProps} />
      <br />
      <Message {...messageProps} direction="outgoing" />
    </div>
  );
};

const createProps = (overrideProps: Partial<Props> = {}): Props => ({
  attachment: overrideProps.attachment || undefined,
  authorColor: overrideProps.authorColor || 'green',
  authorName: text('authorName', overrideProps.authorName || ''),
  authorPhoneNumber: text(
    'authorPhoneNumber',
    overrideProps.authorPhoneNumber || ''
  ),
  authorProfileName: text(
    'authorProfileName',
    overrideProps.authorProfileName || ''
  ),
  authorTitle: text('authorTitle', overrideProps.authorTitle || ''),
  i18n,
  isFromMe: boolean('isFromMe', overrideProps.isFromMe || false),
  isIncoming: boolean('isIncoming', overrideProps.isIncoming || false),
  onClick: action('onClick'),
  onClose: action('onClose'),
  referencedMessageNotFound: boolean(
    'referencedMessageNotFound',
    overrideProps.referencedMessageNotFound || false
  ),
  text: text('text', overrideProps.text || 'A sample message from a pal'),
  withContentAbove: boolean(
    'withContentAbove',
    overrideProps.withContentAbove || false
  ),
});

story.add('Outgoing by Another Author', () => {
  const props = createProps({
    authorTitle: 'Terrence Malick',
  });

  return <Quote {...props} />;
});

story.add('Outgoing by Me', () => {
  const props = createProps({
    isFromMe: true,
  });

  return <Quote {...props} />;
});

story.add('Incoming by Another Author', () => {
  const props = createProps({
    authorTitle: 'Terrence Malick',
    isIncoming: true,
  });

  return <Quote {...props} />;
});

story.add('Incoming by Me', () => {
  const props = createProps({
    isFromMe: true,
    isIncoming: true,
  });

  return <Quote {...props} />;
});

story.add('Incoming/Outgoing Colors', () => {
  const props = createProps({});
  return (
    <>
      {Colors.map(color => renderInMessage({ ...props, authorColor: color }))}
    </>
  );
});

story.add('Content Above', () => {
  const props = createProps({
    withContentAbove: true,
  });

  return (
    <>
      <div>Content Above</div>
      <Quote {...props} />
    </>
  );
});

story.add('Image Only', () => {
  const props = createProps({
    attachment: {
      contentType: IMAGE_PNG,
      fileName: 'sax.png',
      isVoiceMessage: false,
      thumbnail: {
        contentType: IMAGE_PNG,
        objectUrl: pngUrl,
      },
    },
  });
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  props.text = undefined as any;

  return <Quote {...props} />;
});
story.add('Image Attachment', () => {
  const props = createProps({
    attachment: {
      contentType: IMAGE_PNG,
      fileName: 'sax.png',
      isVoiceMessage: false,
      thumbnail: {
        contentType: IMAGE_PNG,
        objectUrl: pngUrl,
      },
    },
  });

  return <Quote {...props} />;
});

story.add('Image Attachment w/o Thumbnail', () => {
  const props = createProps({
    attachment: {
      contentType: IMAGE_PNG,
      fileName: 'sax.png',
      isVoiceMessage: false,
    },
  });

  return <Quote {...props} />;
});

story.add('Video Only', () => {
  const props = createProps({
    attachment: {
      contentType: VIDEO_MP4,
      fileName: 'great-video.mp4',
      isVoiceMessage: false,
      thumbnail: {
        contentType: IMAGE_PNG,
        objectUrl: pngUrl,
      },
    },
  });
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  props.text = undefined as any;

  return <Quote {...props} />;
});

story.add('Video Attachment', () => {
  const props = createProps({
    attachment: {
      contentType: VIDEO_MP4,
      fileName: 'great-video.mp4',
      isVoiceMessage: false,
      thumbnail: {
        contentType: IMAGE_PNG,
        objectUrl: pngUrl,
      },
    },
  });

  return <Quote {...props} />;
});

story.add('Video Attachment w/o Thumbnail', () => {
  const props = createProps({
    attachment: {
      contentType: VIDEO_MP4,
      fileName: 'great-video.mp4',
      isVoiceMessage: false,
    },
  });

  return <Quote {...props} />;
});

story.add('Audio Only', () => {
  const props = createProps({
    attachment: {
      contentType: AUDIO_MP3,
      fileName: 'great-video.mp3',
      isVoiceMessage: false,
    },
  });
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  props.text = undefined as any;

  return <Quote {...props} />;
});

story.add('Audio Attachment', () => {
  const props = createProps({
    attachment: {
      contentType: AUDIO_MP3,
      fileName: 'great-video.mp3',
      isVoiceMessage: false,
    },
  });

  return <Quote {...props} />;
});

story.add('Voice Message Only', () => {
  const props = createProps({
    attachment: {
      contentType: AUDIO_MP3,
      fileName: 'great-video.mp3',
      isVoiceMessage: true,
    },
  });
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  props.text = undefined as any;

  return <Quote {...props} />;
});

story.add('Voice Message Attachment', () => {
  const props = createProps({
    attachment: {
      contentType: AUDIO_MP3,
      fileName: 'great-video.mp3',
      isVoiceMessage: true,
    },
  });

  return <Quote {...props} />;
});

story.add('Other File Only', () => {
  const props = createProps({
    attachment: {
      contentType: 'application/json' as MIMEType,
      fileName: 'great-data.json',
      isVoiceMessage: false,
    },
  });
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  props.text = undefined as any;

  return <Quote {...props} />;
});

story.add('Other File Attachment', () => {
  const props = createProps({
    attachment: {
      contentType: 'application/json' as MIMEType,
      fileName: 'great-data.json',
      isVoiceMessage: false,
    },
  });

  return <Quote {...props} />;
});

story.add('No Close Button', () => {
  const props = createProps();
  props.onClose = undefined;

  return <Quote {...props} />;
});

story.add('Message Not Found', () => {
  const props = createProps({
    referencedMessageNotFound: true,
  });

  return renderInMessage(props);
});

story.add('Missing Text & Attachment', () => {
  const props = createProps();
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  props.text = undefined as any;

  return <Quote {...props} />;
});

story.add('@mention + outgoing + another author', () => {
  const props = createProps({
    authorTitle: 'Tony Stark',
    text: '@Captain America Lunch later?',
  });

  return <Quote {...props} />;
});

story.add('@mention + outgoing + me', () => {
  const props = createProps({
    isFromMe: true,
    text: '@Captain America Lunch later?',
  });

  return <Quote {...props} />;
});

story.add('@mention + incoming + another author', () => {
  const props = createProps({
    authorTitle: 'Captain America',
    isIncoming: true,
    text: '@Tony Stark sure',
  });

  return <Quote {...props} />;
});

story.add('@mention + incoming + me', () => {
  const props = createProps({
    isFromMe: true,
    isIncoming: true,
    text: '@Tony Stark sure',
  });

  return <Quote {...props} />;
});