import Vue from 'vue'
import ToastView from './toast.vue'

const ToastConstructor = Vue.extend(ToastView)

const toastPool = []

const getAnInstance = () => {
  if (toastPool.length > 0) {
    const instance = toastPool[0]
    toastPool.splice(0, 1)
    return instance
  }
  return new ToastConstructor({
    el: document.createElement('div'),
  })
}

const returnAnInstance = instance => {
  if (instance) {
    toastPool.push(instance)
  }
}

const removeDom = event => {
  if (event.target.parentNode) {
    event.target.parentNode.removeChild(event.target)
  }
}

ToastConstructor.prototype.close = function close() {
  this.visible = false
  this.$el.addEventListener('transitionend', removeDom)
  this.closed = true
  returnAnInstance(this)
}

function Toast(options = {}) {
  const duration = options.duration || 2000
  const instance = getAnInstance()
  instance.closed = false
  clearTimeout(instance.timer)
  instance.message = typeof options === 'string' ? options : options.message
  instance.type = options.type || ''
  instance.icon = options.icon || ''
  if (!instance.icon) {
    switch (instance.type) {
      case 'success':
        instance.icon = 'check-plain'
        break
      case 'fail':
        instance.icon = 'close-plain'
        break
      case 'warning':
        instance.icon = 'warning-plain'
        break
      default:
        instance.icon = ''
    }
  }
  document.body.appendChild(instance.$el)
  Vue.nextTick(() => {
    instance.visible = true
    instance.$el.removeEventListener('transitionend', removeDom)
    if (duration) {
      instance.timer = setTimeout(() => {
        if (instance.closed) return
        instance.close()
      }, duration)
    }
  })
  return instance
}

;['success', 'fail', 'warning'].forEach(method => {
  Toast[method] = (options = {}) => {
    let opt = { type: method }
    if (typeof options === 'string') {
      opt.message = options
    } else {
      opt = Object.assign(opt, options)
    }
    Toast(opt)
  }
})

Toast.install = vueGlobal => {
  /* eslint no-param-reassign: ["error", { "props": false }] */
  vueGlobal.use(ToastView)
  vueGlobal.prototype.$toast = Toast
}

export default Toast
