<template>
  <span :class="avatarClass" :style="sizeStyle">
    <img
      v-if="(src || srcSet) && !hasLoadError"
      :src="src"
      :alt="alt"
      :srcset="srcSet"
      :style="fitStyle"
      @error="handleError"
    />
    <el-icon v-else-if="icon">
      <component :is="icon" />
    </el-icon>
    <slot v-else></slot>
  </span>
</template>

<script lang="ts">
import { defineComponent, computed, ref, watch } from 'vue'
import { ElIcon } from '@element-ultra/components/icon'
import { useNamespace } from '@element-ultra/hooks'
import { isNumber, isString, addUnit } from '@element-ultra/utils'
import { avatarEmits, avatarProps } from './avatar'

import type { CSSProperties } from 'vue'

export default defineComponent({
  name: 'ElAvatar',
  components: {
    ElIcon,
  },
  props: avatarProps,
  emits: avatarEmits,

  setup(props, { emit }) {
    const ns = useNamespace('avatar')

    const hasLoadError = ref(false)

    const avatarClass = computed(() => {
      const { size, icon, shape } = props
      const classList = [ns.b()]
      if (isString(size)) classList.push(ns.m(size))
      if (icon) classList.push(ns.m('icon'))
      if (shape) classList.push(ns.m(shape))
      return classList
    })

    const sizeStyle = computed(() => {
      const { size } = props
      return isNumber(size)
        ? ({
            '--el-avatar-size': addUnit(size),
          } as CSSProperties)
        : undefined
    })

    const fitStyle = computed<CSSProperties>(() => ({
      objectFit: props.fit,
    }))

    // need reset hasLoadError to false if src changed
    watch(
      () => props.src,
      () => (hasLoadError.value = false)
    )

    function handleError(e: Event) {
      hasLoadError.value = true
      emit('error', e)
    }

    return {
      hasLoadError,
      avatarClass,
      sizeStyle,
      fitStyle,
      handleError,
    }
  },
})
</script>
