import React, {useEffect} from 'react';
import {Image, StyleSheet, Text} from 'react-native';
import {View} from 'react-native-animatable';
import {
  cancelAnimation,
  Easing,
  useSharedValue,
  withTiming,
} from 'react-native-reanimated';
import {useDispatch, useSelector} from 'react-redux';
import {checkMomentDoneProcessing} from '../../services';
import {loadUserMoments} from '../../store/actions';
import {setMomentUploadProgressBar} from '../../store/reducers';
import {RootState} from '../../store/rootReducer';
import {MomentUploadStatusType} from '../../types';
import {normalize, SCREEN_WIDTH, StatusBarHeight} from '../../utils';
import {GradientProgressBar} from '../common';

interface MomentUploadProgressBarProps {}

const MomentUploadProgressBar: React.FC<MomentUploadProgressBarProps> =
  ({}) => {
    const dispatch = useDispatch();
    const {userId: loggedInUserId} = useSelector(
      (state: RootState) => state.user.user,
    );
    const {momentUploadProgressBar} = useSelector(
      (state: RootState) => state.user,
    );
    const progress = useSharedValue(0);
    const showLoading =
      momentUploadProgressBar?.status ===
        MomentUploadStatusType.UploadingToS3 ||
      momentUploadProgressBar?.status ===
        MomentUploadStatusType.WaitingForDoneProcessing;

    useEffect(() => {
      let doneProcessing = false;
      const checkDone = async () => {
        if (
          momentUploadProgressBar &&
          (await checkMomentDoneProcessing(momentUploadProgressBar!.momentId))
        ) {
          doneProcessing = true;
          cancelAnimation(progress);
          // upload is done, but let's finish the progress bar animation in a velocity of 10%/s
          const finishProgressBarDuration = (1 - progress.value) * 10 * 1000;
          progress.value = withTiming(1, {
            duration: finishProgressBarDuration,
            easing: Easing.linear,
          });
          // change status to Done 1s after the progress bar animation is done
          setTimeout(() => {
            dispatch(loadUserMoments(loggedInUserId));
            dispatch({
              type: setMomentUploadProgressBar.type,
              payload: {
                momentUploadProgressBar: {
                  ...momentUploadProgressBar,
                  status: MomentUploadStatusType.Done,
                },
              },
            });
          }, finishProgressBarDuration);
        }
      };
      if (
        momentUploadProgressBar?.status ===
        MomentUploadStatusType.WaitingForDoneProcessing
      ) {
        checkDone();
        const timer = setInterval(async () => {
          if (!doneProcessing) {
            checkDone();
          }
        }, 5 * 1000);
        // timeout if takes longer than 1 minute to process
        setTimeout(() => {
          clearInterval(timer);
          if (!doneProcessing) {
            console.error('Check for done processing timed out');
            dispatch({
              type: setMomentUploadProgressBar.type,
              payload: {
                momentUploadProgressBar: {
                  ...momentUploadProgressBar,
                  status: MomentUploadStatusType.Error,
                },
              },
            });
          }
        }, 60 * 1000);
        return () => clearInterval(timer);
      }
    }, [momentUploadProgressBar?.status]);

    useEffect(() => {
      if (
        momentUploadProgressBar?.status === MomentUploadStatusType.UploadingToS3
      ) {
        // e.g. 30s video => 30 * 3 = 60s
        const videoDuration =
          momentUploadProgressBar.originalVideoDuration ?? 30;
        const durationInSeconds = videoDuration * 3;
        progress.value = withTiming(1, {
          duration: durationInSeconds * 1000,
          easing: Easing.out(Easing.quad),
        });
      }
    }, [momentUploadProgressBar?.status]);

    useEffect(() => {
      if (
        momentUploadProgressBar?.status === MomentUploadStatusType.Done ||
        momentUploadProgressBar?.status === MomentUploadStatusType.Error
      ) {
        progress.value = 0;
        // clear this component after a duration
        setTimeout(() => {
          dispatch({
            type: setMomentUploadProgressBar.type,
            payload: {
              momentUploadProgressBar: undefined,
            },
          });
        }, 5000);
      }
    }, [momentUploadProgressBar?.status]);

    if (!momentUploadProgressBar) {
      return null;
    }

    return (
      <View
        style={[
          styles.background,
          momentUploadProgressBar?.status === MomentUploadStatusType.Error
            ? styles.redBackground
            : {},
        ]}>
        <View style={styles.container}>
          {showLoading && (
            <>
              <Text style={styles.text}>Uploading Moment...</Text>
              <GradientProgressBar style={styles.bar} progress={progress} />
            </>
          )}
          {momentUploadProgressBar.status === MomentUploadStatusType.Done && (
            <View style={styles.row}>
              <Image
                source={require('../../assets/images/green-check.png')}
                style={styles.x}
              />
              <Text style={styles.text}>
                Beautiful, the Moment was uploaded successfully!
              </Text>
            </View>
          )}
          {momentUploadProgressBar.status === MomentUploadStatusType.Error && (
            <View style={styles.row}>
              <Image
                source={require('../../assets/images/white-x.png')}
                style={styles.x}
              />
              <Text style={styles.whiteText}>
                Unable to upload Moment. Please retry
              </Text>
            </View>
          )}
        </View>
      </View>
    );
  };

const styles = StyleSheet.create({
  background: {
    position: 'absolute',
    zIndex: 999,
    height: StatusBarHeight + normalize(84),
    backgroundColor: 'white',
    width: '100%',
    alignItems: 'center',
  },
  container: {
    justifyContent: 'center',
    marginTop: StatusBarHeight,
    height: normalize(84),
  },
  text: {
    fontSize: normalize(14),
    fontWeight: 'bold',
    lineHeight: 17,
    marginVertical: 12,
    width: '80%',
  },
  bar: {
    width: SCREEN_WIDTH * 0.9,
  },
  redBackground: {
    backgroundColor: '#EA574C',
  },
  row: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  whiteText: {
    color: 'white',
    fontSize: normalize(14),
    fontWeight: 'bold',
    lineHeight: 17,
    marginVertical: 12,
  },
  x: {
    width: normalize(26),
    height: normalize(26),
    marginRight: 10,
  },
});

export default MomentUploadProgressBar;
