<script setup>
import {
  ref,
  onMounted,
  defineProps,
  markRaw,
  watch,
  nextTick,
  provide,
} from "vue";
import { getUrn, getAccessToken } from "@/apis/forge";
import useForgeDbIdStore from "@/stores/useForgeDbIdStore";
import ForgeModal from "./ForgeModal.vue";
import useRefrigerantTemp from "@/hooks/baja/useRefrigerantHeatMap";
import { twMerge } from "tailwind-merge";
import hexToRgb from "@/util/hexToRgb"

const props = defineProps({
  data: Array,
  fullScreen: Boolean,
});

const deviceList = ref([]);
const forgeDom = ref(null);
const forgeViewer = ref(null);
const forgeViewerModel = ref(null);
const urn = ref("");
let allDbIdsStr = [];

const open = ref(false);
const modalContent = ref(null);
provide("modalContent", modalContent);
const moveModal = (elmnt) => {
  console.log(elmnt);
  var pos1 = 0,
    pos2 = 0,
    pos3 = 0,
    pos4 = 0;
  document.querySelector(
    ".forge_modal .ant-modal-body .card-title"
  ).onmousedown = dragMouseDown;

  function dragMouseDown(e) {
    e = e || window.event;
    e.preventDefault();
    // get the mouse cursor position at startup:
    pos3 = e.clientX;
    pos4 = e.clientY;
    document.onmouseup = closeDragElement;
    // call a function whenever the cursor moves:
    document.onmousemove = elementDrag;
  }

  function elementDrag(e) {
    e = e || window.event;
    e.preventDefault();
    // calculate the new cursor position:
    pos1 = pos3 - e.clientX;
    pos2 = pos4 - e.clientY;
    pos3 = e.clientX;
    pos4 = e.clientY;
    // set the element's new position:
    elmnt.style.top = elmnt.offsetTop - pos2 + "px";
    elmnt.style.left = elmnt.offsetLeft - pos1 + "px";
  }

  function closeDragElement() {
    // stop moving when mouse button is released:
    document.onmouseup = null;
    document.onmousemove = null;
  }
};
const toggleModal = async (e) => {
  open.value = !open.value;
  await nextTick();
  if (open.value) {
    const elmnt = document.querySelector(".forge_modal .ant-modal");
    elmnt.style.top = e.clientY - 20 + "px";
    elmnt.style.left = e.clientX + 20 + "px";
    moveModal(elmnt);
  }
};
const onSpriteClicked = (event) => {
  event.hasStopped = true;
  const data = deviceList.value.find((d) => d.spriteDbId === event.dbId);
  modalContent.value = data;
  store.getDbIdStore(data.forge_dbid);
  toggleModal(event.originalEvent);
};
// 創建 sprites
const createSprites = async (dataVizExtn) => {
  if (!dataVizExtn || !props.data || props.data.length === 0) return;
  const DataVizCore = Autodesk.DataVisualization.Core;
  const viewableType = DataVizCore.ViewableType.SPRITE;
  let spriteColor = new THREE.Color(0xffffff);
  const BASEURL = window.env?.VITE_FORGE_BASEURL;
  const spriteIconUrl = `${BASEURL}/hotspot.svg`;
  const style = new DataVizCore.ViewableStyle(
    viewableType,
    spriteColor,
    spriteIconUrl
  );
  const viewableData = new DataVizCore.ViewableData();
  viewableData.spriteSize = 24; // Sprites as points of size 24 x 24 pixels
  deviceList.value = props.data?.map((myData, index) => {
    const dbId = 10 + index;
    const position = JSON.parse(myData.device_coordinate_3d);
    style.color = new THREE.Color(hexToRgb(myData.device_normal_color));
    const viewable = new DataVizCore.SpriteViewable(position, style, dbId);
    viewableData.addViewable(viewable);
    return {
      ...myData,
      spriteDbId: dbId,
    };
  });
  await viewableData.finish();
  dataVizExtn.addViewables(viewableData);

  forgeViewer.value.addEventListener(DataVizCore.MOUSE_CLICK, onSpriteClicked);
  forgeViewer.value.addEventListener(
    Autodesk.Viewing.SELECTION_CHANGED_EVENT,
    onSpriteClicked
  );
};

