import React, { memo } from 'react';
import { IStickerEmoji, IStickerPack } from '@livelike/javascript';
import { Image, TextStyle, StyleSheet, ImageStyle } from 'react-native';
import { ComponentStyleProp, LLComponentStyleFn } from '../../types';
import { useStickerPacks, useStyles } from '../../hooks';
import { LLText } from '../LLText';

export type LLChatMessageItemBodyTextStyles = {
  text: TextStyle;
  deletedMessageText: TextStyle;
  selfMessageText: TextStyle;
  stickerImage: ImageStyle;
};

export type LLChatMessageItemBodyTextProps =
  ComponentStyleProp<LLChatMessageItemBodyTextStyles> & {
    message: string;
    isDeleted: boolean;
    isSelfMessage: boolean;
  };

const DELIMITER: string = '__$';
const STICKER_REG = /:[^\/\/]([^:]*):/g;

export const LLChatMessageItemBodyText = memo(
  ({
    message,
    styles: stylesProp,
    isDeleted,
    isSelfMessage,
  }: LLChatMessageItemBodyTextProps) => {
    const messageItemBodyTextStyles = useStyles({
      componentStylesFn: getMessageItemBodyTextStyles,
      stylesProp,
    });
    const { stickerPacks } = useStickerPacks();

    if (isDeleted) {
      return (
        <LLText
          style={[
            messageItemBodyTextStyles.text,
            messageItemBodyTextStyles.deletedMessageText,
          ]}
        >
          Message deleted
        </LLText>
      );
    }

    const firstShortcode = message.indexOf(':') === 0;
    const shortcodeNum = (message.match(STICKER_REG) || []).length;
    const size = shortcodeNum > 1 || message.split(' ').length > 1 ? 22 : 90;
    const messages: any = {};
    let stickerIdCounter = 0;
    let textIdCounter = 0;

    message = message.replace(STICKER_REG, (w) => {
      const allStickers = stickerPacks
        ? stickerPacks.reduce(
            (a: IStickerEmoji[], c: IStickerPack) => a.concat(c.stickers),
            []
          )
        : [];
      const foundSticker =
        allStickers.length > 0 &&
        allStickers.find((s: IStickerEmoji) => s.shortcode === w.slice(1, -1));

      if (foundSticker) {
        messages[w] = (
          <Image
            key={`${foundSticker.id}_${stickerIdCounter++}`}
            resizeMode="contain"
            style={[
              {
                height: size,
                width: size,
                marginLeft: firstShortcode ? 0 : 2,
              },
              messageItemBodyTextStyles.stickerImage,
            ]}
            source={{
              uri: foundSticker.file,
            }}
          />
        );
        return `${DELIMITER}${w}${DELIMITER}`;
      }
      return w;
    });

    const convertStringToTextComponent = (value: string) => {
      return (
        <LLText
          key={`${value}_${textIdCounter++}`}
          style={[
            messageItemBodyTextStyles.text,
            isDeleted && messageItemBodyTextStyles.deletedMessageText,
            isSelfMessage && messageItemBodyTextStyles.selfMessageText,
          ]}
        >
          {value}
        </LLText>
      );
    };

    const textMessagesToRender = message
      .split(DELIMITER)
      .map((w) => messages[w] || convertStringToTextComponent(w));

    return <>{textMessagesToRender}</>;
  }
);

const getMessageItemBodyTextStyles: LLComponentStyleFn<
  LLChatMessageItemBodyTextStyles
> = ({ theme }) =>
  StyleSheet.create({
    text: {
      color: theme.text,
    },
    deletedMessageText: {
      fontStyle: 'italic',
    },
    selfMessageText: {},
    stickerImage: {
      marginTop: 0,
      marginBottom: 0,
      marginRight: 2,
    },
  });
