// 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 { setupI18n } from '../../util/setupI18n';
import enMessages from '../../../_locales/en/messages.json';
import { StorybookThemeContext } from '../../../.storybook/StorybookThemeContext';
import { strictAssert } from '../../util/assert';
import { getFakeBadge } from '../../test-both/helpers/getFakeBadge';
import type { PropsType } from './MessageSearchResult';
import { MessageSearchResult } from './MessageSearchResult';
import { getDefaultConversation } from '../../test-both/helpers/getDefaultConversation';

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

export default {
  title: 'Components/MessageSearchResult',
};

const someone = getDefaultConversation({
  title: 'Some Person',
  name: 'Some Person',
  phoneNumber: '(202) 555-0011',
});

const me = getDefaultConversation({
  title: 'Me',
  name: 'Me',
  isMe: true,
});

const group = getDefaultConversation({
  title: 'Group Chat',
  name: 'Group Chat',
  type: 'group',
});

const useProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
  i18n,
  id: '',
  conversationId: '',
  sentAt: Date.now() - 24 * 60 * 1000,
  snippet: text(
    'snippet',
    overrideProps.snippet || "What's <<left>>going<<right>> on?"
  ),
  body: text('body', overrideProps.body || "What's going on?"),
  bodyRanges: overrideProps.bodyRanges || [],
  from: overrideProps.from as PropsType['from'],
  to: overrideProps.to as PropsType['to'],
  getPreferredBadge: overrideProps.getPreferredBadge || (() => undefined),
  isSelected: boolean('isSelected', overrideProps.isSelected || false),
  showConversation: action('showConversation'),
  isSearchingInConversation: boolean(
    'isSearchingInConversation',
    overrideProps.isSearchingInConversation || false
  ),
  theme: React.useContext(StorybookThemeContext),
});