const initViewer = (container) => {
  return new Promise(function (resolve, reject) {
    Autodesk.Viewing.Initializer({ getAccessToken }, function () {
      const config = {
        extensions: ["Autodesk.DataVisualization", "Autodesk.DocumentBrowser"],
      };
      let viewer = new Autodesk.Viewing.GuiViewer3D(container, config);
      Autodesk.Viewing.Private.InitParametersSetting.alpha = true;
      viewer.start();
      viewer.setTheme("light-theme");
      resolve(viewer);
    });
  });
};

const loadModel = (viewer, urn) => {
  return new Promise(function (resolve, reject) {
    async function onDocumentLoadSuccess(doc) {
      viewer.setGroundShadow(false);
      viewer.impl.renderer().setClearAlpha(0); //clear alpha channel
      viewer.impl.glrenderer().setClearColor(0xffffff, 0); //set transparent background, color code does not matter
      viewer.impl.invalidate(true); //trigger rendering

      const documentNode = await viewer.loadDocumentNode(
        doc,
        doc.getRoot().getDefaultGeometry()
      );

      resolve(documentNode);
    }
    function onDocumentLoadFailure(code, message, errors) {
      reject({ code, message, errors });
    }
    viewer.setLightPreset(0);
    Autodesk.Viewing.Document.load(
      "urn:" + urn,
      onDocumentLoadSuccess,
      onDocumentLoadFailure
    );
  });
};

const hideAllObjects = (viewer, filDbids = []) => {
  for (var i = 0; i < allDbIdsStr.length; i++) {
    viewer.hide(parseInt(allDbIdsStr[i]));
  }

  for (var i = 0; i < filDbids.length; i++) {
    viewer.show(parseInt(filDbids[i]));
  }
  viewer.impl.invalidate(true);
};

const initForge = () => {
  getUrn().then((res) => {
    if (!res.isSuccess) return;
    urn.value = res.data[0].urn_3D;
    initViewer(forgeDom.value).then((viewer) => {
      loadModel(viewer, res.data[0].urn_3D).then(() => {
        viewer.addEventListener(
          Autodesk.Viewing.GEOMETRY_LOADED_EVENT,
          async function () {
            forgeViewer.value = markRaw(viewer);
            forgeViewerModel.value = viewer.model;
            const dataVizExtn = await viewer.loadExtension(
              "Autodesk.DataVisualization"
            );

            createSprites(dataVizExtn);
            refrigerantHeatMap.getBasicData(
              viewer,
              dataVizExtn,
              deviceList.value
            );
            viewer.fitToView([0], viewer.model);
            window.setTimeout(() => {
              let instanceTree = viewer.model?.getData().instanceTree;
              allDbIdsStr = Object.keys(instanceTree.nodeAccess.dbIdToIndex);
              const filDbids = deviceList.value.map((x) => x.forge_dbid);
              hideAllObjects(forgeViewer.value, filDbids);
            }, 500);
          }
        );
      });
    });
  });
};

onMounted(() => {
  initForge();
});

// 聚焦
const store = useForgeDbIdStore();
const fitToView = () => {
  forgeViewer.value?.fitToView(store.dbId);
};

const refrigerantHeatMap = useRefrigerantTemp();

watch(
  () => store.dbId,
  (newVal) => {
    if (forgeViewer.value) {
      fitToView();
    }
  }
);
</script>

<template>
  <div
    :class="
      twMerge(
        fullScreen
          ? 'absolute top-0 left-0 w-screen h-screen z-0'
          : 'w-full relative'
      )
    "
  >
    <slot name="heat_bar"></slot>
    <div
      id="forge-preview"
      ref="forgeDom"
      :class="
        twMerge(
          'relative w-full max-h-full ',
          fullScreen ? 'h-screen' : 'min-h-[600px]'
        )
      "
    ></div>
  </div>
  <ForgeModal :open="open" :toggleModal="toggleModal" />
</template>

<style lang="css">
.adsk-viewing-viewer {
  background-color: transparent !important;
}

#guiviewer3d-toolbar {
  /* display: none; */
  bottom: 200px;
}
</style>
