<template>
  <div>
    <Upload
      ref="uploadComp"
      :headers="headers"
      :data="{ fileType: fileType }"
      :before-upload="handleBeforeUpload"
      :action="
        '/api/ecs_oe_admin/offlineExam/submitPaper?examRecordDataId=' +
          course.examRecordDataId
      "
      :max-size="1024 * 30"
      :format="uploadFileFormat"
      :accept="uploadFileAccept"
      :on-format-error="handleFormatError"
      :on-exceeded-size="handleMaxSize"
      :on-success="handleSuccess"
      :on-error="handleError"
      :show-upload-list="false"
    >
      <i-button
        icon="ios-cloud-upload-outline"
        class="qm-primary-button"
        style="width: 100%;"
      >
        上传作答
      </i-button>
    </Upload>
    <div v-if="file !== null && loadingStatus">
      待上传文件: {{ file.name }}
      <i-button :loading="loadingStatus">
        {{ loadingStatus ? "上传中..." : "上传" }}
      </i-button>
    </div>
  </div>
</template>

<script>
export default {
  name: "EcsOfflineUpload",
  props: {
    course: {
      type: Object,
      default() {
        return {};
      },
    },
  },
  data() {
    return {
      headers: {
        token: window.sessionStorage.getItem("token"),
        key: window.localStorage.getItem("key"),
      },
      file: null,
      fileType: null,
      loadingStatus: false,
      uploadFileFormat: [],
      uploadFileAccept: "",
    };
  },
  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: {
    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 "FFD8FFDB":
          case "FFD8FFE0":
          case "FFD8FFE1":
            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 (["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();
            }
          } 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();
            }
          } 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);
    },
    handleSuccess() {
      window._hmt.push(["_trackEvent", "离线考试页面", "上传作答", "上传成功"]);
      this.file = null;
      this.loadingStatus = false;
      this.$Message.success({
        content: "上传成功",
        duration: 5,
        closable: true,
      });
      this.$emit("reloadList");
    },
    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.",
      });
    },
    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");
      }

      return new Promise((resolve, reject) => {
        if (this.course.offlineFileUrl) {
          this.$Modal.confirm({
            title: "已有作答附件，是否覆盖？",
            onCancel: () => reject(-1),
            onOk: () => resolve(),
          });
        } else {
          resolve();
        }
      }).then(() => {
        if (file.type.includes("/pdf")) {
          this.fileType = "pdf";
        } else if (file.type.includes("/zip")) {
          this.fileType = "zip";
        }
        this.file = file;
        this.loadingStatus = true;
        return new Promise((resolve, reject) =>
          this.fileFormatCheck(file, resolve, reject)
        );
      });
    },
  },
};
</script>

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