import * as React from "react";
import { isNil } from "ramda";
import { ImageStyle, View } from "react-native";
import {
  FIT_POSITION,
  IMAGE_SIZING_FILL,
  IMAGE_SIZING_FIT,
} from "@applicaster/zapp-react-native-utils/manifestUtils/secondaryImage";
import { QBImage as Image } from "@applicaster/zapp-react-native-ui-components/Components/Image";

import { useGetImageDimensions } from "./hooks";
import {
  DisplayMode,
  getStyle,
  isDisplayModeFixed,
  isImageSizingFit,
} from "./utils";
import { withAsyncRenderHOC } from "../../hoc/withAsyncRender";

interface Props {
  displayMode: DisplayMode;
  uri: Nullable<string>;
  style: ImageStyle;
  imageSizing: typeof IMAGE_SIZING_FIT | typeof IMAGE_SIZING_FILL;
  fitPosition: typeof FIT_POSITION;
  fixedWidth: number;
  fixedHeight: number;
  onAsyncRender?: () => void;
}

/** Secondary Image Dynamic does not render until the image is loaded */
const SecondaryImageDynamic = withAsyncRenderHOC(
  (props: Props & { onAsyncRender: () => void }) => {
    const { uri, style, displayMode, imageSizing, fitPosition, onAsyncRender } =
      props;

    const imageDimension = useGetImageDimensions(
      uri,
      style.width as number,
      isImageSizingFit(imageSizing) ? undefined : (style.height as number)
    );

    const containerHeight = imageDimension?.height;

    const containerWidth = style?.width;

    if (isNil(imageDimension?.aspectRatio)) {
      return null;
    }

    return (
      <View style={style} onLayout={onAsyncRender}>
        <Image
          {...props}
          source={{ uri }}
          style={{
            ...getStyle({
              imageSizing,
              fitPosition,
              displayMode,
              imageDimension,
              containerHeight,
              containerWidth,
            }),
            borderRadius: style.borderRadius,
            aspectRatio: imageDimension.aspectRatio,
          }}
        />
      </View>
    );
  }
);

/** Secondary Image Fixed does not render  the image until the image is loaded, but keep container rendered */
const SecondaryImageFixed = (props: Props) => {
  const {
    uri,
    style,
    displayMode,
    imageSizing,
    fitPosition,
    fixedHeight,
    fixedWidth,
  } = props;

  const imageDimension = useGetImageDimensions(
    uri,
    style.width as number,
    isImageSizingFit(imageSizing) ? undefined : (style.height as number)
  );

  return (
    <View style={style}>
      {isNil(imageDimension?.aspectRatio) ? null : (
        <Image
          {...props}
          source={{ uri }}
          style={{
            ...getStyle({
              imageSizing,
              fitPosition,
              displayMode,
              imageDimension,
              containerHeight: fixedHeight,
              containerWidth: fixedWidth,
            }),
            borderRadius: style.borderRadius,
            aspectRatio: imageDimension.aspectRatio,
          }}
        />
      )}
    </View>
  );
};

const SecondaryImageComponent = (props: Props) => {
  const { uri, displayMode } = props;

  if (!uri) {
    return null;
  }

  const isFixed = isDisplayModeFixed(displayMode);

  return isFixed ? (
    <SecondaryImageFixed {...props} />
  ) : (
    <SecondaryImageDynamic {...props} />
  );
};

export const SecondaryImage = SecondaryImageComponent;
