<template>
  <div style="width: 350px">
    <div v-if="selectedFileType === 'IMAGE'" class="total-images">
      <div
        v-for="(item, index) in uploadFileList"
        :key="index"
        class="demo-upload-list"
      >
        <img
          :ref="'image' + index"
          class="image-small"
          :data-src="blobToSrc(item, index)"
        />
        <div class="demo-upload-list-cover">
          <Icon
            type="ios-eye-outline"
            size="30"
            @click.native="handleView('.total-images', index)"
          ></Icon>
          <Icon
            type="ios-trash-outline"
            size="30"
            style="position: absolute; top: 0px"
            @click.native="handleRemoveTotal(index)"
          ></Icon>
        </div>
      </div>
    </div>
    <Upload
      ref="uploadComp"
      action
      :headers="headers"
      :data="{ fileType: fileType }"
      :before-upload="handleBeforeUpload"
      :format="uploadFileFormat"
      :accept="uploadFileAccept"
      :on-format-error="handleFormatError"
      :on-success="handleSuccess"
      :on-error="handleError"
    >
      <div v-if="selectedFileType !== 'IMAGE'">
        <i-button
          icon="ios-cloud-upload-outline"
          class="qm-primary-button"
          style=""
          @click="clickUpload"
        >
          选择文件
        </i-button>
        <span v-if="uploadFileList.length > 0">{{
          uploadFileList[0].name
        }}</span>
      </div>
      <div v-else>
        <div
          v-if="uploadFileList.length < 6"
          class="demo-upload-list plus"
          @click="clickUpload"
        >
          +
        </div>
      </div>
    </Upload>

    <div>
      <i-button
        icon="ios-cloud-upload-outline"
        class="qm-primary-button"
        style="width: 40%; margin-right: 20px"
        :disabled="uploadFileList.length === 0"
        :loading="uploading"
        @click="uploadFiles"
      >
        确认上传
      </i-button>
      <i-button
        class="qm-primary-button"
        style="width: 40%"
        @click="$emit('close-modal')"
      >
        取消上传
      </i-button>
    </div>
  </div>
</template>

<script>
import MD5 from "js-md5";
import "viewerjs/dist/viewer.css";
import Viewer from "viewerjs";

