<template>
  <transition
    enter-active-class="fadeIn"
    leave-active-class="fadeOut"
    @after-leave="$emit('closed')"
  >
    <div
      v-if="visible"
      class="ptc-toast"
      :class="{ 'ptc-toast--loading': icon === 'loading' }"
    >
      <i v-if="icon !== 'none'" class="ptc-toast__icon"></i>
      <span class="ptc-toast__message">{{ message }}</span>
    </div>
  </transition>
</template>

<script setup lang="ts">
import { getCurrentInstance, ref, watch } from 'vue'

const props = withDefaults(
  defineProps<{
    visible: boolean
    message: string
    duration?: number
    icon?: 'loading' | 'none'
  }>(),
  {
    duration: 2000,
    icon: 'none',
  }
)
const emit = defineEmits<{
  (e: 'closed'): void
  (e: 'update:visible', val: boolean): void
}>()

let tid: NodeJS.Timeout

const close = () => emit('update:visible', false)
const reset = () => {
  clearTimeout(tid)
  if (props.duration) {
    tid = setTimeout(close, props.duration)
  }
}

watch(
  () => props.visible,
  val => val && reset()
)
watch(() => props.message, reset)
</script>

<style lang="scss">
.ptc-toast {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  box-sizing: content-box;

  // hack for avoid max-width when use left & fixed
  min-width: 192px;
  max-width: 60%;
  width: fit-content;
  padding: 22px 38px;
  color: #fff;
  font-size: 28px;
  line-height: 40px;

  // allow newline charactor
  white-space: pre-wrap;
  text-align: center;
  word-wrap: break-word;
  background-color: rgba(0, 0, 0, 0.7);
  border-radius: 12px;
  z-index: 9999;

  &--loading {
    padding: 56px 24px 40px;
  }

  &__icon {
    margin-bottom: 32px;
    width: 64px;
    height: 64px;
    background-size: contain;

    .ptc-toast--loading & {
      background-image: url(@img/loading.svg);
      animation: rotate 1s linear infinite;
    }
  }
}
</style>
