import { identity, isNil } from "ramda";
import {
  POSITION_OVER_IMAGE,
  DISPLAY_MODE_DYNAMIC,
  DISPLAY_MODE_FIXED,
  VISIBILITY_ALWAYS,
  VISIBILITY_DEFAULT,
  VISIBILITY_FOCUSED,
  IMAGE_POSITION,
  IMAGE_SIZING_FIT,
  IMAGE_SIZING_FILL,
  FIT_POSITION,
} from "@applicaster/zapp-react-native-utils/manifestUtils/secondaryImage";
import { ImageStyle } from "react-native";

const SECONDARY_IMAGE_PREFIX = "secondary_image";

type ImageSizing = typeof IMAGE_SIZING_FIT | typeof IMAGE_SIZING_FILL;

type ImagePosition = (typeof IMAGE_POSITION)[keyof typeof IMAGE_POSITION];

export type DisplayMode =
  | typeof DISPLAY_MODE_FIXED
  | typeof DISPLAY_MODE_DYNAMIC;

export enum SecondaryImageStyleKeys {
  ENABLE = "switch",
  IMAGE_KEY = "image_key",
  VISIBILITY = "visibility",
  DISPLAY_MODE = "display_mode",
  FIXED_HEIGHT = "fixed_height",
  FIXED_WIDTH = "fixed_width",
  IMAGE_SIZING = "image_sizing",
  FIT_POSITION = "fit_position",
  DYNAMIC_WIDTH = "dynamic_width",
  POSITION = "position",
  ALIGN = "align",
  IMAGE_POSITION = "image_position",
  CORNER_RADIUS = "corner_radius",
  MARGIN_TOP = "margin_top",
  MARGIN_BOTTOM = "margin_bottom",
  MARGIN_LEFT = "margin_left",
  MARGIN_RIGHT = "margin_right",
}

export const getSecondaryImageStylesFor =
  (value) =>
  (key: SecondaryImageStyleKeys, transformFn = identity) =>
    transformFn(value(`${SECONDARY_IMAGE_PREFIX}_${key}`));

export const isPositionOverImage = (position: string): boolean =>
  position === POSITION_OVER_IMAGE;

export const isDisplayModeFixed = (displayMode: DisplayMode): boolean =>
  displayMode === DISPLAY_MODE_FIXED;

export const isImageSizingFit = (imageSizing: ImageSizing): boolean =>
  imageSizing === IMAGE_SIZING_FIT;

export const toSize = ({
  displayMode,
  fixedWidth,
  fixedHeight,
  dynamicWidth,
}): { width: number; height: Option<number> } => {
  if (isDisplayModeFixed(displayMode)) {
    return { width: fixedWidth, height: fixedHeight };
  }

  return { width: dynamicWidth, height: undefined };
};

export const isVisible = (visibility, state): boolean => {
  if (isNil(visibility)) {
    // for mobile cells we don't have visibilty into configuration and assume is is === always
    return true;
  }

  if (VISIBILITY_ALWAYS === visibility) {
    return true;
  }

  if (VISIBILITY_DEFAULT === visibility && state === "default") {
    return true;
  }

  if (VISIBILITY_FOCUSED === visibility && state.includes("focused")) {
    return true;
  }

  return false;
};

export const getImageContainerStyles = (imagePosition: ImagePosition) => {
  const position = {
    position: "absolute",
  };

  if (imagePosition === IMAGE_POSITION.TOP_LEFT) {
    return {
      ...position,
      top: 0,
      left: 0,
    };
  }

  if (imagePosition === IMAGE_POSITION.TOP_RIGHT) {
    return {
      ...position,
      top: 0,
      right: 0,
    };
  }

  if (imagePosition === IMAGE_POSITION.BOTTOM_LEFT) {
    return {
      ...position,
      bottom: 0,
      left: 0,
    };
  }

  if (imagePosition === IMAGE_POSITION.BOTTOM_RIGHT) {
    return {
      ...position,
      bottom: 0,
      right: 0,
    };
  }

  if (imagePosition === IMAGE_POSITION.CENTER) {
    return {
      ...position,
      top: 0,
      right: 0,
      bottom: 0,
      left: 0,
      alignItems: "center",
      justifyContent: "center",
    };
  }

  return {};
};

const calculateImageSize = ({
  imageDimension,
  containerWidth,
  containerHeight,
}) => {
  const imageWidth = imageDimension.width;
  const imageHeight = imageDimension.height;

  const imageAspectRatio = imageWidth / imageHeight;
  const containerAspectRatio = containerWidth / containerHeight;

  const calculatedImageWidth =
    imageAspectRatio > containerAspectRatio
      ? containerWidth
      : containerHeight * imageAspectRatio;

  const calculatedImageHeight =
    imageAspectRatio > containerAspectRatio
      ? containerWidth / imageAspectRatio
      : containerHeight;

  return { width: calculatedImageWidth, height: calculatedImageHeight };
};

export const getStyle = ({
  imageSizing,
  fitPosition,
  displayMode,
  imageDimension,
  containerWidth,
  containerHeight,
}): ImageStyle => {
  if (!isImageSizingFit(imageSizing)) {
    return {
      width: containerWidth,
      height: containerHeight,
    };
  }

  const imageSize = calculateImageSize({
    imageDimension,
    containerWidth,
    containerHeight,
  });

  if (!isDisplayModeFixed(displayMode)) {
    return imageSize;
  }

  switch (fitPosition) {
    case FIT_POSITION.BOTTOM_RIGHT:
      return {
        position: "absolute",
        bottom: 0,
        right: 0,
        ...imageSize,
      };
    case FIT_POSITION.BOTTOM_CENTER:
      return {
        position: "absolute",
        bottom: 0,
        ...imageSize,
        alignSelf: "center",
      };
    case FIT_POSITION.BOTTOM_LEFT:
      return {
        position: "absolute",
        bottom: 0,
        left: 0,
        ...imageSize,
      };
    case FIT_POSITION.TOP_RIGHT:
      return {
        position: "absolute",
        top: 0,
        right: 0,
        ...imageSize,
      };
    case FIT_POSITION.TOP_CENTER:
      return {
        position: "absolute",
        top: 0,
        ...imageSize,
        alignSelf: "center",
      };
    case FIT_POSITION.TOP_LEFT:
      return {
        position: "absolute",
        top: 0,
        left: 0,
        ...imageSize,
      };
    case FIT_POSITION.CENTER_RIGHT:
      return {
        position: "absolute",
        right: 0,
        ...imageSize,
      };
    case FIT_POSITION.CENTER_LEFT:
      return {
        position: "absolute",
        left: 0,
        ...imageSize,
      };
    default:
      return imageSize;
  }
};
