<template>
  <div id="scene">
    <div id="cvs" ref="content"></div>
    <dev-info ref="info" :devInfo="devInfo" />
    <edit-dialog
      ref="edit"
      @addEquipment="handleAddEqu"
      @removeEquipment="handleRemoveEqu"
      @cancel="handleCancel"
      :hasDev="hasDevice"
      :pointNum="pointNum"
      pointGap="500"
    />
  </div>
</template>

<script setup>
import * as three from "three";
import ThreeDScene from "./sceneClass/demo.js";
import DevInfo from "./displayInfoComp/DevInfo.vue";
import editDialog from "./editEquComp/editDialog.vue";

// 导入模模型加载器
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
// import { DRACOLoader } from "three/examples/jsm/loaders/dracoloader";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import * as TWEEN from "three/examples/jsm/libs/tween.module";
import {
  CSS3DRenderer,
  CSS3DObject,
  CSS3DSprite,
} from "three/addons/renderers/CSS3DRenderer.js";
// 引入CSS2渲染器CSS2DRenderer和CSS2模型对象CSS2DObject
import {
  CSS2DRenderer,
  CSS2DObject,
} from "three/addons/renderers/CSS2DRenderer.js";

import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader";
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader";
import { onMounted, reactive, ref } from "vue";

// 获取html标签跟随组件dom
const content = ref(null);
const info = ref(null);
const edit = ref(null);
let demo; //定义demo全局变量
// const loader = new OBJLoader();
const loader = new OBJLoader();
let hdrLoader = new RGBELoader();
let backColorSet = three.sRGBEncoding;

onMounted(handleMounted);
// 挂载后回调
async function handleMounted() {
  const doms = [info.value.$el, edit.value.$el];
  demo = new ThreeDScene(three, content.value);
  demo.loadModel(GLTFLoader, "./assets/tunnelModel/chanel.gltf");
  demo.addOrbitControls(OrbitControls);
  demo.addTween(TWEEN);
  demo.addCSS3Renderer(CSS3DRenderer, CSS3DSprite, doms);
  demo.setDistance(10);
  lClickCallback(demo); //绑定左键回调
  rClickCallback(demo); //绑定右键回调

  //加载HDR背景图片
  demo.loadBackground(hdrLoader, backColorSet);

  // 初始化设备模型
  try {
    const map = new Map();
    map.set("equ_fan", await loadModel("/devicesModel/fan.obj"));
    map.set("equ_sensors", await loadModel("/devicesModel/sensors.obj"));

    // 给对象初加载设备模型
    demo.initDevicesModel(map);
  } catch (err) {
    console.log(err);
  }
}

// 每个模型加载回调
function loadModel(path) {
  return new Promise((resolve, reject) => {
    loader.load(
      path,
      (obj) => {
        resolve(obj);
      },
      (xhr) => {},
      (err) => {
        reject(err);
      }
    );
  });
}

let hasDevice = ref(true);
let devInfo = reactive({
  meshId: null,
  name: "无",
  state: "无",
  position: "无",
});

// 对象建构赋值功能
function editDevInfo(
  value = {
    meshId: null,
    name: "无",
    state: "无",
    position: "无",
  }
) {
  devInfo.meshId = value.meshId;
  devInfo.name = value.name;
  devInfo.state = value.state;
  devInfo.position = value.position;
}

//左键/双击左键回调函数
function lClickCallback(demo) {
  //demo动态添加函数，为操作组件内部
  function displayDevInfo(targetPoint = null) {
    hasDevice.value = targetPoint.hasDevice;
    if (!targetPoint.info) {
      editDevInfo();
      return;
    }
    editDevInfo(targetPoint.info);
  }
  // 传给内部使用
  demo.addFunction("displayDevInfo", displayDevInfo);
}

let pointNum = ref(0);
let targetP;
// 右键点击附着点后调函数
function rClickCallback(demo) {
  function editDev(targetPoint = null) {
    hasDevice = targetPoint.hasDevice;
    targetP = targetPoint;
    pointNum.value = Number(
      targetPoint.name.substring(
        targetPoint.name.indexOf("_") + 1,
        targetPoint.name.lastIndexOf("_")
      ) - 1
    );

    if (!targetPoint.info) return;
    editDevInfo(targetPoint.info);
  }
  demo.addFunction("editDev", editDev);
}

// 添加设备
function handleAddEqu(formInfo) {
  if (!formInfo.equipmentType) {
    alert("请选择设备");
    return;
  }
  //表单信息
  //这里利用处理请求
  demo.addEquipment(targetP, formInfo);
}

// 删除设备
async function handleRemoveEqu() {
  demo.removeEquipment(targetP);
}

// 处理取消关闭编辑框事件
function handleCancel() {
  if (!demo) return;
  // 关闭标签
  demo.isControlOrbit(true);
  demo._resetState();
  demo.clearTagsObj();
}
</script>

<style lang="scss" scope>
#scene {
  position: relative;
  height: 100%;
  width: 100%;
  #cvs {
    height: 100%;
  }
}
</style>
