import React, {useCallback, useEffect, useRef, useState} from 'react';
import {StyleSheet, View} from 'react-native';
import {useTranslation} from 'react-i18next';
import {Camera, useCameraDevice} from 'react-native-vision-camera';
import Text from '@components/Text';
import ActivityIndicator from '@components/ActivityIndicator';
import BackButton from '@components/BackButton';
import {UserAvatar} from '@components/Image';
import {useBackHandler} from '@hooks/useBackHandler';
import {useSafeAreaBottomPadding} from '@hooks/useSafeAreaBottomPadding';
import {Navigation} from '@interfaces/navigation';
import {User} from '@interfaces/user';
import {GettingReadyType} from '@modules/commons/interfaces';
import {useAppSelector} from '@redux/utils';
import {COLORS} from '@shared/colors';
import {Screens} from '@shared/constants';
import {getCompleteName, wait} from '@shared/utils';
import {SPACING} from '@shared/theme';

import CallFooter from './components/CallFooter';
import InactiveFeatureModal from './components/InactiveFeatureModal';
import LiveIndicator from './components/LiveIndicator';
import StreamingFooter from './components/StreamingFooter';
import {styles} from './styles';

export const READY_TIMEOUT = 2500;
export const INACTIVE_MODAL_TIMEOUT = 10000;

function GettingReady({
  navigation,
  route: {
    params: {type},
  },
}: Navigation<Screens.GETTING_READY>) {
  const {t} = useTranslation();
  const device = useCameraDevice('front');
  const currentUser = useAppSelector(({user}) => user) as User;
  const [isLive, setIsLive] = useState(false);
  const [isReady, setIsReady] = useState(false);
  const [showModal, setShowModal] = useState(false);
  const [showCamera, setShowCamera] = useState(
    type !== GettingReadyType.AudioCall,
  );
  const modalTimeoutRef = useRef<NodeJS.Timeout>(undefined);
  const paddingBottom = useSafeAreaBottomPadding({
    extra: isLive ? SPACING.x2 : SPACING.x4,
  });
  const isVideoCall = type === GettingReadyType.VideoCall;
  const isStreaming = type === GettingReadyType.Streaming;
  const canGoBack = isStreaming && !isLive;

  const onGoBack = useCallback(() => {
    clearTimeout(modalTimeoutRef.current);
    navigation.goBack();
    return true;
  }, [navigation]);

  useBackHandler(canGoBack ? onGoBack : () => true);

  const onCloseModal = useCallback(async () => {
    setShowModal(false);
    // To avoid overlapping between closing and back animations
    await wait(250);
    navigation.goBack();
  }, [navigation]);

  const onOpenModal = useCallback(() => {
    modalTimeoutRef.current = setTimeout(
      () => setShowModal(true),
      INACTIVE_MODAL_TIMEOUT,
    );
  }, []);

  useEffect(() => {
    const readyTimeout = setTimeout(() => setIsReady(true), READY_TIMEOUT);
    !isStreaming && onOpenModal();
    return () => {
      clearTimeout(readyTimeout);
    };
  }, [isStreaming, onGoBack, onOpenModal]);

  useEffect(() => {
    const headerLeft = () => (
      <BackButton color={COLORS.WHITE} onPress={onGoBack} />
    );
    navigation.setOptions(
      canGoBack
        ? {headerLeft, headerStyle: styles.header}
        : {gestureEnabled: false, headerShown: false},
    );
  }, [canGoBack, navigation, onGoBack]);

  const onToggleCamera = () => setShowCamera(prevState => !prevState);

  const onStartStream = () => {
    setIsLive(true);
    onOpenModal();
  };

  return (
    <View style={styles.container}>
      <LiveIndicator isLive={isLive} />
      {isReady ? (
        <>
          {(isVideoCall || isStreaming) && showCamera && !!device ? (
            <Camera
              isActive
              device={device}
              outputOrientation="preview"
              style={StyleSheet.absoluteFill}
            />
          ) : (
            <View style={styles.avatarContainer}>
              <UserAvatar size="5xl" />
              <Text variant="subtitle1" color={COLORS.WHITE}>
                {getCompleteName(currentUser)}
              </Text>
            </View>
          )}
          <InactiveFeatureModal
            showModal={showModal}
            onCloseModal={onCloseModal}
            type={type}
          />
        </>
      ) : (
        <View style={styles.textContainer}>
          <Text variant="h6" color={COLORS.WHITE}>
            {t('general.getting_ready')}
          </Text>
          {!isStreaming && (
            <Text variant="body1" color={COLORS.WHITE}>
              {t('general.join_in_a_moment')}
            </Text>
          )}
          <ActivityIndicator size="large" style={styles.loadingIndicator} />
        </View>
      )}
      <View
        style={[
          styles.bottomContainer,
          isLive && styles.finishContainer,
          {paddingBottom},
        ]}>
        {isStreaming ? (
          <StreamingFooter
            isLive={isLive}
            isReady={isReady}
            onFinishStream={onGoBack}
            onStartStream={onStartStream}
          />
        ) : (
          <CallFooter
            isReady={isReady}
            isVideoCall={isVideoCall}
            onFinishCall={onGoBack}
            onToggleCamera={onToggleCamera}
          />
        )}
      </View>
    </View>
  );
}

export default GettingReady;
