<template>
  <view 
    :id="id"
    class="nana-image-wrapper"
    :style="style"
    :class="innerClass"
    @click="handleClick"
  >
    <image 
      :style="{
        width: style.width,
        height: style.height,
      }"
      :mode="($attrs.mode as any)"
      :lazyLoad="$attrs.lazyLoad"
      :fadeShow="$attrs.fadeShow"
      :webp="$attrs.webp"
      :show-menu-by-longpress="$attrs.showMenuByLongpress"
      :draggable="$attrs.draggable"
      :src="isErrorState ? failedImage : (src || defaultImage)"
      @loadstart="isLoadState = true"
      @load="isLoadState = false"
      @error="isErrorState = true; isLoadState = false"
    />
    <view v-if="showFailed && isErrorState && !failedImage" class="inner-view error">
      <Icon icon="warning" color="text.second" :size="32" />
      <Text v-if="realWidth > 50" color="text.second" :text="src ? '加载失败' : '暂无图片'" :fontSize="22" />
    </view>
    <view v-if="showLoading && isLoadState" class="inner-view loading">
      <ActivityIndicator
        :color="themeContext.resolveThemeColor(loadingColor)"
        :size="themeContext.resolveThemeSize(loadingSize)"
      />
    </view>
  </view>
</template>

<script setup lang="ts">
import { computed, getCurrentInstance, nextTick, onMounted, ref, watch } from 'vue';
import { propGetThemeVar, useTheme } from '../theme/ThemeDefine';
import ActivityIndicator from './ActivityIndicator.vue';
import Text from './Text.vue';
import Icon from './Icon.vue';
import { RandomUtils } from '@imengyu/imengyu-utils';

export interface ImageProps {
  /**
   * 图片地址
   */
  src?: string,
  /**
   * 加载失败图片地址
   */
  failedImage?: string,
  /**
   * 为空时图片地址
   */
  defaultImage?: string,
  /**
   * 是否显示加载中提示，默认是
   */
  showLoading?: boolean,
  /**
   * 是否显示加载失败提示，默认是
   */
  showFailed?: boolean,
  /**
   * 是否显示灰色占位，默认是
   */
  showGrey?: boolean,
  width?: string|number,
  height?: string|number,
  /**
   * 是否可以点击预览图片
   */
  clickPreview?: boolean,
  /**
   * 初始加载中状态
   */
  loading?: boolean,
  /**
   * 加载中圆圈颜色
   */
  loadingColor?: string,
  /**
   * 加载中圆圈颜色
   */
  loadingSize?: string|number,
  /**
   * 指定图片是否可以点击，默认否
   */
  touchable?: boolean,
  /**
   * 图片是否有圆角
   */
  round?: boolean,
  /**
   * 当round为true的圆角大小，默认是50%
   */
  radius?: string|number,
  /**
   * 内部样式
   */
  innerStyle?: object;
  innerClass?: string,
}

const id = 'img' + RandomUtils.genNonDuplicateID(20);

defineOptions({
  options: {
    virtualHost: true
  }
})
const props = withDefaults(defineProps<ImageProps>(), {
  src: '',
  failedImage: '',
  defaultImage: '',
  showLoading: true,
  showFailed: true,
  showGrey: () => propGetThemeVar('ImageShowGrey', false),
  loading: false,
  loadingColor: () => propGetThemeVar('ImageLoadingColor', 'border.default'),
  loadingSize: () => propGetThemeVar('ImageLoadingSize', 50),
  touchable: false,
  round: () => propGetThemeVar('ImageRound', false),
  radius: () => propGetThemeVar('ImageRadius', '50%'),
})
const emit = defineEmits([ 'click' ]);

const isErrorState = ref(false);
const isLoadState = ref(true);
const themeContext = useTheme();
const instance = getCurrentInstance();

const style = computed(() => {
  const o : Record<string, any> = {
    borderRadius: props.round ? themeContext.resolveThemeSize(props.radius) : '', 
    backgroundColor: isErrorState.value || props.showGrey ? themeContext.resolveThemeColor('background.imageBox') : 'transparent',
    overflow: 'hidden',
    width: themeContext.resolveThemeSize(props.width),
    height: themeContext.resolveThemeSize(props.height),
    ...props.innerStyle,
  }
  return o;
});
const realWidth = ref(0);

function handleClick() {
  if (props.clickPreview) {
    uni.previewImage({
      urls: [ props.src ],
    })
  }
  if (props.touchable)
    emit('click');
}
function loadSrcState() {
  if (props.src) {
    isErrorState.value = false;
    isLoadState.value = true;
  } else {
    isErrorState.value = true;
    isLoadState.value = false;
  }
}
function measureImage() {
  uni.createSelectorQuery()
    .in(instance)
    .select('#' + id)
    .boundingClientRect((rect) => {
      if (rect)
        realWidth.value = (rect as UniApp.NodeInfo).width || 0;
    }).exec();
}

watch(() => props.src, (newVal, oldVal) => {
  if (!newVal) {
    isErrorState.value = true;
    isLoadState.value = false;
  } else
    isErrorState.value = false;
  nextTick(() => {
    measureImage();
  });
})

onMounted(() => {
  loadSrcState();
  nextTick(() => {
    measureImage();
  })
})
</script>

<style lang="scss">
.nana-image-wrapper {
  position: relative;
  flex-shrink: 0;

  .inner-view {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    display: flex;
    align-items: center;
    justify-content: center;
  }
}
</style>