import React, {useCallback, useEffect, useRef, useState} from 'react';
import {TouchableOpacity, View} from 'react-native';
import {GiphyMediaID, GiphyMediaView} from '@giphy/react-native-sdk';
import {IconGif} from '@tabler/icons-react-native';
import {GifAsset} from '@modules/chats/interfaces';
import {useViewPort} from '@modules/chats/screens/ChatMessages/components/Messages/components/ViewPortProvider';
import {useTheme} from '@shared/theme';

import {styles} from './styles';

interface Props {
  attachment: GifAsset;
  itemId: string;
}

//For Giphy SDK Limitations, we are pausing the gif after 30 seconds of reproduction or when it goes out the viewport
const GIF_MAXIMUM_DURATION = 30000;
export const GifMessageDisplayer = ({attachment, itemId}: Props) => {
  const [hasReproduced, setHasReproduced] = useState(false);
  const {theme, colors} = useTheme();
  const mediaViewRef = useRef<GiphyMediaView>(null);
  const timeoutRef = useRef<NodeJS.Timeout>(undefined);
  const {subscribe} = useViewPort();
  const unsubscribeRef = useRef<(() => void) | null>(null);
  const [isVisible, setIsVisible] = useState(false);

  const subscribeToViewPort = useCallback(() => {
    if (unsubscribeRef.current) {
      return;
    }

    unsubscribeRef.current = subscribe(viewPort => {
      if (viewPort.some(item => item.item.id === itemId && item.isViewable)) {
        setIsVisible(true);
      } else {
        setIsVisible(false);
      }
    });
  }, [subscribe, itemId]);

  const mediaGif = attachment.external_reference as GiphyMediaID;

  const onActivateGif = () => {
    if (timeoutRef.current) {
      clearTimeout(timeoutRef.current);
      timeoutRef.current = undefined;
    }
    setHasReproduced(false);
    mediaViewRef.current?.resume();
    timeoutRef.current = setTimeout(() => {
      mediaViewRef.current?.pause();
      setHasReproduced(true);
    }, GIF_MAXIMUM_DURATION);
  };

  useEffect(() => {
    if (timeoutRef.current) {
      clearTimeout(timeoutRef.current);
      timeoutRef.current = undefined;
    }
    if (isVisible) {
      if (!hasReproduced) {
        setHasReproduced(false);
        mediaViewRef.current?.resume();
        timeoutRef.current = setTimeout(() => {
          mediaViewRef.current?.pause();
          setHasReproduced(true);
        }, GIF_MAXIMUM_DURATION);
      }
    } else {
      setHasReproduced(false);
      mediaViewRef.current?.pause();
    }
    return () => {
      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current);
        timeoutRef.current = undefined;
      }
    };
  }, [isVisible, hasReproduced]);

  useEffect(() => {
    subscribeToViewPort();
    return () => {
      unsubscribeRef.current?.();
      unsubscribeRef.current = null;
    };
  }, [subscribeToViewPort]);

  return (
    <View
      style={[
        styles.container,
        {
          width: attachment.image_width,
          height: attachment.image_height,
        },
      ]}>
      <TouchableOpacity
        style={[
          {
            width: attachment.image_width,
            height: attachment.image_height,
          },
          styles.gifIconContainer,
        ]}
        activeOpacity={hasReproduced ? 1 : 0}
        onPress={onActivateGif}>
        {hasReproduced && (
          <View
            style={[
              styles.gifIconInnerContainer,
              {backgroundColor: colors.grey.transparent['800-60']},
            ]}>
            <IconGif color={theme.text.neutral.inverted} />
          </View>
        )}
      </TouchableOpacity>
      <GiphyMediaView
        ref={mediaViewRef}
        autoPlay={isVisible}
        media={mediaGif}
        style={{
          width: attachment.image_width,
          height: attachment.image_height,
        }}
      />
    </View>
  );
};
