<template>
  <span class="uif-upload" :class="classes" @click="handleClick" @paste="handlePaste"
       @dragover.prevent="hover = true" @dragleave.prevent="hover = false" @drop.prevent="onDrop">
    <slot :hover="hover"></slot>
    <input ref="input" type="file" class="uif-upload-input" :multiple="multiple"
           @change="handleChange" :accept="accept">
  </span>
</template>
<script>
import Notice from '@uif/hq/src/prototypes/notice'
import {filter, findIndex, forEach, toArray} from '@uif/hq/src/utils/array'

function getDefaultModifiers (maxSize, extList) {
  return [
    {
      // 检查文件大小
      name: 'size',
      disabled: false,
      check: (file) => file.size <= maxSize,
      message: '上传文件最大不能超过5M'
    },
    {
      // 检查文件扩展名
      name: 'ext',
      disabled: false,
      check: (file) => {
        if (!extList.length) return true
        const name = typeof file.name === 'string' ? file.name : ''
        const ext = name.substr(name.lastIndexOf('.') + 1).toUpperCase()
        return extList.map(e => e.toUpperCase()).includes(ext.toUpperCase())
      },
      message: '文件类型不合法'
    }
  ]
}

export default {
  name: 'u-upload',
  props: {
    multiple: {
      type: Boolean,
      default: false
    },
    paste: {
      type: Boolean,
      default: false
    },
    disabled: {
      type: Boolean,
      default: false
    },
    // input原生属性
    accept: {
      type: String
    },
    // 文件类型检查
    ext: {
      type: Array,
      default () {
        return []
      }
    },
    // 检查文件大小
    maxSize: {
      type: Number,
      default: 5 * 1024 * 1024
    },
    // 检查文件方法
    modifiers: {
      type: Array,
      default () {
        return []
      }
    },
    // 检查错误使用Notice警告
    notice: {
      type: Boolean,
      default: true
    }
  },
  data () {
    return {
      hover: false
    }
  },
  computed: {
    classes () {
      return {
        'disabled': this.disabled,
        'available': !this.disabled,
        'uif-upload-drag-hover': this.hover
      }
    }
  },
  methods: {
    handleClick () {
      if (this.disabled) return
      this.$refs.input.click()
      this.$emit('focus')
    },
    handleChange (e) {
      const files = e.target.files
      if (!files) return
      this.uploadFiles(files)
      this.$refs.input.value = null
    },
    onDrop (e) {
      this.hover = false
      if (this.disabled) return
      this.uploadFiles(e.dataTransfer.files)
    },
    handlePaste (e) {
      if (this.disabled) return
      if (this.paste) {
        this.uploadFiles(e.clipboardData.files)
      }
    },
    uploadFiles (files) {
      let fileList = toArray(files)
      if (!this.multiple) fileList = [fileList[0]]
      if (fileList.length > 0 && this.checkFiles(fileList)) {
        this.$emit('change', fileList)
      }
      this.$emit('blur')
    },
    // 检查文件列表
    checkFiles (files) {
      const modifiers = this.getModifiers()
      for (let i = 0; i < files.length; i++) {
        const file = files[i]
        for (let j = 0; j < modifiers.length; j++) {
          const {check, message} = modifiers[j]
          if (!check(file)) {
            if (this.notice) {
              Notice.warning(message)
            }
            this.$emit('error', {file, modifier: modifiers[j]})
            return false
          }
        }
      }
      return true
    },
    // 获取检查文件方法
    getModifiers () {
      const values = getDefaultModifiers(this.maxSize, this.ext)
      forEach(this.modifiers, (value) => {
        if (value.name) {
          const index = findIndex(values, ({name}) => name && (name === value.name))
          if (index >= 0) values.splice(index, 1)
        }
        values.push(value)
      })
      return filter(values, value => !value.disabled)
    }
  }
}
</script>
