import React, { useCallback, useState } from 'react';
import {
  TextInput,
  View,
  StyleSheet,
  Image,
  TouchableOpacity,
  Keyboard,
  ViewStyle,
  ImageStyle,
} from 'react-native';
import { IGif } from '@livelike/javascript';
import {
  useAnalytics,
  useChatMessageActions,
  useChatRoomState,
  useCustomFontStyle,
  useStyles,
  useTheme,
  useTrackKeyboardEffect,
} from '../../hooks';
import { ComponentStyleProp, LLComponentStyleFn } from '../../types';
import {
  LLComposerSendButton,
  LLComposerSendButtonProps,
} from './LLComposerSendButton';
import { LLGifPicker, LLGifPickerProps } from '../LLGifPicker';
import { LLStickerPicker, LLStickerPickerProps } from '../LLStickerPicker';

export type LLChatMessageComposerStyles = {
  composerContainer: ViewStyle;
  composerInput: ViewStyle;
  composerIcon: ImageStyle;
};

export type LLChatMessageComposerProps =
  ComponentStyleProp<LLChatMessageComposerStyles> & {
    roomId: string;
    TextInputComponent?: typeof TextInput;
    GifPickerComponent?: typeof LLGifPicker;
    GifPickerComponentStyles?: LLGifPickerProps['styles'];
    StickerPickerComponent?: typeof LLStickerPicker;
    StickerPickerComponentStyles?: LLStickerPickerProps['styles'];
    SendButtonComponent?: typeof LLComposerSendButton;
    SendButtonComponentStyles?: LLComposerSendButtonProps['styles'];
  };

