<template>
  <el-image :src="mainSrc" v-bind="elImageProps" class="img-box" :style="{ background: props.errBg }" @load="onImageLoad">
    <!-- 占位图插槽 -->
    <template #placeholder>
      <div class="placeholder-wrapper">
        <slot name="placeholder">
          <img v-if="placeholderSrc" :src="placeholderSrc" class="placeholder-img" :draggable="false" />
        </slot>
      </div>
    </template>
    <!-- 错误状态 -->
    <template #error>
      <div class="error-wrapper" :style="{ background: props.errBg }">
        <slot name="error">
          <solar-gallery-wide-bold-duotone v-if="isUrl" width="min(50%,100px)" height="min(50%,100px)"></solar-gallery-wide-bold-duotone>
        </slot>
      </div>
    </template>
  </el-image>
</template>

<script lang="ts" setup>
  import { computed, ref, watch } from 'vue';
  import type { ImageProps } from 'element-plus';
  import SolarGalleryWideBoldDuotone from '~icons/solar/gallery-wide-bold-duotone';

  type BaseImageProps = Partial<ImageProps> & {
    /** 错误背景色 */
    errBg?: string;
  };

  const props = withDefaults(defineProps<BaseImageProps>(), {
    errBg: 'rgba(255,255,255,0.5)',
  });

  // 定义slots
  defineSlots<{
    /** 占位图插槽 */
    placeholder: (props: Record<string, never>) => any;
    /** 错误状态插槽 */
    error: (props: Record<string, never>) => any;
  }>();

  /** 主图 */
  const mainSrc = ref(props.src || '');
  /** 占位图初始为空 */
  const placeholderSrc = ref('');
  /**
   * 判断是否为有效URL
   */
  const isUrl = computed<boolean>(() => getIsUrl(props.src || ''));
  watch(
    () => props.src,
    (newSrc) => {
      if (newSrc) {
        mainSrc.value = getIsUrl(newSrc) ? newSrc : '';
      }
    },
    { immediate: true }
  );

  /**
   * 判断是否为有效的URL
   * @param src - 待判断的字符串
   * @returns 是否为有效的URL
   */
  function getIsUrl(src: string) {
    if (!src) {
      return false;
    }
    const urlWithoutQuery = src.split('?')[0] || '';
    return urlWithoutQuery.length > 4;
  }

  /**
   * 提取传递给 el-image 的属性
   */
  function getElImageProps() {
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    const { errBg: _, src: ___, ...elProps } = props;
    return elProps;
  }

  const elImageProps = computed(() => getElImageProps());

  /**
   * 图片加载完成 - 核心逻辑
   */
  function onImageLoad() {
    // 加载完成后，将当前图片设为占位图
    placeholderSrc.value = mainSrc.value;
  }
</script>

<style lang="scss" scoped>
  .img-box {
    position: relative;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    overflow: hidden;
  }

  .placeholder-wrapper {
    position: absolute;
    top: 0;
    left: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    background: transparent;

    .placeholder-img {
      width: 100%;
      height: 100%;
      object-fit: cover;
    }
  }
</style>
