<template>
  <div class="ibps-cell-wrapper">
    <van-field
      ref="input"
      v-model="inputValue"
      :label="label"
      :name="name"
      :size="size"
      :border="false"
      :disabled="disabled"
      :required="required"
      :clearable="clearable"
      :clickable="clickable"
      :is-link="isLink"
      :error="error"
      :error-message="errorMessage"

      :arrow-direction="arrowDirection"
      :label-class="labelClass"
      :label-width="labelWidth"
      :label-align="labelAlign"
      :input-align="inputAlign"
      :error-message-align="errorMessageAlign"
      :autosize="autosize"
      :left-icon="leftIcon"
      :right-icon="rightIcon"
      :icon-prefix="iconPrefix"
      :rules="editable?rules:null"
      class="ibps-uploader"
      readonly
      @click-input="onClick"
    >
      <template #label>
        {{ label }}<van-icon v-if="desc && descPosition==='lableIcon'" name="warning" class="ibps-dialog-icon" @click="$action.descDialog({ title:label, message:desc })" />
      </template>
      <template #input>
        <!-- <van-icon
          v-if="editable"
          slot="left-icon"
          name="add-o"
          class="van-cell__left-icon"
        /> -->
        <div class="van-field__body">
          <input
            v-if="!$utils.isNotEmpty(selectorValue)"
            :value="editable?'':(showClear?' ':'')"
            type="text"
            readonly="readonly"
            :name="name"
            :placeholder="editable?placeholder:''"
            class="van-field__control"
          >
        </div>
        <div class="van-field__body" />
      </template>
      <template #right-icon>
        <van-icon name="arrow" class="ibps-gray-b2" @click="onClick" />
      </template>
    </van-field>
    <van-cell-group v-if="$utils.isNotEmpty(selectorValue)">
      <ibps-file
        v-for="(item,index) in selectorValue"
        :key="index"
        :file="item"
        :file-ext-key="fileExtKey"
        :file-size-key="fileSizeKey"
        :label-key="labelKey"
        :style="havePadding ? 'padding-left:40px;':''"
        @click="previewFile(item)"
      >
        <template #right-icon>
          <div class="ibps-enclosure_icon">
            <van-icon
              v-if="download"
              name="back-top"
              class="ibps-rotate"
              @click.stop="downloadFile(item)"
            />
            <span v-if="showClear" class="ibps-wingblank" />
            <van-icon
              v-if="showClear"
              name="delete"
              @click.stop="removeFile(index)"
            />
          </div>
        </template>
      </ibps-file>
    </van-cell-group>

    <ibps-field-desc :desc="desc" :desc-position="descPosition" />

    <van-uploader
      v-if="uploadType === 'default'"
      ref="fileUploader"
      :after-read="onAfterRead"
      :before-read="onBeforeRead"
      :accept="accept"
      :max-size="maxSize"
      :multiple="multiple"
      style="width：0;height:0;"
      class="ibps-uploader__default"
    />
    <!--选择附件-->
    <van-popup
      v-model="showPopup"
      class="ibps-fullscreen-popup"
      position="bottom"
      get-container="body"
    >
      <ibps-picker-toolbar
        :title="title"
        @cancel="onCancel"
        @title="onTitle"
        @confirm="onConfirm"
      />
      <div class="ibps-fixed-navbar">
        <van-tabs v-model="activeTab" @click="onTabClick">
          <van-tab :title="$t('components.uploader.uploadingTitle')">
            <div class="ibps-p-15">
              <van-uploader
                :after-read="onAfterRead"
                :before-read="onBeforeRead"
                :accept="accept"
                :max-size="maxSize"
                :multiple="multiple"
              >
                <van-button plain block type="info" icon="add-o">请上传文件</van-button>
              </van-uploader>
            </div>
            <!--正在上传--->
            <van-checkbox-group ref="uploadingCheckboxGroup" v-model="checkbox" :max="multiple?0:1">
              <van-cell-group>
                <van-cell
                  v-for="(item,index) in uploadingFiles"
                  :key="item[valueKey]+index"
                  clickable
                  @click="toggleUploading(index)"
                >
                  <van-checkbox
                    slot="icon"
                    ref="uploadingCheckboxes"
                    :name="item[valueKey]"
                    style="overflow: unset;"
                  />
                  <template #title>
                    <ibps-file
                      :file="item"
                      :file-ext-key="fileExtKey"
                      :file-size-key="fileSizeKey"
                      :label-key="labelKey"
                    />
                  </template>
                </van-cell>
              </van-cell-group>
            </van-checkbox-group>
          </van-tab>
          <van-tab :title="$t('components.uploader.uploadedTitle')">
            <van-sticky :offset-top="45">
              <van-pagination
                v-show="pagination.totalCount >0"
                v-model="pagination.page"
                :total-items="pagination.totalCount"
                :items-per-page="pagination.limit"
                :page-count="pagination.totalPages"
                force-ellipses
                @change="loadUploadedFiles()"
              />
            </van-sticky>

            <!--已上传--->
            <van-checkbox-group
              ref="uploadedCheckboxGroup"
              v-model="checkbox"
              :max="multiple?0:1"
              @change="changeUploaded"
            >
              <van-cell
                v-for="(item,index) in uploadedFiles"
                :key="item[valueKey]+index"
                clickable
                @click="toggleUploaded(index,item)"
              >
                <template #icon>
                  <van-checkbox
                    ref="uploadedCheckboxes"
                    :name="item[valueKey]"
                  />
                </template>
                <template #title>
                  <ibps-file
                    :file="item"
                    :file-ext-key="fileExtKey"
                    :file-size-key="fileSizeKey"
                    :label-key="labelKey"
                  />
                </template>
              </van-cell>
            </van-checkbox-group>
          </van-tab>
        </van-tabs>
      </div>
    </van-popup>

    <!--点击明细-查看选中的 -->
    <van-popup
      v-if="multiple"
      v-model="showDetailPopup"
      class="ibps-fullscreen-popup"
      get-container="body"
      position="right"
    >
      <ibps-picker-toolbar
        title="已选择的选项"
        @cancel="onDetailCancel"
        @confirm="onDetailConfirm"
      />

      <van-cell-group>
        <van-swipe-cell
          v-for="(data,index) in selectedData"
          :key="data[valueKey]+index"
          :right-width="65"
          class="ibps-swipe-cell"
        >
          <van-cell
            clickable
          >
            <template #title>
              <ibps-file
                :file="data"
                :file-ext-key="fileExtKey"
                :file-size-key="fileSizeKey"
                :label-key="labelKey"
              />
            </template>
            <template #right-icon>
              <van-icon
                name="clear"
                class="van-field__clear"
                @click.stop="removeSelected(index)"
              />
            </template>
          </van-cell>
          <van-button
            slot="right"
            type="danger"
            :text="$t('delete')"
            class="ibps-swipe-button"
            @click="removeSelected(index)"
          />
        </van-swipe-cell>
      </van-cell-group>
    </van-popup>
    <!--预览 -->
    <ibps-file-preview
      v-model="showPreviewPopup"
      :file="previewFileList"
    />
  </div>
