<template>
<div class="glp-upload" :class="[disabledCls, inlineCls]">
<el-upload v-bind="props" ref="upload" v-if="type === 'card'">
  <i slot="default" class="el-icon-plus"></i>
  <template slot="file" slot-scope="{file}">
    <div class="glp-upload__content">
      <el-progress type="circle" :percentage="file.percentage" :width="80" v-if="file.status === 'uploading'"></el-progress>
      <el-progress type="circle" :percentage="file.percentage" :width="80" status="exception" v-if="file.status === 'fail'"></el-progress>
      <template v-if="file.status === 'success'">
        <img class="el-upload-list__item-thumbnail" :src="file.url" alt="" v-if="getContentType(file.name) === 'image'">
        <span v-else-if="getContentType(file.name) === 'word'"><i class="iconfont icon-word" style="font-size: 80px;"></i></span>
        <span v-else-if="getContentType(file.name) === 'excel'"><i class="iconfont icon-excelwenjian" style="font-size: 80px;"></i></span>
        <span v-else-if="getContentType(file.name) === 'ppt'"><i class="iconfont icon-ppt" style="font-size: 80px;"></i></span>
        <span v-else-if="getContentType(file.name) === 'pdf'"><i class="iconfont icon-pdf" style="font-size: 80px;"></i></span>
          <span style="font-size: 80px;" v-else><i class="el-icon-document"></i></span>
      </template>

      <div class="glp_upload__title">{{file.name}}</div>
    </div>
    <span class="el-upload-list__item-actions" :title="file.name">
      <span class="el-upload-list__item-preview" @click="onPreview(file)" v-if="['image', 'pdf', 'word', 'excel', 'ppt'].includes(getContentType(file.name)) && file.status === 'success'">
        <i class="el-icon-view"></i>
      </span>
      <span class="el-upload-list__item-delete" v-if="file.status === 'success'" @click="onDownload(file)">
        <i class="el-icon-download"></i>
      </span>
      <span class="el-upload-list__item-delete" v-if="!disabled && (file.status === 'success' || file.status === 'fail')" @click="onRemove(file)">
        <i class="el-icon-delete"></i>
      </span>
    </span>
  </template>
  <div slot="tip" class="el-upload__tip glp-text-warning" v-if="!disabled"><slot name="tip"></slot></div>
</el-upload>
<el-upload v-bind="props" ref="upload" v-else>
  <el-button size="small" type="primary" plain :disabled="disabled" v-if="!disabled">点击上传</el-button>
  <div slot="tip" class="el-upload__tip glp-text-warning" v-if="!disabled"><slot name="tip"></slot></div>
  <template slot="file" slot-scope="{file}">
    <a class="el-upload-list__item-name">
      <el-checkbox v-if="editControl" true-label="3" false-label="2" v-model="file.verifyStatus"></el-checkbox>
      <i class="el-icon-document"></i>
      <span v-if="file.ifNew !== 1" style="margin-right: 8px;" class="glp-text-primary">{{file.name}}</span>
      <span v-if="file.ifNew === 1"  style="margin-right: 8px;" class="el-error">{{file.name}}</span>
      <el-link :underline="false" @click="onPreview(file)" v-if="['image', 'pdf', 'word', 'excel', 'ppt'].includes(getContentType(file.name)) && file.status === 'success'" style="margin-left: 8px;" class="el-icon-view"></el-link>
      <el-link :underline="false" v-if="file.status === 'success'" @click="onDownload(file)" style="margin-left: 8px;" class="el-icon-download"></el-link>
      <el-link :underline="false" v-if="showDelete(file)" @click="onRemove(file)" style="margin-left: 8px;" class="el-icon-delete"></el-link>
      <span v-if="showTips(file)" class="el-error">此附件审批未通过，请修改后重新提交</span>
      <label class="el-upload-list__item-status-label">
        <i class="el-icon-upload-success el-icon-circle-check"></i>
      </label>
      <el-progress v-if="file.status === 'uploading'" type="line" :stroke-width="2"  :percentage="file.percentage"></el-progress>
    </a>
  </template>
</el-upload>
<!-- <el-dialog :visible.sync="visible">
  <img width="100%" :src="imageUrl" alt="">
</el-dialog> -->
  <div style="height: 0;overflow: hidden;"><el-image style="width: 0px; height: 0px" :preview-src-list="imageUrls" ref="image"></el-image></div>
</div>
</template>

<script lang="ts">

import { Vue, Component, Prop, Emit, Ref, Model } from 'vue-property-decorator'
import config from '../../config'
import { getFileType } from '../../utils/file'

export interface FileResp {
  name: string;
  url: string;
  verifyStatus?: boolean;
  ifNew?: number;
  uid?: number;
  status?: 'ready' | 'uploading' | 'success' | 'fail';
  [key: string]: any;
}

export interface RequestOptions {
    headers: Record<string, any>;
    withCredentials: boolean;
    file: File;
    data: any;
    filename: string;
    action: string;
    onProgress: (e: { percent: number }) => void;
    onSuccess: (res: any) => void;
    onError: (err: Error) => void;
}

