<template>
  <div
    :class="imgWrapClassComputed"
    ref="imgWrapRef"
  >
    <template v-if="!isLoading && !isError">
      <img
        :src="imgSrc"
        :style="imgStyleComputed"
        :class="`w-full block ${needHeightAuto ? 'h-auto' : 'h-full'}`"
        :alt="imgSrc"
      />
    </template>
    <!-- 加载loading -->
    <img
      :src="loadingPic"
      alt="loading"
      class="w-1/5 uno-min-w-20 uno-min-h-20 uno-max-w-60 uno-max-h-60 absolute-middle-center animate-spin"
      v-if="isLoading && needLoading"
    />
    <!-- 加载失败 -->
    <img
      :src="loadingFailPic"
      alt="failure"
      class="w-1/5 uno-min-w-20 uno-min-h-20 uno-max-w-60 uno-max-h-60 absolute-middle-center"
      v-if="isError"
    />
    <slot name="picFooter" />
  </div>
</template>

<script lang="ts">
/*
 * @Author: Liao.xiuli
 * @Date: 2021-09-18 11:18:59
 * @Last Modified by: Liao.xiuli
 * @Last Modified time: 2023-12-28 13:39:18
 */
export default {
  name: "WlPic",
};
</script>

<script setup lang="ts">
import { ref, computed, CSSProperties, watch, defineExpose } from "vue";
import { loadingPic, loadingFailPic } from "@mobileUI/utils/cdn";
import { loadImage, isTencentCosPic, isBase64 } from "@mobileUI/utils/index";

enum ECosType {
  normal = "imageView2/1/q/85",
  thumbnail = "imageView2/1/w/100/h/100/q/85",
}

type TCosTyoe = "thumbnail" | "normal";

type TObjectFit = "fill" | "contain" | "cover" | "none" | "scale-down";

type Props = {
  src: string;
  needCos?: boolean;
  cosType?: TCosTyoe;
  radius?: boolean;
  round?: boolean;
  needLoading?: boolean;
  needMiddleCenter?: boolean;
  needHeightAuto?: boolean;
  fit?: TObjectFit;
};

const props = withDefaults(defineProps<Props>(), {
  src: "",
  needCos: true,
  cosType: "normal",
  radius: false,
  round: false,
  needLoading: true,
  needMiddleCenter: true,
  needHeightAuto: false,
  fit: "fill",
});

const isLoading = ref(true);
const isError = ref(false);
const imgSrc = ref("");
const imgWrapRef = ref("");

const imgStyleComputed = computed((): CSSProperties => {
  return {
    "border-radius": props.round ? "50%" : "",
    "object-fit": props.fit,
  };
});

const imgWrapClassComputed = computed(() => {
  return [
    "wl-img", "wh-full", "relative", "flex-col",
    props.needMiddleCenter ? "flex-middle-center" : "",
  ];
});

const onLoadImage = (url) => {
  return new Promise((resolve, reject) => {
    loadImage(url)
      .then((elem: HTMLImageElement) => {
        resolve(elem);
      })
      .catch((reason) => {
        reject(reason);
      })
      .finally(() => {
        isLoading.value = false;
      });
  });
};

const setImgSrc = (url) => {
  const needCos = isTencentCosPic(url) && props.needCos;
  const file_type = url.split(".").pop();
  let isSvg = file_type === "svg";
  let isBase64Bool = isBase64(url);
  //非svg和props.needCos为true才会用cos
  if (isSvg || !needCos || isBase64Bool) {
    imgSrc.value = url;
    onLoadImage(imgSrc.value).catch(() => {
      isError.value = true;
    });
  } else {
    imgSrc.value = `${url}?${ECosType[props.cosType]}`;
    onLoadImage(imgSrc.value).catch(() => {
      imgSrc.value = url;
    });
  }
};

watch(
  () => props.src,
  (val) => {
    if (val) {
      isLoading.value = true;
      setImgSrc(props.src);
    }
  },
  { immediate: true }
);

defineExpose({
  imgWrapRef
})
</script>
