<template>
  <div class="container">
    <div class="modal-height">
      <div class="file-box">
        <p class="file-name" v-show="!renderLoading">{{ file.filename }}</p>
        <div class="view-wrapper">
          <div class="preview-wrapper" ref="wrapper" v-if="isAbleView">
            <div class="preview-inner" ref="preview-inner">
              <div class="preview-mark" ref="bg-mark" id="bg-mark"></div>
              <div class="loading-container" v-show="renderLoading">
                <div class="loading-spinner">
                  <svg viewBox="0 0 50 50" class="circular">
                    <circle cx="25" cy="25" r="20" fill="none" class="path"></circle>
                  </svg>
                </div>
              </div>
              <div class="output" v-show="!renderLoading" ref="output"></div>
            </div>
          </div>
          <view-other-component
            v-else-if="file.type && !isAbleView"
            :file="file"
          />
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, watch, nextTick } from "vue"
import commJs from "@/comm_js"
import { render } from "@/components/view_file/util"
import ViewOtherComponent from "@/components/view_file/vendors/other/index.vue"


const props = defineProps({
  file: {
    type: Object,
    default: () => {
      return {}
    },
  },
})

const renderLoading = ref(false)
const output = ref(null)

// 可在在线预览文件类型
const isAbleView = computed(() => {
  const lowType = (props.file.type || "").toLowerCase()
  const typeObject = {
    doc: ["docx"],
    xlsx: ["xlsx"],
    pdf: ["pdf"],
    ppt: ["pptx"],
    image: ["gif", "jpg", "jpeg", "bmp", "tiff", "tif", "png", "svg"],
    text: [
      "txt",
      "json",
      "js",
      "css",
      "java",
      "py",
      "html",
      "jsx",
      "ts",
      "tsx",
      "xml",
      "md",
      "log",
    ],
  }
  const ablePreviewTypes = Object.values(typeObject).flat()
  return ablePreviewTypes.includes(lowType)
})

/**
 * @{params} buffer 文件字节流
 * @{params} extend 文件扩展名
 */
const renderResult = (buffer, extend) => {
  if (!output.value) {
    return Promise.reject(new Error("Output element not found"))
  }
  output.value.innerHTML = ""
  const node = document.createElement("div")
  const child = output.value.appendChild(node)
  return new Promise((resolve, reject) =>
    render(buffer, extend, child).then(resolve).catch(reject)
  )
}

watch(
  () => props.file,
  (newFile) => {
    if (newFile && newFile.type) {
      try {
        renderLoading.value = true
        nextTick(() => {
          renderResult(newFile.fileBuffer, newFile.type).finally(() => {
            renderLoading.value = false
          })
        })
      } catch (error) {
        console.warn(error)
      }
    }
  },
  { immediate: true, deep: true }
)
</script>

<style lang="less">
.container {
  width: 100%;
  height: 100%;
  .docx-wrapper {
    background: unset !important;
    padding: 0 !important;

    & > section.docx {
      background: unset !important;
    }
  }
}
</style>
<style lang="less" scoped>
@import url("./index.less");
:deep(.header-rewrite) {
  margin-bottom: 0 !important;
}

.modal-height {
  display: flex;
  justify-content: space-between;
  height: 100%;
  .file-box {
    flex: 1;
    padding: 15px 40px;
    overflow: scroll;
    text-align: center;

    .file-name {
      line-height: 36px;
      text-align: center;
      font-size: 16px;
      font-weight: 500;
    }

    .view-wrapper {
      position: relative;
      width: 100%;
      height: calc(100% - 36px);
      overflow: hidden;
      .preview-inner {
        position: relative;
        width: 100%;
        height: 100%;
        
        .loading-container {
          position: absolute;
          top: 50%;
          left: 50%;
          transform: translate(-50%, -50%);
          z-index: 999;
          display: flex;
          flex-direction: column;
          align-items: center;
          
          .loading-spinner {
            width: 50px;
            height: 50px;
            
            .circular {
              animation: rotate 2s linear infinite;
              height: 100%;
              transform-origin: center center;
              width: 100%;
              position: absolute;
              top: 0;
              bottom: 0;
              left: 0;
              right: 0;
              margin: auto;
            }
            
            .path {
              stroke-dasharray: 90, 150;
              stroke-dashoffset: 0;
              stroke-width: 4;
              stroke-miterlimit: 10;
              stroke: #409eff;
              stroke-linecap: round;
              animation: dash 1.5s ease-in-out infinite;
            }
          }
          
          .loading-text {
            margin-top: 15px;
            color: #606266;
            font-size: 14px;
          }
        }
      }
    }
  }
}

@keyframes rotate {
  100% {
    transform: rotate(360deg);
  }
}

@keyframes dash {
  0% {
    stroke-dasharray: 1, 150;
    stroke-dashoffset: 0;
  }
  50% {
    stroke-dasharray: 90, 150;
    stroke-dashoffset: -35;
  }
  100% {
    stroke-dasharray: 90, 150;
    stroke-dashoffset: -124;
  }
}
</style>
