/**
* @Author think
* @Date 2019-07-11 10:07
*/

<template>
  <section class="h-file">
    <div class="review-wrap">
      <div v-for="(item,index) in fileList" v-if="previewImage" class="review-img">
        <img v-lazy="item.content" :key="index" @click="showBigPic(index)">
        <i v-if="deleteImage" class="icon ion-trash-a" @click="deleteFile(item,index)"/>
      </div>
      <section v-show="fileList.length < maxCount" class="file-upload">
        <slot/>
        <img v-if="!slot" class="default-img" src="./plus.png">
        <input
          ref="input" :accept="accept" :disabled="disabled" type="file"
          multiple
          @change="change">
      </section>
    </div>
  </section>
</template>

<script>
import ShowPicturePlugin from '../ShowPicture/index'
import { toArray, readFile, isOversize, isImageDataUrl } from './utils'
import axios from 'axios'

export default {
  name: 'HFile',
  props: {
    disabled: {
      type: Boolean,
      default: false,
    },
    afterRead: {
      type: Function,
      default: () => { return true },
    },
    beforeRead: {
      type: Function,
      default: () => { return true },
    },
    uploadConfig: {
      type: Object,
      default: () => {},
    },
    upload: {
      type: Boolean,
      default: false,
    },
    fileList: {
      type: Array,
      default: () => [],
    },
    accept: {
      type: String,
      default: 'image/*',
    },
    maxSize: {
      type: Number,
      default: Number.MAX_VALUE,
    },
    maxCount: {
      type: Number,
      default: Number.MAX_VALUE,
    },
    previewImage: {
      type: Boolean,
      default: true,
    },
    resultType: {
      type: String,
      default: 'dataUrl',
    },
    deleteImage: {
      type: Boolean,
      default: true,
    },
  },
  data () {
    return {
      slot: false,
      fileReadList: [],
      uploadFiles: [],
    }
  },
  mounted () {
    let vm = this
    if (this.$slots.default) {
      vm.slot = true
    } else {
      vm.slot = false
    }
  },
  methods: {
    resetInput () {
      /* istanbul ignore else */
      if (this.$refs.input) {
        this.$refs.input.value = ''
      }
    },
    change ($event) {
      let vm = this
      let { files } = event.target
      if (vm.disabled || !files.length) {
        return
      }
      files = files.length === 1 ? files[0] : [].slice.call(files)
      if (vm.beforeRead) {
        const response = vm.beforeRead(toArray(files))

        if (!response) {
          vm.resetInput()
          return
        }

        if (response.then) {
          response
            .then(() => {
              vm.fileRead(files)
            })
            .catch(vm.resetInput)
        }
      }
      vm.fileRead(files)
    },
    fileRead (files) {
      const oversize = isOversize(files, this.maxSize)
      if (oversize) {
        files = files.filter(file => file.size <= this.maxSize)
      }
      if (Array.isArray(files)) {
        const maxCount = this.maxCount - this.fileList.length

        if (files.length > maxCount) {
          files = files.slice(0, maxCount)
        }

        Promise.all(files.map(file => readFile(file, this.resultType))).then(contents => {
          const fileList = files.map((file, index) => ({
            file,
            content: contents[index],
          }))

          this.onAfterRead(fileList, oversize)
        })
      } else {
        readFile(files, this.resultType).then(content => {
          this.onAfterRead({ file: files, content: content }, oversize)
        })
      }
    },
    onAfterRead (files, oversize) {
      if (oversize) {
        this.$emit('oversize', toArray(files))
        // return
      }
      this.resetInput()
      this.$emit('input', [...this.fileList, ...toArray(files)])
      if (this.afterRead) {
        this.afterRead(toArray(files))
      }
      if (this.upload) {
        this.fileReadList = [...this.fileList, ...toArray(files)]
        this.uploadFiles = Object.assign(this.uploadFiles, toArray(files))
        this.onUploadFile()
      }
    },
    onUploadFile () {
      let vm = this
      if (this.upload) {
        if (vm.uploadConfig) {
          let itemFile = vm.uploadFiles.pop()
          let url = vm.uploadConfig.uploadUrl
          let uploadParams = vm.uploadConfig.params
          let uploadSuccess = vm.uploadConfig.uploadSuccess
          let param = new FormData()
          for (let key in uploadParams) {
            param.append(key, uploadParams[key])
          }
          param.append('fileName', itemFile.file.name)
          param.append('file', itemFile.file)
          axios.post(url, param, {
            headers: {
              'Content-Type': 'application/x-www-form-urlencoded',
              'Authorization': 'Bearer ' + window.localStorage.access_token,
            },
          }).then(function (result) {
            /* vm.fileReadList.forEach((itemFile, index) => {
                if (result.response && itemFile.file && !itemFile.attachment_id && result.response.fileName === itemFile.file.name) {
                  itemFile.attachment_id = result.response.attachment_id
                }
              }) */
            if (uploadSuccess) {
              uploadSuccess(itemFile, result)
            }
            if (vm.uploadFiles.length > 0) {
              vm.onUploadFile()
            } else {
              vm.$emit('upload', vm.fileReadList)
              vm.$emit('input', vm.fileReadList)
              vm.fileReadList = []
            }
          })
        }
      }
    },
    deleteFile (file, index) {
      const fileList = this.fileList.slice(0)
      fileList.splice(index, 1)

      this.$emit('input', fileList)
      this.$emit('delete', file, index)
    },

    showBigPic (index) {
      let vm = this
      if (vm.previewImage) {
        const imageFiles = vm.fileList
          .filter(item => isImageDataUrl(item.content))
        ShowPicturePlugin.show({
          imgList: imageFiles,
          startPosition: index,
        })
      }
    },
  },
}
</script>

<style lang="less">
  .h-file {
    display: flex;
    flex-wrap: wrap;

    .review-wrap {
      display: flex;
      flex-wrap: wrap;

      .review-img {
        position: relative;
        display: block;

        img {
          width: 65px;
          height: 65px;
          margin: 0 10px 10px 0;
          object-fit: cover
        }

        .icon {
          position: absolute;
          right: 10px;
          bottom: 12px;
          font-size: 16px;
          width: 16px;
          height: 16px;
          display: flex;
          color: #fff;
          background-color: rgba(0, 0, 0, 0.45);
          justify-content: center;
        }
      }

      .file-upload {
        position: relative;
        display: inline-block;
        //width: 75px;
        //height: 75px;

        .default-img {
          width: 65px;
          height: 65px;
          margin: 0 10px 10px 0;
          object-fit: cover
        }

        input {
          position: absolute;
          top: 0;
          left: 0;
          width: 100%;
          height: 100%;
          overflow: hidden;
          cursor: pointer;
          opacity: 0;
        }
      }
    }

  }
</style>
