<template>
  <transition
    ref="root"
    :name="transition"
  >
    <div
      v-show="isActive"
      tabindex="0"
      class="vc-loading is-active"
      :class="{
        'is-full-page': fullPage,
      }"
      :aria-busy="isActive"
      aria-label="Loading"
    >
      <div
        class="vc-loading__background"
      />
      <div class="vc-loading__content">
        <slot name="default">
          <component
            :is="loader"
            :color="color"
            :size="size"
            :icon="icon"
          />
        </slot>
      </div>
    </div>
  </transition>
</template>

<script lang="ts">
import { defineComponent, PropType } from 'vue'
import Circles from '@/components/VcLoading/Loaders/Circles.vue'
import LoadIcon from '@/components/VcLoading/Loaders/LoadIcon.vue'
import Stretch from '@/components/VcLoading/Loaders/Stretch.vue'
import LdsSpinner from '@/components/VcLoading/Loaders/LdsSpinner.vue'
import { VcLoadingType } from './VcLoading.types'
import DomHandler from '@/utils/DomHandler'

const DEFAULT_SIZE = 40
const DEFAULT_TYPE = 'circles'
const DEFAULT_COLOR = 'primary'

type NumberOrNumberString = PropType<string | number | undefined>

export default defineComponent({
  name: 'VcLoading',
  components: {
    Circles,
    LoadIcon,
    Stretch,
    LdsSpinner
  },
  props: {
    active: {
      type: Boolean,
      default: true
    },
    fullPage: {
      type: Boolean,
      default: false
    },
    color: {
      type: String,
      default: DEFAULT_COLOR
    },
    size: {
      type: [Number, String] as NumberOrNumberString,
      default: DEFAULT_SIZE
    },
    loader: {
      type: String as PropType<VcLoadingType>,
      default: DEFAULT_TYPE
    },
    icon: {
      type: String,
      default: undefined
    }
  },
  data () {
    return {
      transition: 'fade-loading'
    }
  },
  computed: {
    isActive () {
      return this.active
    }
  },
  watch: {
    active (val) {
      if (!val && this.fullPage) {
        DomHandler.removeClass(document.body, 'overflow-hidden')
      } else if (val && this.fullPage) {
        DomHandler.addClass(document.body, 'overflow-hidden')
      }
    }
  },
  mounted () {
    if (this.$refs.root) {
      const parent = (this.$refs.root as HTMLElement).parentElement
      if (parent) {
        parent.classList.add('relative')
      }
    }
  }
})
</script>

<style lang="scss" scoped>
  .vc-loading {
    @apply
    absolute
    bottom-0
    left-0
    right-0
    top-0
    items-center
    justify-center
    overflow-hidden;
    display: none;
    z-index: 1;

    &.is-active {
      @apply flex;
    }

    &.is-full-page {
      @apply fixed;
      z-index: 9999;
    }

    &__background {
      @apply
      absolute
      bottom-0
      left-0
      right-0
      top-0
      opacity-50
      pointer-events-none
      bg-white;
    }

    &__content {
      @apply relative;
    }
  }
  .fade-loading-enter-active, .fade-loading-leave-active {
    transition: opacity .5s;
  }
  .fade-loading-enter, .fade-loading-leave-to {
    @apply opacity-0;
  }
</style>
