<template>
  <div id="scene" ref="content">
    <dev-info ref="info" :devInfo="devInfo" />
    <edit-dev ref="edit" @addDev="handleAddDev" @removeDev="handleRemoveDev" :hasDev="hasDevice" />
  </div>
</template>

<script setup>
import * as three from "three";
import ThreeDScene from "./sceneClass/demo.js";

// 导入模模型加载器
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";
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader";
import DevInfo from "./childComp/DevInfo.vue";
import EditDev from "./childComp/EditDev.vue";
import { onMounted, reactive, ref } from "vue";

import { ElMessage } from "element-plus";
// 获取html标签跟随组件
const content = ref(null);
const info = ref(null);
const edit = ref(null);
const num = 10000;
let demo; //定义demo全局变量
const loader = new OBJLoader();
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(backColorSet)
  // 初始化设备模型
  try {
    const deviceList = [];
    let result = await loadModel("/devicesModel/camera.obj");
    deviceList.push(result);
    modelEffectProcess(result);
    result = await loadModel("/devicesModel/fan.obj");
    deviceList.push(result);
    modelEffectProcess(result);
    result = await loadModel("/devicesModel/sensors.obj");
    deviceList.push(result);
    modelEffectProcess(result);
    result = await loadModel("/devicesModel/sensors.obj");
    deviceList.push(result);
    modelEffectProcess(result);
    result = await loadModel("/devicesModel/sensors.obj");
    deviceList.push(result);
    modelEffectProcess(result);
    // 给对象初加载设备模型
    demo.initDevicesModel(deviceList);
    console.info("设备模型加载完毕");
    // 清空内存
    result = null;
  } catch (err) {
    console.log(err);
  }
}
// 每个模型加载回调
function loadModel(path) {
  return new Promise((resolve, reject) => {
    loader.load(
      path,
      (obj) => {
        resolve(obj);
      },
      (xhr) => { },
      (err) => {
        reject(err);
      }
    );
  });
}


function modelEffectProcess(model) {
  model.traverse((v) => {
    v.material = new three.MeshBasicMaterial
    v.material.color = new three.Color(0xC0C0C0)
  })
}


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

// 点击右键设备返回附着点对象
function rClickCallback(demo) {
  function editDev(targetPoint = null) {
    hasDevice = targetPoint.hasDevice;
    if (!targetPoint.info) return;
    editDevInfo(targetPoint.info);
  }
  demo.addFunction("editDev", editDev);
}

// 添加设备
function handleAddDev(devInfo) {
  if (!demo) {
    //  处理未加载完场景情况
    console.info("3D场景正在渲染，请稍后操作");
    return;
  }
  const tempDevInfo = demo.addDev(devInfo);
  hasDevice.value = true;
  editDevInfo(tempDevInfo);
  ElMessage({
    message: "添加成功",
    type: "success",
  });
}

// 删除设备
async function handleRemoveDev() {
  const result = await demo.removeDev(devInfo.meshId);
  if (result === "ok") {
    hasDevice.value = false;
    editDevInfo();
    ElMessage({
      message: "删除成功",
      type: "success",
    });
  }
}
</script>

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