export function LLChatMessageComposer({
  roomId,
  styles: stylesProp,
  TextInputComponent = TextInput,
  GifPickerComponentStyles,
  StickerPickerComponentStyles,
  SendButtonComponentStyles,
  StickerPickerComponent = LLStickerPicker,
  GifPickerComponent = LLGifPicker,
  SendButtonComponent = LLComposerSendButton,
}: LLChatMessageComposerProps) {
  const [inputValue, setInputValue] = useState('');
  const [isGifPickerVisible, setIsGifPickerVisible] = useState(false);
  const [isStickerPickerVisible, setIsStickerPickerVisible] = useState(false);
  const [isSendingMessage, setIsSendingMessage] = useState(false);
  const { theme, themeAssets } = useTheme();
  const messageComposerStyles = useStyles({
    componentStylesFn: getMessageComposerStyles,
    stylesProp,
  });
  const { sendChatMessage } = useChatMessageActions({ roomId });
  const { userAvatarUrl } = useChatRoomState({ roomId });
  const { trackEvent } = useAnalytics();
  const composerInputStyles = useCustomFontStyle({
    style: messageComposerStyles.composerInput,
  });
  useTrackKeyboardEffect();

  const onSendMessage = useCallback(() => {
    const textValue = inputValue.trim();
    if (!textValue) {
      return;
    }
    setIsSendingMessage(true);
    sendChatMessage({
      roomId,
      message: textValue,
      sender_image_url: userAvatarUrl,
    })
      .then((messageRes) => {
        setInputValue('');
      })
      .finally(() => {
        setIsSendingMessage(false);
      });
  }, [roomId, inputValue, sendChatMessage, userAvatarUrl]);

  const onSelectSticker = useCallback(
    (stickerShortcode: string) => {
      sendChatMessage({
        roomId,
        message: `:${stickerShortcode}:`,
        sender_image_url: userAvatarUrl,
      }).then((imageMessageRes) => {
        setIsStickerPickerVisible(false);
      });
    },
    [roomId, sendChatMessage, userAvatarUrl]
  );

  const onSelectGif = useCallback(
    (gif: IGif) => {
      sendChatMessage({
        roomId,
        sender_image_url: userAvatarUrl,
        image_url: gif.images.downsized.url,
        image_width: gif.images.downsized.width,
        image_height: gif.images.downsized.height,
      }).then((imageMessageRes) => {
        Keyboard.dismiss();
        setIsGifPickerVisible(false);
      });
    },
    [sendChatMessage, roomId, userAvatarUrl]
  );

  const onStickerPanelOpen = useCallback(() => {
    trackEvent('Sticker Panel Opened', { roomId });
  }, [roomId]);
  const onStickerPanelClose = useCallback(() => {
    trackEvent('Sticker Panel Closed', { roomId });
  }, [roomId]);
  const onGifPanelOpen = useCallback(() => {
    trackEvent('GIF Panel Opened', { roomId });
  }, [roomId]);
  const onGifPanelClose = useCallback(() => {
    trackEvent('GIF Panel Closed', { roomId });
  }, [roomId]);
  const toggleStickerPicker = useCallback(() => {
    if (!isStickerPickerVisible) {
      Keyboard.dismiss();
      setIsStickerPickerVisible(true);
    } else {
      setIsStickerPickerVisible(false);
    }
  }, [isStickerPickerVisible]);

  const toggleGifPicker = useCallback(() => {
    if (!isGifPickerVisible) {
      Keyboard.dismiss();
      setIsGifPickerVisible(true);
    } else {
      setIsGifPickerVisible(false);
    }
  }, [isGifPickerVisible]);

  const onInputPressIn = useCallback(() => {
    if (isStickerPickerVisible) {
      setIsStickerPickerVisible(false);
    } else if (isGifPickerVisible) {
      setIsGifPickerVisible(false);
    }
  }, [isStickerPickerVisible, isGifPickerVisible]);

  if (isGifPickerVisible) {
    return (
      <GifPickerComponent
        visible={isGifPickerVisible}
        onPanelOpen={onGifPanelOpen}
        onPanelClose={onGifPanelClose}
        onSelectGif={onSelectGif}
        closeGifPicker={toggleGifPicker}
        styles={GifPickerComponentStyles}
      />
    );
  }

  if (isStickerPickerVisible) {
    return (
      <StickerPickerComponent
        visible={isStickerPickerVisible}
        onPanelOpen={onStickerPanelOpen}
        onPanelClose={onStickerPanelClose}
        onSelectSticker={onSelectSticker}
        closeStickerPicker={toggleStickerPicker}
        styles={StickerPickerComponentStyles}
      />
    );
  }

  return (
    <View style={messageComposerStyles.composerContainer}>
      <TextInputComponent
        style={composerInputStyles}
        onChangeText={setInputValue}
        onPressIn={onInputPressIn}
        value={inputValue}
        editable={!isSendingMessage}
        placeholder="Start typing"
        placeholderTextColor={theme.secondaryText}
      />
      {inputValue.length === 0 ? (
        <>
          <TouchableOpacity
            onPress={toggleGifPicker}
            accessibilityLabel="Gifs"
            disabled={isSendingMessage}
          >
            <Image
              style={messageComposerStyles.composerIcon}
              source={themeAssets.gif}
            />
          </TouchableOpacity>
          <TouchableOpacity
            onPress={toggleStickerPicker}
            accessibilityLabel="Stickers"
            disabled={isSendingMessage}
          >
            <Image
              style={messageComposerStyles.composerIcon}
              source={themeAssets.sticker}
            />
          </TouchableOpacity>
        </>
      ) : (
        <SendButtonComponent
          onPress={onSendMessage}
          disabled={isSendingMessage || inputValue.length === 0}
          isSendingMessage={isSendingMessage}
          styles={SendButtonComponentStyles}
        />
      )}
    </View>
  );
}

const getMessageComposerStyles: LLComponentStyleFn<
  LLChatMessageComposerStyles
> = ({ theme }) =>
  StyleSheet.create({
    composerContainer: {
      flexDirection: 'row',
      alignItems: 'center',
      padding: 10,
      backgroundColor: theme.secondaryBackground,
    },
    composerInput: {
      flex: 1,
      height: 45,
      borderRadius: 10,
      paddingHorizontal: 12,
      marginRight: 10,
      color: theme.text,
      backgroundColor: theme.background,
    },
    composerIcon: {
      height: 24,
      width: 24,
      marginHorizontal: 10,
    },
  });
