import React, { useEffect, useRef } from 'react';
import { Animated, Modal, StyleSheet } from 'react-native';
import { Box, AnimatedBox } from '../Box';
import { SliderText } from './components/SliderText';

interface INewLoadingDefault {
  /**
   * A message description
   */
  text: Array<string>;
  /**
   * Open a lightbox with loading progress
   */
  show: boolean;
}

interface IWithAnimationOnly extends INewLoadingDefault {
  percentage?: never;
  setPercentage?: never;
}

interface IWithDownloadSupport extends INewLoadingDefault {
  /**
   * Percentage of completed download request
   * `content-length` is required.
   * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Length
   */
  percentage: number;
  /**
   * If percentage download is supported
   * then `setPercentage` is required to change download status
   */
  setPercentage: (progress: React.SetStateAction<number>) => void;
}

type TNewLoading = IWithAnimationOnly | IWithDownloadSupport;

/**
 * Enable to use only if there is progress status from API.
 * Otherwise it just works like any other animation.
 *
 * @example
 * ## Fake progress (Only animated progress)
 *
 * ```js
 * <NewLoading
 *    text="Estamos generando tu orden"
 *    show={show}
 * />
 * ```
 *
 * @example
 * ## With progress percentage (if this is supported)
 * `content-length` is required
 *
 * ```js
 * <NewLoading
 *    text="Estamos generando tu orden"
 *    show={show}
 *    percentage={progress}
 *    setPercentage={setPercentage}
 * />
 * ```
 *
 * ### Request with Axios
 * ```js
 * const [show, setShow] = useState(false);
 * const [percentage, setPercentage] = useState(0);
 * const request = async () => {
 *   setPercentage(0);
 *   await axios({
 *     url: `http://universities.hipolabs.com/search?country=United+States`,
 *     method: 'GET',
 *     responseType: 'json',
 *     onDownloadProgress: (progressEvent) => {
 *       const percentCompleted = Math.round(
 *         (progressEvent.loaded * 100) / progressEvent.total
 *       );
 *       setPercentage(percentCompleted);
 *       if (percentCompleted === 100) {
 *         setTimeout(() => {
 *           setShow(false);
 *         }, 5000);
 *       }
 *     },
 *   });
 * };
 * ```
 *
 */
export const NewLoading = ({
  text,
  show,
  percentage,
  setPercentage,
}: TNewLoading) => {
  const progress = useRef(new Animated.Value(0)).current;

  const animation = Animated.timing(progress, {
    duration: 6000,
    toValue: 100,
    useNativeDriver: false,
  });

  useEffect(() => {
    if (show && !setPercentage) {
      animation.start(({ finished }) => {
        if (finished) {
          animation.reset();
        }
      });
    }
  }, [animation, show, setPercentage]);

  return (
    <Modal transparent={true} visible={show} animationType="fade">
      <Box
        flex={1}
        pointerEvents="box-none"
        style={StyleSheet.absoluteFill}
        collapsable={false}
        alignItems="center"
        justifyContent="center"
        backgroundColor="white"
      >
        <Box width="100%" paddingHorizontal="spacing-l">
          <SliderText text={text} />
          <Box
            width="100%"
            height={4}
            flexDirection="row"
            backgroundColor="gray25"
            borderRadius={50}
            marginTop="spacing-m"
          >
            <AnimatedBox
              backgroundColor="chiperBrandRed"
              borderRadius={50}
              justifyContent="center"
              alignItems="center"
              style={{
                ...StyleSheet.absoluteFillObject,
                width:
                  percentage && !!setPercentage
                    ? `${percentage}%`
                    : progress.interpolate({
                        inputRange: [0, 100],
                        outputRange: ['0%', '100%'],
                      }),
              }}
            />
          </Box>
        </Box>
      </Box>
    </Modal>
  );
};
