<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" :class="{ full: full === 'scene' }">
      <span class="taggle switch" v-if="full !== 'scene'" @click="full = 'scene'">
        <ui-icon type="f-l" ctrl />
      </span>
      <div id="direction"></div>
    </div>
    <div id="scene-map" :class="{ full: full === 'map' }">
      <span class="taggle switch" v-if="full === 'scene'" @click="full = 'map'">
        <ui-icon type="f-l" ctrl />
      </span>
    </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";

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 urls = !(window as any).offline
        ? {
            [SceneType.SWKK]: `/swkk/spg.html?m=${scene.value.num}`,
            [SceneType.SWKJ]: `/swkk/spg.html?m=${scene.value.num}`,
            [SceneType.SWSS]: `/swss/index.html?m=${scene.value.num}`,
            [SceneType.SWSSMX]: `/swkk/spg.html?m=${scene.value.num}`,
            [SceneType.SWMX]: `index.html?caseId=${params.caseId}&app=${params.app}&modelId=${scene.value.num}&share=1#sign-model`,
            [SceneType.SWYDSS]: `/swss/index.html?m=${scene.value.num}`,
            [SceneType.SWYDMX]: `/swkk/spg.html?m=${scene.value.num}`,
          }
        : {
            [SceneType.SWKK]: `/swkk/spg.html?m=${scene.value.num}`,
            [SceneType.SWKJ]: `/swkk/spg.html?m=${scene.value.num}`,
            [SceneType.SWSS]: `/swss/offline.html?m=${scene.value.num}`,
            [SceneType.SWSSMX]: `/swkk/spg.html?m=${scene.value.num}`,
            [SceneType.SWMX]: `offline.html?caseId=${params.caseId}&app=${params.app}&modelId=${scene.value.num}&share=1#sign-model`,
            [SceneType.SWYDSS]: `/swss/offline.html?m=${scene.value.num}`,
            [SceneType.SWYDMX]: `/swkk/spg.html?m=${scene.value.num}`,
          };
      setUrl(urls[type as SceneType]);
    });

    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);
          }, 100);
        }

        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,
      full: ref("scene"),
      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%;
}

.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)) !important;
  margin: 10px;
  transition: top 0.3s ease, right 0.3s ease;
}
.scene-canvas,
#scene-map {
  &:not(.full) {
    position: absolute !important;
    right: calc(var(--editor-menu-right) + var(--editor-toolbox-width)) !important;
    bottom: 0;
    width: 320px;
    height: 200px;
    z-index: 99;
    #direction {
      top: 0 !important;
      right: 0 !important;
    }
  }

  &.full {
    width: 100%;
    height: 100%;
    background-color: #ccc;
    z-index: 90;
  }
}

#scene-map {
  display: none;
}

.taggle {
  position: absolute;
  font-size: 16px;
  color: #fff;
  background: rgba(0, 0, 0, 0.3);
  z-index: 9999999;
  width: var(--taggle-btn-width);
  height: var(--taggle-btn-width);
  display: flex;
  align-items: center;
  left: 10px;
  top: 10px;
  overflow: hidden;
  justify-content: center;
  border-radius: 3px;
  cursor: pointer;
}
</style>