</template>
<script>
/**
 * 需要完善的功能
 * 数据存储格式 string 还是数组，现在默认的是数组
 *
 */
import { get, transfer, uploadFile, queryPageList } from '@/api/platform/file/attachment'
import { findByCategoryKey } from '@/api/platform/cat/type'
import { downloadFile } from '@/business/platform/file/utils'

import { isDef } from 'vant/lib/utils'
import FieldMixin from '@/mixins/field'
import ActionUtils from '@/utils/action'
import i18n from '@/utils/i18n'
import { remoteRequest, remoteTransRequest } from '@/utils/remote'
import { TRANSFER_DATA } from '@/constant'
import IbpsFile from './file'
import IbpsFilePreview from '@/components/ibps-file-preview'
import IbpsPickerToolbar from '@/components/ibps-picker-toolbar'

export default {
  name: 'ibps-uploader',
  components: {
    IbpsPickerToolbar,
    IbpsFile,
    IbpsFilePreview
  },
  mixins: [FieldMixin],
  props: {
    havePadding: { // 附件是否显示间距
      type: Boolean,
      default: true
    },
    valueKey: {
      type: String,
      default: 'id'
    },
    labelKey: {
      type: String,
      default: 'fileName'
    },
    fileExtKey: {
      type: String,
      default: 'ext'
    },
    fileSizeKey: {
      type: String,
      default: 'totalBytes'
    },
    pathKey: {
      type: String,
      default: 'filePath'
    },
    leftText: {
      type: String,
      default: i18n.t('cancel')
    },
    rightText: {
      type: String,
      default: i18n.t('confirm')
    },
    accept: {
      type: String,
      default: '*'
    },
    multiple: {
      type: Boolean,
      default: true
    },
    store: { // 返回值类型  array: 数组。string 字符串类型
      type: String,
      default: 'id',
      validator: function(value) {
        // value:只存value,all:存value和label
        // return ['all', 'value'].indexOf(value) !== -1
        // json ->是存储json字符串 [ {id:xxxx,fileName:xxxx}]
        // id -> xxxxxxxxx,xxx
        // path -> file\xxx\xxxxx
        return ['json', 'id', 'path'].indexOf(value) !== -1
      }
    },
    storeSeparator: { // 返回值分割符，对于设置字符串类型的分隔符
      type: String,
      default: ','
    },
    maxSize: { // 文件大小限制，单位为 byte
      type: Number
    },
    limit: { // 文件上传个数
      type: Number
    },
    fileFormates: { // 文件后缀
      type: Array
    },
    uploadType: { // 文件上传方式，直接上传，附件上传
      type: String,
      default: 'attachment'
    },
    download: { // 允许下载
      type: Boolean,
      default: false
    },
    preview: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      showPopup: false,
      activeTab: 0,
      curFileType: '',
      fileTypeList: [],
      cacheData: {},

      checkbox: [], // 选中的附件id
      uploadingFiles: [], // 正在上传的附件列表
      uploadedFiles: [], // 已上传的附件列表

      pagination: {
        limit: 20,
        page: 1,
        totalCount: 0,
        totalPages: 0
      },
      showPreviewPopup: false,
      previewFileList: {},

      selectorValue: [], // 选中的附件
      showDetailPopup: false
    }
  },

  computed: {
    showClear() {
      return this.clearable && this.$utils.isNotEmpty(this.value) && isDef(this.value) && this.editable
    },
    title() {
      if (this.multiple) {
        const length = this.checkbox.length
        return length > 0 ? i18n.t('components.checkbox.title', { length: length }) : ''
      } else {
        if (this.$utils.isEmpty(this.checkbox)) {
          return ''
        }
        const checked = this.checkbox[0]
        return this.$utils.isNotEmpty(checked) ? this.cacheData[checked] ? this.cacheData[checked][this.labelKey] : '' : ''
      }
    },
    selectedData() {
      return this.checkbox.map((d) => {
        return this.cacheData[d] || {}
      })
    }
  },
  watch: {
    value: {
      handler() {
        this.checkbox = []
        this.initData()
        this._setInputValue()
      },
      deep: true,
      immediate: true
    }
  },
  methods: {
    _setInputValue() {
      this.inputValue = this.$utils.isNotEmpty(this.value) ? JSON.stringify(this.value) : ''
      setTimeout(() => {
        this.validate()
      }, 10)
    },

    /**
     * 初始化数据
     */
    initData() {
      const data = this.getArrayValue(this.value)
      this.selectorValue = []
      if (this.$utils.isEmpty(data)) {
        return
      }
      data.forEach(v => {
        if (this.cacheData[v]) {
          this.setSelectorValue(v)
        } else {
          this.getDataInfo(v)
        }
      })
    },
    setCacheFiles(files) {
      if (this.$utils.isEmpty(files)) { return }
      files.forEach((v) => {
        this.cacheData[v[this.valueKey]] = v
      })
    },
    setSelectorValue(v) {
      this.checkbox.push(v)
      this.selectorValue.push(this.cacheData[v])
    },
    /**
     * 获得数组数据
     */
    getArrayValue(value, bindId) {
      if (this.$utils.isEmpty(value)) {
        return []
      }
      if (this.store === 'json') { // json
        return this.parseJsonData(value)
      } else if (this.store === 'id') { // id
        // 可能是json数据[之前存储的josn格式]
        if (this.$utils.isJSON(value)) {
          return this.parseJsonData(value)
        } else {
          return this.$utils.isString(value) ? value.split(this.storeSeparator) : []
        }
      } else if (this.store === 'bind') { // 绑定id
        if (this.$utils.isEmpty(bindId)) {
          return []
        }
        return bindId.split(this.storeSeparator)
      } else { // array
        return value.map((d) => {
          return d[this.valueKey]
        })
      }
    },
    parseJsonData(value) {
      try {
        const data = this.$utils.parseData(value)
        const result = []
        if (Array.isArray(data)) {
          data.forEach(d => {
            const node = d[this.valueKey]
            if (node) result.push(node)
          })
        } else {
          if (this.$utils.isPlainObject(data)) {
            result.push(data[this.valueKey])
          } else {
            const realData = this.$utils.isString(value) ? value.split(this.storeSeparator) : []
            realData.forEach(v => {
              result.push(v)
            })
          }
        }
        return result
      } catch (error) {
        console.warn(error)
        return []
      }
    },
    getStoreValue(value) {
      const res = []
      if (this.store === 'json') { // json
        if (this.$utils.isEmpty(value)) {
          return ''
        }
        if (this.multiple) {
          value.forEach(v => {
            const o = {}
            o[this.valueKey] = v[this.valueKey]
            o[this.labelKey] = v[this.labelKey]
            res.push(o)
          })
          return JSON.stringify(res)
        } else {
          const o = {}
          o[this.valueKey] = value[this.valueKey]
          o[this.labelKey] = value[this.labelKey]
          return JSON.stringify(o)
        }
      } else if (this.store === 'id') { // id
        if (this.$utils.isEmpty(value)) {
          return ''
        }
        if (this.multiple) {
          value.forEach(v => {
            res.push(v[this.valueKey])
          })
        } else {
          res.push(value[this.valueKey])
        }
        return res.join(this.storeSeparator)
      } else if (this.store === 'bind') { // 绑定id
        const res = []
        const bindIdValue = []
        value.forEach(v => {
          bindIdValue.push(v[this.valueKey])
          res.push(v[this.labelKey])
        })
        this.bindIdValue = bindIdValue.join(this.storeSeparator)

        return res.join(this.storeSeparator)
      } else { // 数组 array
        return value || []
      }
    },
    /**
    * 通过ID获取数据
     */
    getDataInfo(id) {
      if (TRANSFER_DATA === 'transfer') {
        this.getTransferData(id)
      } else {
        this.getRemoteData(id)
      }
    },
    getTransferData(id) {
      remoteTransRequest('attachment', id).then(idset => {
        const ids = Array.from(idset)
        remoteRequest('attachmentIds', ids, () => {
          return this.getRemoteTransFunc(ids)
        }).then(response => {
          const responseData = response.data
          const data = responseData[id]
          this.setRemoteData(data)
        }).catch(() => {
        })
      })
    },
    getRemoteTransFunc(ids) {
      return new Promise((resolve, reject) => {
        transfer({
          'ids': ids
        }).then(response => {
          resolve(response)
        }).catch((error) => {
          reject(error)
        })
      })
    },

    getRemoteData(id) {
      remoteRequest('attachment' + this.valueKey, id, () => {
        return this.getRemoteByIdFunc(id)
      }).then(response => {
        const data = response.data
        this.setRemoteData(data)
      }).catch(() => {
      })
    },
    getRemoteByIdFunc(id) {
      return new Promise((resolve, reject) => {
        get({
          attachmentId: id
        }).then(response => {
          resolve(response)
        }).catch(() => {
        })
      })
    },
    setRemoteData(data) {
      if (this.$utils.isNotEmpty(data)) {
        this.cacheData[data[this.valueKey]] = data
        this.setSelectorValue(data[this.valueKey])
      }
    },
    // ==============点击=====
    onClick() {
      if (this.readonly) { return }
      if (this.uploadType === 'attachment') {
        this.showPopup = true
        // 还原原来的数据
        this.activeTab = 0
        this.uploadingFiles = [] // 正在上传的文件
        this.uploadedFiles = []// 已上传的文件
      } else {
        this.$refs.fileUploader.chooseFile()
      }
    },
    onTitle() {
      if (!this.multiple) { return }
      this.showDetailPopup = true
    },
    onDetailCancel() {
      this.showDetailPopup = false
    },
    onDetailConfirm() {
      this.showDetailPopup = false
    },
    toggleChild(data, index) {
      this.$emit('toggle-child', data)
    },
    changePath(index) {
      this.$emit('change-path', index)
    },
    // 删除选中
    removeSelected(index) {
      this.checkbox.splice(index, 1)
    },
    onCancel() {
      this.checkbox = []
      this.showPopup = false
    },
    onConfirm() {
      if (this.$utils.isEmpty(this.checkbox)) {
        this.$notify({
          type: 'warning',
          message: '请上传文件或选择已上传的文件！'
        })
        return
      }
      this.showPopup = false
      this.emitInput()
    },
    emitInput() {
      this.$emit('input', this.getStoreValue(this.getCheckValue()))
    },
    getCheckValue() {
      const selectorValue = []
      this.checkbox.forEach(v => {
        selectorValue.push(this.cacheData[v])
      })
      return this.multiple ? selectorValue : selectorValue[0]
    },
    onBeforeRead(file) {
      const flag = this.checkFileFormat({
        fileName: this.getFileName(file.name),
        fileExt: this.getExtName(file.name),
        fileSize: file.size
      })
      if (!flag) {
        return false
      }

      this.$emit('before-read', file)
      return true
    },

    onAfterRead(file) {
      if (file.length > 0) {
        for (let i = 0; i < file.length; i++) {
          this.addFile(file[i])
        }
      } else {
        this.addFile(file)
      }
      this.$emit('afte-read', file)
    },
    addFile(file) {
      // 上传文件用file
      const fileData = file.file
      const fileName = fileData.name
      const fileSize = fileData.size
      // 上传文件
      uploadFile(fileData).then(response => {
        const data = response.data
        const fileId = data.id
        const res = {
          [this.valueKey]: fileId,
          [this.labelKey]: this.getFileName(fileName),
          [this.fileExtKey]: this.getExtName(fileName),
          [this.fileSizeKey]: fileSize,
          [this.pathKey]: data[this.pathKey]
        }
        this.uploadingFiles.push(res)
        if (this.multiple) {
          this.checkbox.push(fileId)
        } else {
          this.checkbox.splice(0, 1, fileId)
        }
        this.checkUploadedQuantity()
        // 缓存的文件
        this.cacheData[data[this.valueKey]] = data
        if (this.uploadType !== 'attachment') {
          this.emitInput()
        }
      }).catch((e) => {
        console.error(e)
      })
    },
    toggleUploading(index) {
      if (!this.multiple) {
        this.$refs.uploadingCheckboxGroup.toggleAll(false)
      }
      this.$refs.uploadingCheckboxes[index].toggle()
    },
    checkFileFormat({ fileName, fileSize, fileExt }) {
      // 文件数量
      if (this.limit > 0 && this.checkbox.length === this.limit) {
        this.$notify({
          type: 'warning',
          message: '文件上传数量的超出限制！'
        })
        return false
      }
      // 上传大小
      if (this.$utils.isNotEmpty(this.maxSize) &&
         fileSize > this.maxSize) {
        this.$notify({
          type: 'warning',
          message: `[${fileName}]文件大小的超出上传限制！`
        })
        return false
      }

      // 上传格式
      if (this.$utils.isNotEmpty(this.fileFormates) &&
          (!fileExt || !this.fileFormates.includes('.' + fileExt))) {
        const fileType = this.fileFormates.join(',')
        this.$notify({
          type: 'warning',
          message: `[${fileName}]文件格式不允许！请选择[${fileType}]格式`
        })
        return false
      }

      return true
    },

    // /-===================已上传===============
    toggleUploaded(index, file) {
      const flag = this.checkFileFormat({
        fileName: file.fileName,
        fileSize: file[ this.fileSizeKey],
        fileExt: file[ this.fileExtKey]
      })
      if (!flag) {
        this.$refs.uploadedCheckboxes[index].toggle(false)
        return false
      }
      if (!this.multiple) {
        this.$refs.uploadedCheckboxGroup.toggleAll(false)
      }
      this.$refs.uploadedCheckboxes[index].toggle()
    },
    changeUploaded(file) {
      if (this.$utils.isEmpty(this.limit) || this.limit < 0) {
        return
      }
      // 只能指定个数  删除第一个
      if (file.length > this.limit) {
        this.checkbox.splice(0, 1)
      }
    },
    checkUploadedQuantity() {
      if (this.$utils.isEmpty(this.limit) || this.limit < 0) {
        return
      }
      if (this.checkbox.length > this.limit) {
        this.checkbox.splice(0, this.checkbox.length - this.limit)
      }
    },
    removeFile(index) {
      if (this.multiple) {
        this.selectorValue.splice(index, 1)
      } else {
        this.selectorValue = {}
      }
      this.$emit('input', this.getStoreValue(this.selectorValue))
    },
    onTabClick(index) {
      // 加载已上传的附件
      if (this.activeTab === 1) {
        // 没有加载文件类型
        // this.loadFileType()
        this.loadUploadedFiles()
      }
    },
    loadFileType() {
      findByCategoryKey({
        categoryKey: 'FILE_TYPE'
      }).then(response => {
        this.fileTypeList = response.data
      }).catch((e) => {
        console.error(e)
      })
    },
    loadUploadedFiles() {
      const params = ActionUtils.formatParams({ 'Q^TYPE_ID_^SL': this.fileType || '' }, this.pagination)
      queryPageList(params).then(response => {
        const data = response.data
        this.uploadedFiles = data.dataResult
        this.setCacheFiles(this.uploadedFiles) // 缓存文件
        this.pagination = data.pageResult
      }).catch((e) => {
        console.error(e)
      })
    },

    // 获取扩展名
    getExtName(name) {
      return name ? name.substring(name.lastIndexOf('.') + 1, name.length) : ''
    },
    // 获取文件名
    getFileName(name) {
      return name ? name.substring(0, name.lastIndexOf('.')) : ''
    },
    /**
     * 下载文件
     */
    downloadFile(item) {
      downloadFile(item)
    },
    /**
     * 预览文件
     */
    previewFile(item) {
      const FILE_TYPE = ['pdf', 'jpg', 'jpeg', 'bmp', 'png', 'gif', 'mp3', 'mp4', 'doc', 'docx', 'ppt', 'pptx', 'xls', 'xlsx']

      // 支持预览类型
      if (FILE_TYPE.includes(item.ext)) {
        this.previewFileList = item
        this.showPreviewPopup = true
      }
    }
  }
}
</script>
<style lang="scss">
  .ibps-uploader__default{
    width:0;
    height: 0;
    display: block;
    .van-uploader__upload{
      width:0;
      height: 0;
      margin: 0;
    }
    .van-uploader__upload-icon{
      display: none;
    }
  }
  .ibps-enclosure_icon{
    height: 100%;
    display: flex;
    justify-content: flex-end;
    align-items: center;
    color: #999999;
    font-size: 16px;
  }
</style>
