import * as React from "react";
import { ImageStyle, View } from "react-native";
import * as R from "ramda";
import { QBImage } from "@applicaster/zapp-react-native-ui-components/Components/Image";
import { toBooleanWithDefaultFalse } from "@applicaster/zapp-react-native-utils/booleanUtils";

import { useImageSourceWithDefault, useCheckFailedUri } from "./hooks";
import useImageSize from "./hooks/useImageSize";

type Source = {
  uri: string;
};

type Props = Record<string, any> & {
  style: ImageStyle;
  uri?: string;
  placeholderImage?: string;
  entry?: ZappEntry | ZappFeed;
  withDimensions: (source: Source) => Source;
};

const MemoizedImage = React.memo(QBImage, R.equals);

const isValidExternalSource = (source): boolean =>
  source?.uri?.startsWith("http") ||
  source?.uri?.startsWith("data:image") ||
  source?.uri?.startsWith("file://");

export default function Image({
  style,
  uri,
  placeholderImage,
  entry,
  withDimensions,
  ...otherProps
}: Props) {
  const [showDefault, setShowDefault] = React.useState(false);
  const { appendFailedToLoadUri, isFailedToLoadUri } = useCheckFailedUri();
  // TODO: RE-implement this feature so it applies red overlay on too big images, instead of logging.
  // runOnceCheckTooBigImageSize(
  //   uri,
  //   toFiniteNumberWithDefault(0, style.width),
  //   toFiniteNumberWithDefault(0, style.height)
  // );

  const source = useImageSourceWithDefault({
    uri,
    entry,
    showDefault,
    placeholderImage: placeholderImage || "",
    otherProps,
  });

  const onError = React.useCallback(() => {
    appendFailedToLoadUri(uri);
    setShowDefault(true);
  }, []);

  const fallback = React.useMemo(
    () => showDefault || !isValidExternalSource(source),
    [source?.uri, showDefault]
  );

  const applyMaxSize = toBooleanWithDefaultFalse(otherProps?.applyMaxSize);

  const sourceWithMaxSizes = useImageSize({
    style,
    applyMaxSize,
    source,
    withDimensions,
  });

  if (isFailedToLoadUri(uri) || !isValidExternalSource(source)) {
    return <View style={style} />;
  }

  return (
    <MemoizedImage
      style={style}
      source={sourceWithMaxSizes}
      fallback={fallback}
      onError={onError}
      {...R.omit(["source"], otherProps)}
    />
  );
}
