<template>
  <div
    class="avatar-container"
    :style="{
      width: avatarSize,
      height: avatarSize,
      borderRadius: avatarBorderRadius,
    }"
  >
    <div
      v-if="useAvatarSkeletonAnimation && !isImgLoaded"
      :class="{
        placeholder: true,
        hidden: isImgLoaded,
        'skeleton-animation': useAvatarSkeletonAnimation,
      }">
    </div>
      <image
        :src="avatarImageUrl || defaultAvatarUrl"
        @load="avatarLoadSuccess"
        @error="avatarLoadFailed"
        style="object-fit: contain; width: 100%; height: 100%;"
      />
  </div>
</template>

<script setup lang="ts">
import vue from '../../../adapter-vue';
const { ref, toRefs } = vue;

interface IProps {
  url: string;
  size?: string;
  borderRadius?: string;
  useSkeletonAnimation?: boolean;
}

interface IEmits {
  (key: 'onLoad', e: Event): void;
  (key: 'onError', e: Event): void;
}

const defaultAvatarUrl = ref(
  'https://web.sdk.qcloud.com/im/desk/assets/user_default_avatar.png',
);
const emits = defineEmits<IEmits>();
const props = withDefaults(defineProps<IProps>(), {
  // uniapp vue2 does not support constants in defineProps
  url: 'https://web.sdk.qcloud.com/im/desk/assets/user_default_avatar.png',
  size: '36px',
  borderRadius: '50%',
  useSkeletonAnimation: false,
});

const {
  size: avatarSize,
  url: avatarImageUrl,
  borderRadius: avatarBorderRadius,
  useSkeletonAnimation: useAvatarSkeletonAnimation,
} = toRefs(props);

let reloadAvatarTime = 0;
const isImgLoaded = ref<boolean>(false);
const loadErrorInUniapp = ref<boolean>(false);

function avatarLoadSuccess(e: Event) {
  isImgLoaded.value = true;
}

function avatarLoadFailed(e: Event) {
  reloadAvatarTime += 1;
  if (reloadAvatarTime > 3) {
    return;
  }
  loadErrorInUniapp.value = true;
  emits('onError', e);
}
</script>

<style scoped lang="scss">
:not(not) {
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  min-width: 0;
}

.avatar-container {
  position: relative;
  justify-content: center;
  align-items: center;
  overflow: hidden;
  flex: 0 0 auto;

  .placeholder {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: #ececec;
    transition: opacity 0.3s, background-color 0.1s ease-out;

    &.skeleton-animation {
      animation: breath 2s linear 0.3s infinite;
    }

    &.hidden {
      opacity: 0;
    }
  }

  .avatar-image {
    width: 100%;
    height: 100%;
    opacity: 1;
  }
}

@keyframes breath {
  50% {
    /* stylelint-disable-next-line scss/no-global-function-names */
    background-color: darken(#ececec, 10%);
  }
}
</style>