export function Default(): JSX.Element {
  const props = useProps({
    from: someone,
    to: me,
  });

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

export function SenderHasABadge(): JSX.Element {
  const props = useProps({
    from: { ...someone, badges: [{ id: 'sender badge' }] },
    to: me,
    getPreferredBadge: badges => {
      strictAssert(
        badges[0]?.id === 'sender badge',
        'Rendering the wrong badge!'
      );
      return getFakeBadge();
    },
  });

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

SenderHasABadge.story = {
  name: 'Sender has a badge',
};

export function Selected(): JSX.Element {
  const props = useProps({
    from: someone,
    to: me,
    isSelected: true,
  });

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

export function FromYou(): JSX.Element {
  const props = useProps({
    from: me,
    to: someone,
  });

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

export function SearchingInConversation(): JSX.Element {
  const props = useProps({
    from: me,
    to: someone,
    isSearchingInConversation: true,
  });

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

SearchingInConversation.story = {
  name: 'Searching in Conversation',
};

export function FromYouToYourself(): JSX.Element {
  const props = useProps({
    from: me,
    to: me,
  });

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

FromYouToYourself.story = {
  name: 'From You to Yourself',
};

export function FromYouToGroup(): JSX.Element {
  const props = useProps({
    from: me,
    to: group,
  });

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

FromYouToGroup.story = {
  name: 'From You to Group',
};

export function FromSomeoneToGroup(): JSX.Element {
  const props = useProps({
    from: someone,
    to: group,
  });

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

FromSomeoneToGroup.story = {
  name: 'From Someone to Group',
};

export function LongSearchResult(): JSX.Element {
  const snippets = [
    'This is a really <<left>>detail<<right>>ed long line which will wrap and only be cut off after it gets to three lines. So maybe this will make it in as well?',
    "Okay, here are the <<left>>detail<<right>>s:\n\n1355 Ridge Way\nCode: 234\n\nI'm excited!",
  ];

  const props1 = useProps({
    from: someone,
    to: me,
    snippet: snippets[0],
  });

  const props2 = useProps({
    from: someone,
    to: me,
    snippet: snippets[1],
  });

  return (
    <>
      <MessageSearchResult {...props1} />
      <MessageSearchResult {...props2} />
    </>
  );
}

export function EmptyShouldBeInvalid(): JSX.Element {
  const props = useProps();

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

EmptyShouldBeInvalid.story = {
  name: 'Empty (should be invalid)',
};

export function Mention(): JSX.Element {
  const props = useProps({
    body: 'moss banana twine sound lake zoo brain count vacuum work stairs try power forget hair dry diary years no results \uFFFC elephant sorry umbrella potato igloo kangaroo home Georgia bayonet vector orange forge diary zebra turtle rise front \uFFFC',
    bodyRanges: [
      {
        length: 1,
        mentionUuid: '7d007e95-771d-43ad-9191-eaa86c773cb8',
        replacementText: 'Shoe',
        conversationID: 'x',
        start: 113,
      },
      {
        length: 1,
        mentionUuid: '7d007e95-771d-43ad-9191-eaa86c773cb8',
        replacementText: 'Shoe',
        conversationID: 'x',
        start: 237,
      },
    ],
    from: someone,
    to: me,
    snippet:
      '...forget hair dry diary years no <<left>>results<<right>> \uFFFC <<left>>elephant<<right>> sorry umbrella potato igloo kangaroo home Georgia...',
  });

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

Mention.story = {
  name: '@mention',
};

export function MentionRegexp(): JSX.Element {
  const props = useProps({
    body: '\uFFFC This is a (long) /text/ ^$ that is ... specially **crafted** to (test) our regexp escaping mechanism! Making sure that the code we write works in all sorts of scenarios',
    bodyRanges: [
      {
        length: 1,
        mentionUuid: '7d007e95-771d-43ad-9191-eaa86c773cb8',
        replacementText: 'RegExp',
        conversationID: 'x',
        start: 0,
      },
    ],
    from: someone,
    to: me,
    snippet:
      '\uFFFC This is a (long) /text/ ^$ that is ... <<left>>specially<<right>> **crafted** to (test) our regexp escaping mechanism...',
  });

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

MentionRegexp.story = {
  name: '@mention regexp',
};

export function MentionNoMatches(): JSX.Element {
  const props = useProps({
    body: '\uFFFC hello',
    bodyRanges: [
      {
        length: 1,
        mentionUuid: '7d007e95-771d-43ad-9191-eaa86c773cb8',
        replacementText: 'Neo',
        conversationID: 'x',
        start: 0,
      },
    ],
    from: someone,
    to: me,
    snippet: '\uFFFC hello',
  });

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

MentionNoMatches.story = {
  name: '@mention no-matches',
};

export const _MentionNoMatches = (): JSX.Element => {
  const props = useProps({
    body: 'moss banana twine sound lake zoo brain count vacuum work stairs try power forget hair dry diary years no results \uFFFC elephant sorry umbrella potato igloo kangaroo home Georgia bayonet vector orange forge diary zebra turtle rise front \uFFFC',
    bodyRanges: [
      {
        length: 1,
        mentionUuid: '7d007e95-771d-43ad-9191-eaa86c773cb8',
        replacementText: 'Shoe',
        conversationID: 'x',
        start: 113,
      },
      {
        length: 1,
        mentionUuid: '7d007e95-771d-43ad-9191-eaa86c773cb8',
        replacementText: 'Shoe',
        conversationID: 'x',
        start: 237,
      },
    ],
    from: someone,
    to: me,
    snippet:
      '...forget hair dry diary years no results \uFFFC elephant sorry umbrella potato igloo kangaroo home Georgia...',
  });

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

_MentionNoMatches.story = {
  name: '@mention no-matches',
};

export function DoubleMention(): JSX.Element {
  const props = useProps({
    body: 'Hey \uFFFC \uFFFC test',
    bodyRanges: [
      {
        length: 1,
        mentionUuid: '9eb2eb65-992a-4909-a2a5-18c56bd7648f',
        replacementText: 'Alice',
        conversationID: 'x',
        start: 4,
      },
      {
        length: 1,
        mentionUuid: '755ec61b-1590-48da-b003-3e57b2b54448',
        replacementText: 'Bob',
        conversationID: 'x',
        start: 6,
      },
    ],
    from: someone,
    to: me,
    snippet: '<<left>>Hey<<right>> \uFFFC \uFFFC <<left>>test<<right>>',
  });

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

DoubleMention.story = {
  name: 'Double @mention',
};
