<template>
  <span :is="tag" class="n-upload" :class="{hover: focus}" @dragover.prevent="setFocus(true)" @dragleave.prevent="setFocus(false)"
        @click="onClick" @paste="onPaste" @drop.prevent="onDrop">
    <slot :focus="focus"></slot>
    <input ref="input" type="file" class="n-upload-input" :multiple="multiple"
           @change="onChange" :accept="accept">
  </span>
</template>
<script>
import toast from '@uif/next/lib/prototypes/toast'
import {prop, toArray, isArray, toString, filterUnique, Timeout} from '@uif/next/lib/utils/tools'
import modifiers from '_common/modifiers'

export default {
  name: 'n-upload',
  props: {
    // 标签
    tag: prop.string('span'),
    // 多选
    multiple: prop.boolean(),
    // 监听粘贴事件
    paste: prop.boolean(),
    // 禁用
    disabled: prop.boolean(),
    // 文件类型检查
    ext: {
      type: [Array, String],
      default: ''
    },
    // 文件大小 ( 兆 )
    size: prop.number(5),
    // 检查文件方法
    modifiers: prop.array(),
    // 检查错误使用Notice警告
    notice: prop.boolean(true)
  },
  data () {
    return {
      focus: false,
      time: new Timeout()
    }
  },
  computed: {
    extList ({ext}) {
      return isArray(ext) ? ext : filterUnique(toString(ext).split(','))
    },
    accept ({extList}) {
      return extList.map(v => '.' + v).join(',')
    }
  },
  methods: {
    setFocus (value) {
      this.focus = value
      this.time.out(() => this.$emit(value ? 'u-focus' : 'u-blur', this), 10)
    },
    onClick () {
      if (!this.disabled) {
        this.$refs.input.click()
        this.setFocus(true)
      }
    },
    onChange (e) {
      if (e.target.files) {
        this.uploadFiles(e.target.files)
        this.$refs.input.value = null
      }
      this.setFocus(false)
    },
    onDrop (e) {
      if (!this.disabled) {
        this.uploadFiles(e.dataTransfer.files)
      }
      this.setFocus(false)
    },
    onPaste (e) {
      if (this.paste && !this.disabled) {
        this.uploadFiles(e.clipboardData.files)
      }
      this.setFocus(false)
    },
    uploadFiles (files) {
      let fileList = toArray(files)
      if (!this.multiple) fileList = [fileList[0]]
      if (fileList.length > 0 && this.checkFiles(fileList)) {
        this.$emit('change', fileList)
      }
    },
    // 检查文件列表
    checkFiles (files) {
      const values = modifiers.getModifiers(this.size, this.extList, this.modifiers)
      const {success, modifier, data} = modifiers.useModifiers(files, values)
      if (!success) {
        if (this.notice) {
          toast.warning(modifier.message)
        }
        this.$emit('error', {file: data, modifier: modifier})
        return false
      }
      return true
    }
  }
}
</script>