export default {
  name: "EcsOfflineUpload",
  props: {
    course: {
      type: Object,
      default() {
        return {};
      },
    },
    selectedFileType: {
      type: String,
      default: "",
    },
    uploadFileFormat: {
      type: Array,
      default: () => [],
    },
    uploadFileAccept: {
      type: String,
      default: "",
    },
  },
  data() {
    return {
      headers: {
        token: window.sessionStorage.getItem("token"),
        key: window.localStorage.getItem("key"),
      },
      file: null,
      fileType: null,
      loadingStatus: false,
      uploadFileList: [],
      uploading: false,
      // uploadFileFormat: [],
      // uploadFileAccept: "",
    };
  },
  watch: {
    selectedFileType() {
      this.uploadFileList = [];
    },
  },
  async created() {
    // const res = await this.$http.get(
    //   "/api/ecs_exam_work/exam/getExamPropertyFromCacheByStudentSession/" +
    //     this.course.examId +
    //     `/OFFLINE_UPLOAD_FILE_TYPE`
    // );
    // this.uploadFileFormat =
    //   (res.data.OFFLINE_UPLOAD_FILE_TYPE &&
    //     JSON.parse(res.data.OFFLINE_UPLOAD_FILE_TYPE)) ||
    //   [];
    // this.uploadFileFormat = this.uploadFileFormat.map((v) => v.toLowerCase());
    // this.uploadFileAccept = this.uploadFileFormat
    //   .map((v) => "application/" + v)
    //   .join();
    // if (this.uploadFileAccept.includes("zip")) {
    //   this.uploadFileAccept = ".zip," + this.uploadFileAccept;
    // }
  },
  methods: {
    clickUpload(e) {
      // console.log(e);
      e.preventDefault();
      if (!this.selectedFileType) {
        this.$Notice.warning({
          title: "请先选择上传文件类型",
          // desc: file.name + " 文件是pdf文档，但文件名后缀不是.pdf！"
        });
        e.stopPropagation();
        return false;
      }
      if (this.selectedFileType !== "IMAGE") this.uploadFileList = [];
    },
    fileFormatCheck(file, resolve, reject) {
      function getMimetype(signature) {
        switch (signature) {
          case "89504E47":
            return "image/png";
          case "47494638":
            return "image/gif";
          case "25504446":
            return "application/pdf";
          case "FFD8FFE0":
          case "FFD8FFE1":
          case "FFD8FFE2":
          case "FFD8FFE3":
            return "image/jpeg";
          case "504B0304":
            return "application/zip";
          case "504B34":
            return "application/zip";
          default:
            return "Unknown filetype";
        }
      }

      const filereader = new FileReader();
      let uploads = [];
      filereader.onloadend = (evt) => {
        if (evt.target.readyState === FileReader.DONE) {
          const uint = new Uint8Array(evt.target.result);
          let bytes = [];
          uint.forEach((byte) => {
            bytes.push(byte.toString(16));
          });
          const hex = bytes.join("").toUpperCase();
          uploads.push({
            filename: file.name,
            filetype: file.type ? file.type : "Unknown/Extension missing",
            binaryFileType: getMimetype(hex),
            hex: hex,
          });

          if (!getMimetype(hex).toUpperCase().includes(this.selectedFileType)) {
            this.$Notice.warning({
              title: "文件内容与所选文件类型不一致",
            });
            resolve("和所选文件类型不一致");
          }

          if (["application/pdf"].includes(getMimetype(hex))) {
            if (!file.name.endsWith(".pdf")) {
              this.loadingStatus = false;
              this.$Notice.warning({
                title: "文件内容与文件的后缀不一致",
                // desc: file.name + " 文件是pdf文档，但文件名后缀不是.pdf！"
              });
              this.file = null;
              reject("文件内容与文件的后缀不一致，请确认文件是pdf文档！");
            } else {
              resolve(true);
            }
          } else if (["application/zip"].includes(getMimetype(hex))) {
            if (!file.name.endsWith(".zip")) {
              this.loadingStatus = false;
              // this.$refs.uploadComp.fileList.splice(0);
              // this.$refs.uploadComp.fileList = [];
              this.$Notice.warning({
                title: "文件内容与文件的后缀不一致",
                // desc: file.name + " 文件是zip压缩包，但文件名后缀不是.zip！"
              });
              this.file = null;
              reject("文件内容与文件的后缀不一致，请确认文件是zip压缩包！");
            } else {
              resolve(true);
            }
          } else if (["image/jpeg"].includes(getMimetype(hex))) {
            if (file.name.endsWith(".jpeg") || file.name.endsWith(".jpg")) {
              resolve(true);
            } else {
              this.loadingStatus = false;
              // this.$refs.uploadComp.fileList.splice(0);
              // this.$refs.uploadComp.fileList = [];
              this.$Notice.warning({
                title: "文件内容与文件的后缀不一致",
                // desc: file.name + " 文件是zip压缩包，但文件名后缀不是.zip！"
              });
              this.file = null;
              reject("文件内容与文件的后缀不一致，请确认文件是jpeg文件！");
            }
          } else if (["image/png"].includes(getMimetype(hex))) {
            if (!file.name.endsWith(".png")) {
              this.loadingStatus = false;
              // this.$refs.uploadComp.fileList.splice(0);
              // this.$refs.uploadComp.fileList = [];
              this.$Notice.warning({
                title: "文件内容与文件的后缀不一致",
                // desc: file.name + " 文件是zip压缩包，但文件名后缀不是.zip！"
              });
              this.file = null;
              reject("文件内容与文件的后缀不一致，请确认文件是png文件！");
            } else {
              resolve(true);
            }
          } else {
            console.log("binary file type check: not zip or pdf");
            window._hmt.push([
              "_trackEvent",
              "离线考试页面",
              "上传作答",
              "文件格式非zip或pdf",
            ]);
            this.$Notice.warning({
              title: "作答文件损坏",
              desc:
                file.name +
                " 文件无法以 " +
                this.uploadFileFormat.join(" 或 ") +
                " 格式读取。",
            });
            this.file = null;
            this.loadingStatus = false;
            reject("作答文件损坏");
          }
        }
      };
      const blob = file.slice(0, 4);
      filereader.readAsArrayBuffer(blob);
    },
    fileSizeCheck(file, resolve, reject) {
      const maxSize = this.selectedFileType === "IMAGE" ? 5 : 30;
      if (file.size > maxSize * 1024 * 1024) {
        this.$Notice.warning({
          title: "超出文件大小限制",
          desc: file.name + ` 太大，作答文件不能超过${maxSize}MB.`,
        });
        reject("附件大小超出限制");
      } else {
        resolve(true);
      }
    },
    handleSuccess() {
      //   window._hmt.push(["_trackEvent", "离线考试页面", "上传作答", "上传成功"]);
      //   this.file = null;
      //   this.loadingStatus = false;
      //   this.$Message.success({
      //     content: "上传成功",
      //     duration: 5,
      //     closable: true,
      //   });
      //   this.uploadFileList = [];
      //   this.$emit("close-modal");
      //   this.$emit("reload-list");
    },
    handleError(error, file) {
      window._hmt.push(["_trackEvent", "离线考试页面", "上传作答", "上传失败"]);
      this.file = null;
      this.loadingStatus = false;
      console.log(error);
      this.$Message.error({
        content: (file && file.desc) || "上传失败",
        duration: 15,
        closable: true,
      });
    },
    handleFormatError(file) {
      this.file = null;
      this.loadingStatus = false;
      this.$Notice.warning({
        title: "作答文件格式不对",
        desc:
          file.name +
          " 文件格式不对，请选择 " +
          this.uploadFileFormat.join(" 或 ") +
          "  文件。",
      });
    },
    handleMaxSize(file) {
      this.file = null;
      this.loadingStatus = false;
      this.$Notice.warning({
        title: "超出文件大小限制",
        desc: file.name + " 太大，作答文件不能超过30M.",
      });
    },
    async handleBeforeUpload(file) {
      const suffix = file.name.split(".").pop();
      if (suffix.toLowerCase() !== suffix) {
        this.$Notice.error({
          title: "文件名后缀必须是小写",
          desc: file.name + " 文件名后缀必须是小写。",
        });
        return Promise.reject("file suffix should be lower case");
      }

      // this.uploadFileList.push(file);
      // const oldLength = this.uploadFileList.length;

      // await new Promise((resolve) => setTimeout(() => resolve(), 1000));

      // const newLength = this.uploadFileList.length;

      // if (oldLength !== newLength) {
      //   console.log("还有新的文件要上传，取消本次上传");
      //   throw "取消";
      // }
      // console.log(this.uploadFileList);

      if (this.uploadFileList.length > 1) {
        if (
          this.uploadFileList.map((v) => v.type).includes("application/pdf")
        ) {
          console.log("PDF文件只允许单独上传");
          throw "取消";
        }
        if (
          this.uploadFileList.map((v) => v.type).includes("application/zip")
        ) {
          console.log("ZIP文件只允许单独上传");
          throw "取消";
        }
      }

      console.log("上传");
      // return;

      // if (file.type.includes("/pdf")) {
      //   this.fileType = "pdf";
      // } else if (file.type.includes("/zip")) {
      //   this.fileType = "zip";
      // }
      this.file = file;
      this.loadingStatus = true;
      const format = await new Promise((resolve, reject) =>
        this.fileFormatCheck(file, resolve, reject)
      );

      if (format !== true) {
        console.log({ format });
        throw "文件类型检测不通过";
      }

      const fileSizeCheckResult = await new Promise((resolve, reject) =>
        this.fileSizeCheck(file, resolve, reject)
      );

      if (fileSizeCheckResult !== true) {
        console.log({ fileSizeCheckResult });
        throw "文件大小检测不通过";
      }

      this.uploadFileList.push(file);

      throw "stop uploading by <Upload>";
    },
    async uploadFiles() {
      if (this.uploadFileList.length === 0) {
        return;
      }
      if (this.course.offlineFiles) {
        const res = await new Promise((resolve, reject) => {
          this.$Modal.confirm({
            title: "已有作答附件，是否覆盖？",
            onCancel: () => reject(-1),
            onOk: () => resolve(),
          });
        });
        if (res === -1) {
          return false;
        }
      }
      this.uploading = true;

      let params = new FormData();
      params.append("examRecordDataId", this.course.examRecordDataId);
      params.append("fileType", this.selectedFileType);

      async function blobToArray(blob) {
        return new Promise((resolve) => {
          var reader = new FileReader();
          reader.addEventListener("loadend", function () {
            // reader.result contains the contents of blob as a typed array
            resolve(reader.result);
          });
          reader.readAsArrayBuffer(blob);
        });
      }

      for (const file of this.uploadFileList) {
        const ab = await blobToArray(file);
        params.append("fileArray", file);
        params.append("fileMd5Array", MD5(ab));
      }
      // for (let f of this.fileList) {
      //   params.append("fileArray", f.raw);
      // }

      // //先对文件md5进行排序(按索引正序排列)
      // this.summaryList.sort((a, b) => a.index - b.index);
      // let summaries = [];
      // for (let s of this.summaryList) {
      //   summaries.push(s.summary);
      // }
      // params.append("fileMd5Array", summaries);

      const upMsg = this.$Message.info({
        content: "上传中...",
        duration: 30,
        closable: true,
      });
      try {
        await this.$http.post(
          "/api/branch_ecs_oe_admin/offlineExam/batchSubmitPaper",
          params,
          { headers: { "Content-Type": "multipart/form-data" } }
        );
      } catch (error) {
        this.logger({
          action: "离线考试附件没有正常上传",
          detail: error,
          errorJSON: JSON.stringify(error, (key, value) =>
            key === "token" ? "" : value
          ),
          errorName: error.name,
          errorMessage: error.message,
          errorStack: error.stack,
        });
        throw error;
      } finally {
        this.uploading = false;
        // this.$Message.destroy();
        upMsg();
      }
      this.$Message.success({
        content: "上传成功",
        duration: 5,
        closable: true,
      });
      this.uploadFileList = [];
      this.$emit("close-modal");
      this.$emit("reload-list");
    },

    async blobToSrc(item, index) {
      var fr = new FileReader();
      fr.onload = (eve) => {
        const e = this.$refs["image" + index];
        e[0].src = eve.target.result;
      };

      fr.readAsDataURL(item);
    },

    handleView(imagesClass, index) {
      const viewer = new Viewer(document.querySelector(imagesClass), {
        container: "#app",
        zIndex: 99999,
        title: false,
        toolbar: {
          zoomIn: 1,
          zoomOut: 1,
          oneToOne: 1,
          reset: 1,
          prev: 1,
          play: {
            show: 0,
            size: "large",
          },
          next: 1,
          rotateLeft: 1,
          rotateRight: 1,
          flipHorizontal: 1,
          flipVertical: 1,
        },
        ready() {
          // viewer.zoomTo(1);
          viewer.view(index);
          // console.log("once");
        },
        hidden() {
          viewer.destroy();
        },
      });
      viewer.show();
    },
    handleRemoveTotal(index) {
      this.uploadFileList.splice(index, 1);
    },
  },
};
</script>

<style lang="postcss">
.list .ivu-upload-select {
  width: 100%;
}
/* .image-small {
  width: 100px;
  height: 100px;
} */

.demo-upload-list {
  display: inline-block;
  width: 100px;
  height: 100px;
  text-align: center;
  line-height: 100px;
  border: 1px solid transparent;
  border-radius: 4px;
  overflow: hidden;
  background: #fff;
  position: relative;
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
  margin-right: 4px;

  /* cursor: move; */
}
.demo-upload-list img {
  width: 100%;
  height: 100%;
}
.plus {
  font-size: 48px;
}
.plus:hover {
  cursor: pointer;
  color: blueviolet;
}
.demo-upload-list-cover {
  display: none;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  background: rgba(0, 0, 0, 0.6);
}
.demo-upload-list:hover .demo-upload-list-cover {
  display: block;
}
.demo-upload-list-cover i {
  color: #fff;
  font-size: 20px;
  cursor: pointer;
  margin: 0 2px;
}
</style>
