/* eslint-disable prefer-rest-params */
/* eslint-disable no-unused-expressions */
import './SntToast.scss'
import Vue from 'vue'
import eventBus from '../../services/notification/utils/bus'
import Timer from '../../services/notification/utils/timer'
import Positions from '../../services/notification/utils/positions'
import { removeElement } from '../../services/notification/utils/helpers'

export default Vue.extend({
  name: 'SntToast',
  props: {
    message: {
      type: String,
      required: true
    },
    type: {
      type: String,
      default: 'success'
    },
    icon: {
      type: String,
      default: undefined
    },
    position: {
      type: String,
      default: Positions.BOTTOM_RIGHT,
      validator (value) {
        return Object.values(Positions).includes(value)
      }
    },
    duration: {
      type: Number,
      default: 3000
    },
    dismissible: {
      type: Boolean,
      default: true
    },
    onDismiss: {
      type: Function,
      default: () => {
      }
    },
    onClick: {
      type: Function,
      default: () => {
      }
    },
    queue: Boolean,
    pauseOnHover: {
      type: Boolean,
      default: true
    }
  },
  data () {
    return {
      isActive: false,
      parentTop: null,
      parentBottom: null,
      isHovered: false
    }
  },
  computed: {
    classes () {
        return [`v-toast__item--${this.type}`, `v-toast__item--${this.position}`]
    },
    correctParent () {
      switch (this.position) {
        case Positions.TOP:
        case Positions.TOP_RIGHT:
        case Positions.TOP_LEFT:
          return this.parentTop

        case Positions.BOTTOM:
        case Positions.BOTTOM_RIGHT:
        case Positions.BOTTOM_LEFT:
          return this.parentBottom
        default:
          return null
      }
    },
    transition () {
      switch (this.position) {
        case Positions.TOP:
        case Positions.TOP_RIGHT:
        case Positions.TOP_LEFT:
          return {
            enter: 'v-toast--fade-in-down',
            leave: 'v-toast--fade-out'
          }

        case Positions.BOTTOM:
        case Positions.BOTTOM_RIGHT:
        case Positions.BOTTOM_LEFT:
          return {
            enter: 'v-toast--fade-in-up',
            leave: 'v-toast--fade-out'
          }
        default:
          return {}
      }
    }
  },
  beforeMount () {
    this.setupContainer()
  },
  mounted () {
    this.showNotice()
    eventBus.on('toast-clear', this.dismiss)
  },
  beforeDestroy () {
    eventBus.off('toast-clear', this.dismiss)
  },
  methods: {
    setupContainer () {
      this.parentTop = document.querySelector('.v-toast.v-toast--top')
      this.parentBottom = document.querySelector('.v-toast.v-toast--bottom')
      // No need to create them, they already exists
      if (this.parentTop && this.parentBottom) return

      if (!this.parentTop) {
        this.parentTop = document.createElement('div')
        this.parentTop.className = 'v-toast v-toast--top'
      }

      if (!this.parentBottom) {
        this.parentBottom = document.createElement('div')
        this.parentBottom.className = 'v-toast v-toast--bottom'
      }

      const container = document.body
      container.appendChild(this.parentTop)
      container.appendChild(this.parentBottom)
    },

    shouldQueue () {
      if (!this.queue) return false

      return (
        this.parentTop.childElementCount > 0
        || this.parentBottom.childElementCount > 0
      )
    },

    dismiss () {
      if (this.timer) this.timer.stop()
      clearTimeout(this.queueTimer)
      this.isActive = false

      // Timeout for the animation complete before destroying
      setTimeout(() => {
        this.onDismiss.apply(null, arguments)
        this.$destroy()
        removeElement(this.$el)
      }, 150)
    },

    showNotice () {
      if (this.shouldQueue()) {
        // Call recursively if should queue
        this.queueTimer = setTimeout(this.showNotice, 250)
        return
      }
      this.correctParent.insertAdjacentElement('afterbegin', this.$el)
      this.isActive = true

      if (this.duration) {
        this.timer = new Timer(this.dismiss, this.duration)
      }
    },

    whenClicked () {
      if (!this.dismissible) return
      this.onClick.apply(null, arguments)
      this.dismiss()
    },

    toggleTimer (newVal) {
      if (!this.pauseOnHover || !this.timer) return
      newVal ? this.timer.pause() : this.timer.resume()
    }
  },
  template: `
    <transition
      :enter-active-class="transition.enter"
      :leave-active-class="transition.leave">
      <div
        role="alert"
        v-show="isActive"
        class="v-toast__item"
        :class="classes"
        @mouseover="toggleTimer(true)"
        @mouseleave="toggleTimer(false)"
        @click="whenClicked">
        <snt-icon
          v-if="icon"
          :icon="icon"
          color="#ffffff"
          class="v-toast__icon"
        />
        <p class="v-toast__text" v-html="message"></p>
      </div>
    </transition>
  `
})
