function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { Animated, Image as RNImage, Platform, StyleSheet, View } from "react-native";
import CacheManager from "./cache-manager";
import Box from "../../atoms/box/box";
import { BlurView } from "expo-blur";
import Spinner from "../../atoms/spinner/spinner";
import { pearl } from "../../../pearl";
import Center from "../../atoms/center/center";
import { createStyleFunction, transformColorValue } from "../../../theme/src/style-functions";
import { useStyleProps } from "../../../hooks";
function usePrevious(value) {
  const ref = useRef();
  useEffect(() => {
    ref.current = value;
  });
  return ref.current;
}
const PearlRNImage = pearl(RNImage, {
  componentName: "",
  type: "basic",
  animatable: true
});
const AnimatedView = Animated.createAnimatedComponent(View);
const AnimatedBlurView = Animated.createAnimatedComponent(BlurView);
const PearlAnimatedBlurView = pearl(AnimatedBlurView, {
  componentName: "",
  type: "basic",
  animatable: true
});
const PearlAnimatedView = pearl(AnimatedView, {
  componentName: "",
  type: "basic",
  animatable: true
});
const previewColorStyleFunction = createStyleFunction({
  property: "previewColor",
  styleProperty: "previewColor",
  themeKey: "palette",
  transform: transformColorValue
});
const CustomImage = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef(({
  atoms
}, ref) => {
  const {
    source,
    onError,
    testID,
    fallbackSource,
    fallbackComponent,
    previewSource,
    imageDownloadOptions,
    isCached = true,
    loaderType = "spinner",
    tint = "dark",
    sourceDelay = 0,
    overlayTransitionDuration = 300,
    ...restImageProps
  } = atoms.image;
  const isRemoteImage = typeof source === "object";
  const shouldCache = isRemoteImage && isCached;
  const isMounted = useRef(true);
  const [uri, setUri] = useState(undefined);
  const [error, setError] = useState(false);
  const previousUri = usePrevious(uri);
  const imageProps = useStyleProps(atoms.image, [previewColorStyleFunction]);
  const {
    previewColor
  } = imageProps.style;
  const isImageReady = useMemo(() => isRemoteImage ? !!uri : true, [isRemoteImage, uri]);
  const finalSource = useMemo(() => isRemoteImage ? {
    ...source,
    uri: uri
  } : source, [isRemoteImage, source, uri]);
  const intensity = useRef(new Animated.Value(100)).current;
  const previewSourceOverlayOpacity = intensity.interpolate({
    inputRange: [0, 100],
    outputRange: [0, 1]
  });
  const blurIntensity = intensity.interpolate({
    inputRange: [0, 100],
    outputRange: [0, 50]
  });
  const finalImageOpacity = intensity.interpolate({
    inputRange: [0, 100],
    outputRange: [1, 0.75]
  });
  const backwardCompatibleTintOverlayOpacity = intensity.interpolate({
    inputRange: [0, 100],
    outputRange: [0, 0.5]
  });
  const previewColorOverlayOpacity = intensity.interpolate({
    inputRange: [0, 100],
    outputRange: [0, 1]
  });
  const {
    borderRadius,
    borderBottomLeftRadius,
    borderBottomRightRadius,
    borderTopLeftRadius,
    borderTopRightRadius,
    ...finalContainerProps
  } = atoms.container;
  const borderRadiiStyles = useMemo(() => ({
    borderRadius,
    borderBottomLeftRadius,
    borderBottomRightRadius,
    borderTopLeftRadius,
    borderTopRightRadius
  }), [borderRadius, borderBottomLeftRadius, borderBottomRightRadius, borderTopLeftRadius, borderTopRightRadius]);
  const onErrorHandler = error => {
    setError(true);
    if (onError) onError(error);
  };
  const loadRemoteImage = async (uri, options = {}) => {
    await new Promise(resolve => setTimeout(resolve, sourceDelay));
    if (shouldCache && Platform.OS !== "web") {
      try {
        const path = await CacheManager.get(uri, options).getPath();
        if (isMounted.current) {
          if (path) {
            setUri(path);
          } else {
            onErrorHandler({
              nativeEvent: {
                error: new Error("Could not load image")
              }
            });
          }
        }
      } catch (error) {
        onErrorHandler({
          nativeEvent: {
            error
          }
        });
      }
    } else {
      setUri(uri);
    }
  };
  const renderFallback = useCallback(() => {
    if (error) {
      if (!!fallbackComponent) {
        return /*#__PURE__*/React.createElement(Box, _extends({
          overflow: "hidden"
        }, borderRadiiStyles, {
          style: {
            zIndex: 4
          }
        }), /*#__PURE__*/React.cloneElement(fallbackComponent));
      }
      if (!!fallbackSource) {
        return /*#__PURE__*/React.createElement(PearlRNImage, _extends({}, atoms.fallbackImage, borderRadiiStyles, {
          zIndex: 3,
          width: "100%",
          height: "100%",
          source: fallbackSource,
          style: StyleSheet.absoluteFill
        }));
      }
      return null;
    }
    return null;
  }, [error, fallbackComponent, fallbackSource, borderRadiiStyles]);
  const renderFinalImage = useCallback(() => {
    if (isImageReady) {
      return /*#__PURE__*/React.createElement(AnimatedView, {
        style: [StyleSheet.absoluteFill, {
          zIndex: 3,
          width: "100%",
          height: "100%",
          opacity: finalImageOpacity
        }]
      }, /*#__PURE__*/React.createElement(PearlRNImage, _extends({}, restImageProps, borderRadiiStyles, {
        ref: ref,
        onError: onErrorHandler,
        testID: testID,
        source: finalSource,
        width: "100%",
        height: "100%"
      })));
    }
    return null;
  }, [ref, isImageReady, restImageProps, borderRadiiStyles, onErrorHandler, testID, finalSource]);
  const renderPreview = useCallback(() => {
    if (!!previewSource) {
      return /*#__PURE__*/React.createElement(AnimatedView, {
        style: {
          width: "100%",
          height: "100%",
          opacity: previewSourceOverlayOpacity
        }
      }, /*#__PURE__*/React.createElement(PearlRNImage, _extends({}, atoms.previewImage, borderRadiiStyles, {
        source: previewSource,
        zIndex: 1,
        width: "100%",
        height: "100%",
        style: StyleSheet.absoluteFill,
        blurRadius: Platform.OS === "android" || Platform.OS === "web" ? 0.5 : 0
      })));
    }
  }, [previewSource, borderRadiiStyles]);
  const renderImageLoader = () => {
    if (typeof finalSource === "number") return null;
    if (loaderType === "progressive") {
      if (!!previewSource) {
        if (Platform.OS === "ios" && tint !== "none") {
          return /*#__PURE__*/React.createElement(PearlAnimatedBlurView, _extends({
            tint: tint
          }, borderRadiiStyles, {
            zIndex: 3,
            overflow: "hidden",
            alignItems: "center",
            justifyContent: "center",
            intensity: blurIntensity,
            style: [StyleSheet.absoluteFill]
          }), renderFallback());
        } else {
          return /*#__PURE__*/React.createElement(AnimatedView, {
            style: [StyleSheet.absoluteFill, {
              zIndex: 3,
              width: "100%",
              height: "100%",
              opacity: backwardCompatibleTintOverlayOpacity
            }]
          }, /*#__PURE__*/React.createElement(Box, _extends({}, borderRadiiStyles, {
            w: "100%",
            h: "100%",
            overflow: "hidden",
            alignItems: "center",
            justifyContent: "center",
            bgColor: tint === "none" ? undefined : tint === "light" ? "white" : "black"
          }), renderFallback()));
        }
      }
      if (!!previewColor) {
        return /*#__PURE__*/React.createElement(AnimatedView, {
          style: {
            zIndex: 3,
            width: "100%",
            height: "100%",
            opacity: previewColorOverlayOpacity
          }
        }, /*#__PURE__*/React.createElement(Box, _extends({}, borderRadiiStyles, {
          w: "100%",
          h: "100%",
          overflow: "hidden",
          alignItems: "center",
          justifyContent: "center",
          bgColor: previewColor
        }), renderFallback()));
      }
    }
    if (loaderType === "spinner") {
      if (!error) return /*#__PURE__*/React.createElement(Box, {
        width: "100%",
        height: "100%",
        style: StyleSheet.absoluteFill
      }, /*#__PURE__*/React.createElement(Spinner, _extends({}, atoms.spinner, {
        isExpanded: true
      })));
      return renderFallback();
    }
  };
  useEffect(() => {
    let reduceIntensity = false;
    if (isRemoteImage) {
      loadRemoteImage(source.uri, imageDownloadOptions);
      if (uri && !previousUri) reduceIntensity = true;
    } else reduceIntensity = true;
    if (reduceIntensity) Animated.timing(intensity, {
      toValue: 0,
      duration: overlayTransitionDuration,
      useNativeDriver: Platform.OS === "android"
    }).start();
    return () => {
      isMounted.current = false;
    };
  }, [uri, isRemoteImage, loadRemoteImage, source, imageDownloadOptions, overlayTransitionDuration]);
  return /*#__PURE__*/React.createElement(Center, _extends({}, finalContainerProps, borderRadiiStyles, {
    accessible: true,
    accessibilityRole: "image"
  }), renderFinalImage(), renderPreview(), renderImageLoader());
}));

/** The Image component is used to display images. */
const Image = pearl(CustomImage, {
  componentName: "Image",
  type: "molecule",
  animatable: true
}, undefined, {
  partForOverridenStyleProps: "container",
  partForOverridenNativeProps: "image",
  partForOverridenAnimationProps: "container"
});
Image.displayName = "Image";
export default Image;
//# sourceMappingURL=image.js.map