<template>
  <iframe class="external" :src="url" ref="iframeRef" v-if="url"></iframe>
  <div class="laser-layer" v-show="!url">
    <div class="scene-canvas" ref="fuseRef">
      <div id="direction"></div>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref, watchEffect, computed, watch, nextTick } from "vue";
import { SceneType } from "@/store";
import { params } from "@/env";
import { fuseModel, modelProps } from "./index";
import { modelSDKFactory } from "./platform";
import { getToken } from "@/api";
import { offlinePrev } from "@/api/offline";

const typeChange = () => {
  const oldType = modelProps.type;
  let stopWatch = (null as unknown) as () => void;

  const typePromise = new Promise((_, reject) => {
    stopWatch = watchEffect(() => {
      if (modelProps.type !== oldType) {
        reject(new Error("当前模型未加载完已切换到下个"));
        stopWatch!();
      }
    });
  });
  return { typePromise, typeCleanup: stopWatch };
};

export const Model = defineComponent({
  name: "model",
  setup() {
    const scene = computed(() => modelProps.type !== fuseModel && modelProps.type);
    const url = ref("");
    const setUrl = (newURL: string) => {
      if (newURL !== url.value) {
        setTimeout(() => {
          const hook = (iframeRef.value?.contentWindow as any)?.beforeDestroy;
          if (hook) {
            try {
              hook();
            } catch (e) {
              console.error(e);
            }
            url.value = "";
            setTimeout(() => (url.value = newURL), 300);
          } else {
            url.value = newURL;
          }
        });
      }
    };

    watchEffect(() => {
      if (!scene.value) {
        return setUrl("");
      }
      const type = scene.value.type;
      const sign = params.sign ? `&sign=${params.sign}` : "";
      const urls = offline
        ? {
            [SceneType.SWKK]: `${offlinePrev}swkk/${scene.value.num}/wwwroot/spg.html?m=${scene.value.num}&lang=zh`,
            [SceneType.DSFXJ]: `${offlinePrev}swkk/${scene.value.num}/wwwroot/spg.html?m=${scene.value.num}&lang=zh`,
            [SceneType.SWKJ]: `${offlinePrev}swkk/${scene.value.num}/wwwroot/spg.html?m=${scene.value.num}&lang=zh`,
            [SceneType.SWSS]: `${offlinePrev}swss/${scene.value.num}/www/offline.html?m=${scene.value.num}&lang=zh`,
            [SceneType.SWSSMX]: `${offlinePrev}swkk/${scene.value.num}/wwwroot/spg.html?m=${scene.value.num}&lang=zh`,
            [SceneType.SWMX]: `offline.html?caseId=${params.caseId}&modelId=${scene.value.num}&share=1#sign-model`,
            [SceneType.SWYDSS]: `${offlinePrev}swss/${scene.value.num}/www/offline.html?m=${scene.value.num}&lang=zh`,
            [SceneType.SWYDMX]: `${offlinePrev}swkk/${scene.value.num}/wwwroot/spg.html?m=${scene.value.num}&lang=zh`,
          }
        : {
            [SceneType.SWKK]: `/swkk/spg.html?m=${scene.value.num}${sign}`,
            [SceneType.DSFXJ]: `/swkk/spg.html?m=${scene.value.num}${sign}`,
            [SceneType.SWKJ]: `/swkk/spg.html?m=${scene.value.num}${sign}`,
            [SceneType.SWSS]: `/swss/index.html?m=${scene.value.num}${sign}`,
            [SceneType.SWSSMX]: `/swkk/spg.html?m=${scene.value.num}${sign}`,
            [SceneType.SWMX]: `index.html?caseId=${params.caseId}&modelId=${scene.value.num}${sign}#sign-model`,
            [SceneType.SWYDSS]: `/swss/index.html?m=${scene.value.num}${sign}`,
            [SceneType.SWYDMX]: `/swkk/spg.html?m=${scene.value.num}${sign}`,
          };

      if (import.meta.env.DEV && !offline) {
        Object.assign(urls, {
          [SceneType.SWKK]: `/swkk/spg.html?m=${
            scene.value.num
          }&toen=${getToken()}${sign}`,
          [SceneType.DSFXJ]: `/swkk/spg.html?m=${
            scene.value.num
          }&toen=${getToken()}${sign}`,
          [SceneType.SWKJ]: `/swkk/spg.html?m=${
            scene.value.num
          }&toen=${getToken()}${sign}`,
          [SceneType.SWSS]: `/swss/index.html?m=${
            scene.value.num
          }&toen=${getToken()}${sign}`,
          [SceneType.SWSSMX]: `/swkk/spg.html?m=${
            scene.value.num
          }&toen=${getToken()}${sign}`,
          [SceneType.SWMX]: `index.html?caseId=${params.caseId}&modelId=${
            scene.value.num
          }&toen=${getToken()}${sign}#sign-model`,
          [SceneType.SWYDSS]: `/swss/index.html?m=${
            scene.value.num
          }${sign}&toen=${getToken()}`,
          [SceneType.SWYDMX]: `/swkk/spg.html?m=${
            scene.value.num
          }${sign}&toen=${getToken()}`,
        });
      }
      setUrl(urls[type]);
    });

    const fuseRef = ref<HTMLDivElement>();
    const iframeRef = ref<HTMLIFrameElement>();

    watch(
      () => [modelProps.type, url.value],
      async ([type, url], oldType, onCleanup) => {
        if (type !== fuseModel && !url) {
          return;
        }
        const callback = modelProps.callback;

        await nextTick();
        const { typePromise, typeCleanup } = typeChange();
        const modelPromise = modelSDKFactory(
          type as any,
          type === fuseModel ? fuseRef.value! : iframeRef.value!
        );
        let result: any = null,
          error = null;
        try {
          result = await Promise.race([typePromise, modelPromise]);
        } catch (err: any) {
          error = err;
        }
        typeCleanup();
        callback && callback(result, error);
      },
      { immediate: true, flush: "post" }
    );

    // 处理iframe 定制页面
    watch(
      () => [scene.value && scene.value.type, url.value],
      ([type], oldType, onCleanup) => {
        if (type === false) {
          // 手动渲染融合场景
          console.log("手动渲染！");
          setTimeout(() => {
            (window as any).viewer?.setDisplay(true);
          }, 1000);
        }

        const interval = setInterval(async () => {
          let doc: Document | undefined;
          try {
            doc = iframeRef.value?.contentWindow?.document!;
          } catch {
            clearInterval(interval);
          }
          if (!doc || !doc.querySelector("div")) return;
          console.error(doc, doc.head);
          const target = doc.head;
          clearInterval(interval);
          (window as any).iframeCreated && (window as any).iframeCreated(iframeRef.value);
          if (type === SceneType.SWSS) {
            const $style = document.createElement("style");
            $style.type = "text/css";
            var textNode = document.createTextNode(`
              .mode-tab > .model-mode-tab.strengthen {
                display: none !important;
              }
            `);
            $style.appendChild(textNode);
            target.appendChild($style);
          }
        }, 16);
        onCleanup(() => clearInterval(interval));
      },
      { flush: "post", immediate: true }
    );

    return {
      iframeRef,
      fuseRef,
      url,
    };
  },
});

export default Model;
</script>

<style scoped lang="scss">
.laser-layer {
  position: absolute;
  z-index: 1;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;

  .scene-canvas {
    width: 100%;
    height: 100%;
  }
}

.external {
  position: absolute;
  z-index: 1;
  border: none;
  top: calc(var(--editor-head-height) + var(--header-top));
  left: 0;
  height: calc(100% - (var(--editor-head-height) + var(--header-top)));
  width: 100%;
}

#direction {
  right: calc(var(--editor-menu-right) + var(--editor-toolbox-width)) !important;
  top: calc(var(--header-top) + var(--editor-head-height) + 50px) !important;
  margin: 10px;
  transition: top 0.3s ease, right 0.3s ease;
}
</style>