export interface Request {
  (options: RequestOptions): Request;
}

@Component({
  components: { }
})
export default class GlpUpload extends Vue {
  @Prop(Boolean) disabled!: boolean

  @Prop({ type: String, default: '#' }) action!: string

  @Prop(Function) resp!: (response: any) => FileResp

  @Prop(Function) request!: Request

  @Prop(Function) onView!: any

  @Prop(Boolean) editControl!: any

  @Prop({ type: String, default: 'card' }) type!: 'card' | 'list'

  @Prop({ type: String, default: 'image/jpeg,image/jpg,image/png,.pdf,.xlsx,.docx' }) accept!: string

  @Prop(Number) limit!: number

  @Prop(String) maxSize!: string // 20K 1M

  @Prop(Function) beforeUpload!: (file: any, fileList: any[]) => boolean | Promise<any>

  @Prop(Boolean) inline!: boolean // 行内模式 只有list风格有行内模式

  @Prop(Boolean) multiple!: boolean

  @Model('input', { type: Array }) readonly value!: FileResp[]

  @Emit() input (value: FileResp[]) {}

  @Ref() upload!: any

  @Ref() image!: any

  imageUrl = ''

  // visible = false

  get imageUrls () {
    return this.imageUrl ? [this.imageUrl] : []
  }

  get disabledCls () {
    return this.disabled ? 'glp-upload--disabled' : ''
  }

  get inlineCls () {
    return this.inline ? 'glp-upload--inline' : ''
  }

  showTips (file: any) {
    if (file.isDetail) {
      return false
    }
    if (String(file.verifyStatus) === '3' && !this.editControl) {
      return true
    }
  }

  showDelete (file: any) {
    if (this.disabled) {
      return false
    }
    if (this.editControl) {
      return true
    }
    if ((file.status === 'success' || file.status === 'fail') && !file.id) {
      return true
    }

    if (file.verifyStatus === 2) {
      return false
    }

    if (file.verifyStatus === 1) {
      return true
    }

    if (file.verifyStatus === 3) {
      return true
    }
    return false
  }

  get props () {
    return {
      listType: this.type === 'card' ? 'picture-card' : undefined,
      onSuccess: this.successFn,
      fileList: this.value,
      action: this.action,
      disabled: this.disabled,
      httpRequest: this.request,
      accept: this.accept,
      limit: this.limit,
      onExceed: this.onExcced,
      beforeUpload: this.defaultBeforeUpload,
      multiple: this.multiple
    }
  }

  successFn (response: any, file: any, fileList: any[]) {
    const ret = fileList.filter((v: any) => ['success', 'uploading'].includes(v.status)).map((v: any) => {
      const url = v.response ? (this.resp ? this.resp(v.response) : v.response)?.url : v.url
      return {
        uid: v.uid,
        id: v.id,
        status: v.status,
        name: v.name,
        ifNew: v.ifNew,
        checked: false,
        verifyStatus: v.verifyStatus,
        url
      }
    })
    this.input(ret)
  }

  onRemove (file: any) {
    this.input(this.value.filter((v: any) => v.uid !== file.uid))
  }

  onPreview (file: any) {
    if (this.onView) {
      this.onView(file)
      return
    }
    if (this.getContentType(file.name) === 'pdf') config.previewPdf(file.url)
    else if (['word', 'excel', 'ppt'].includes(this.getContentType(file.name))) config.previewOffice(file.url)
    else if (this.getContentType(file.name) === 'image') {
      this.imageUrl = file.url
      // this.visible = true
      this.image.clickHandler()
      this.$nextTick(() => {
        this.image.clickHandler()
      })
    } else {
      this.$message.info('尚不支持预览该类型文件')
    }
  }

  onDownload (file: any) {
    const { url, name } = file
    config.download(name, url)
  }

  onExcced () {
    this.$message.warning(`最多只能上传 ${this.limit} 个文件`)
  }

  defaultBeforeUpload (file: any) {
    let ret!: Promise<any>
    if (this.beforeUpload) {
      const fileList = this.upload?.uploadFiles
      const result = this.beforeUpload(file, fileList)
      if (!(result instanceof Promise)) ret = result ? Promise.resolve(result) : Promise.reject(result)
      else {
        ret = result
      }
    } else ret = Promise.resolve()
    return ret.then(() => {
      if (!this.maxSize) return Promise.resolve()
      const max = this.maxSize.replace(/[MK]/g, (_, c) => _ === 'K' ? '*1024' : '*1048576').split('*').reduce((t, n: any) => t * n, 1)
      if (file.size > max) {
        this.$message.warning(`文件大小不能超过${this.maxSize}`)
        return Promise.reject(new Error(''))
      }
      return Promise.resolve()
    })
  }

  getContentType (name: string): 'image' | 'pdf' | 'word' | 'excel' | 'ppt' | 'other' {
    return getFileType(name)
  }
}
</script>

<style lang="scss">
@import "./style/index.scss";

</style>
