<template>
  <div :class="$style['threemap']" ref="map"></div>
</template>

<script setup lang="ts">
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import {
  CSS3DRenderer,
  CSS3DObject,
} from "three/examples/jsm/renderers/CSS3DRenderer.js";
import { DragControls } from "three/examples/jsm/controls/DragControls";
// import { TransformControls } from "three/examples/jsm/controls/TransformControls";
// import  { Projector }  from 'three/examples/jsm/renderers/Projector.js';
import {
  markRaw,
  nextTick,
  onMounted,
  onUnmounted,
  reactive,
  ref,
  watch,
} from "vue";
import { useRoute, useRouter } from "vue-router";
import { useMechanicalViewStore } from "@/store/module/MechanicalView";
import { useMechanicsStore } from "@/store/module/Mechanics";
import { useI18n } from 'vue-i18n'
let {t} = useI18n();
const storeMechanics = useMechanicsStore();
const store = useMechanicalViewStore();
const router = useRouter();
let ThreeObj = null;
let cssThreeObj = null;
let devposition = {
  精加车间: {
    start: [-218, -63.5],
    end: [-167, -296.7],
  },
  焊接车间: {
    start: [211.6, -88.6],
    end: [262.5, -282.6],
  },
  精饰车间: {
    start: [56.4, -167.2],
    end: [138.8, -297.6],
  },
  机加车间: {
    start: [-117.2, -53.2],
    end: [-85, -279],
  },
  大件车间: {
    start: [-10.2, -72.2],
    end: [27.4, -273.7],
  },
};
let map = ref();
/**
 * @函数功能:
 * @param {*} val 重置画布宽高值
 * @出口参数:
 * @函数备注:
 */
function reset(val: any) {
  //宽高为0时跳出该方法

  if (!val.oWidth && !val.oHeight) return;
  // mapSize.width=val.width
  // mapSize.height=val.height
  // 更新修改相机比例
  map.value.style.width = val.oWidth;
  map.value.style.height = val.oHeight;
  ThreeObj.camera.aspect = val.oWidth / val.oHeight;
  // 更新摄像机的投影矩阵
  ThreeObj.camera.updateProjectionMatrix();

  //处理返回操作时dom层数变多问题
  if (document.getElementsByClassName("cssrender").length > 1) {
    document.getElementsByClassName("cssrender")[1].remove();
  }
  // 更新画布大小
  ThreeObj.renderer.setSize(
    val.oWidth, // 宽度
    val.oHeight // 高度
  );
  cssThreeObj.cssRender.setSize(
    val.oWidth, // 宽度
    val.oHeight // 高度
  );
  // 更新画布像素比
  ThreeObj.renderer.setPixelRatio(map.value.devicePixelRatio);

  //重置盒子尺寸
}
defineExpose({
  reset,
});

let mapPng = require("@/assets/img/jingjia.svg");

// 为模型添加点击事件处理程序
const raycaster = new THREE.Raycaster();
// 加载控制器,获取场景内模型列表
var objects = [];
//储存tip的dom用于显示与隐藏
let saveTipDom = null;
let transformControls = null;
let dragControls = null;
let index = 1;
let meshBox = {};
let size = {
  x: 25,
  y: 50,
  z: 2,
};
let MaterialObj = {
  color: 0xff00ff, //颜色 16进制
  opacity: 1, //透明度 0-1
  transparent: true, //开启透明度，默认关闭
  wireframe: false, //线框，默认关闭
  visible: false, //设置材质隐藏
};
watch(
  () => store.sensorList,
  (newVal, oldVal) => {
    newVal.forEach((res) => {
      if (res.judge == "t") {
        if (
          cssThreeObj.cssScene.children.some((item) => {
            return item.devId == res.id;
          })
        ) {
          cssThreeObj.cssScene.children.forEach((ele) => {
            if (ele.devId == res.id) {              
              ele.children[0].element.className = `iconfont ${res.status ? "icon-blue" : "icon-red"
    } iconSize ${res.iconName}`;
              if (res.editStatus) {
                ele.devStatus=JSON.parse(res.status)
              }
            }
          });
        } else {
          setIconDom(
            cssThreeObj,
            { id: res.id, name: res.name, status: res.status },
            { x: res.x, y: res.y },
            res.iconName,
            10
          );
        }
      }
    });
    if (newVal.length != oldVal.length) {
      sethoveMesh(cssThreeObj, ThreeObj);
    }
  },
  { deep: true, flush: "post" }
);
watch(
  () => store.devdataList,
  (newVal, oldVal) => {
    newVal.forEach((res) => {
      let x = [devposition[res.store].start[0], devposition[res.store].end[0]];
      let y = [devposition[res.store].start[1], devposition[res.store].end[1]];
      res.value.forEach((devitem) => {
        if (
          cssThreeObj.cssScene.children.some((item) => {
            return item.devId == devitem.id;
          })
        ) {
          cssThreeObj.cssScene.children.forEach((ele) => {
            if (ele.devId == devitem.id) {              
              if (JSON.parse(devitem.status)) {
                  ele.children[0].element.className = `iconfont icon-blue iconSize ${devitem.iconName}`;
                } else {
                  ele.children[0].element.className = `iconfont icon-red iconSize ${devitem.iconName}`;
                }
                if (devitem.editStatus) {
                  ele.devStatus=JSON.parse(devitem.status)

                }
            }
          });
        } else {
          setIconDom(
            cssThreeObj,
            {
              id: devitem.id,
              name: devitem.name,
              status: JSON.parse(devitem.status),
            },
            { x: devitem.x, y: devitem.y },
            devitem.iconName,
            5
          );

          x[0] += 7;
          if (x[0] >= x[1]) {
            x[0] = devposition[res.store].start[0];
            y[0] -= 7;
          }
        }
      });
    });

    setTimeout(() => {
      document.querySelectorAll(".icon-shebeiditu").forEach((res: any) => {
        let a = res.className.split(" ");
        let b = res.style.transform.split(" ");
        
        if (
          a.some((e) => {
            return e == "SSCBar";
          })||b.some((e) => {
            return e=="scale(" + 0.5 + ")";
          })
        ) {
          return;
        }
        res.style.transform = res.style.transform + "scale(" + 0.5 + ")";
      });
    });
    
    
    let new1 = []
    let old = []
    newVal.forEach(res=>{
      new1.push(...res.value)
    })
    oldVal.forEach(res=>{
      old.push(...res.value)
    })
    if (new1.length != old.length) {
      
      sethoveMesh(cssThreeObj, ThreeObj);
    }
  },
  { deep: true, flush: "post" }
);
let routeDataSet = [
{
    id: "fineMachining",
    size: { x: 122, y: 396, z: 1 },
    MaterialObj: MaterialObj,
    position: { x: -260, y: -38, z: 0 },
    router: 1,
  },
];
/**
 * @函数功能:
 * @param {*} size 框大小
 * @param {*} material 材质设置
 * @param {*} id 通过id判断跳转
 * @param {*} position 位置
 * @出口参数:
 * @函数备注:
 */
function setMesh(size, material, id, position) {
  var geometry = new THREE.BoxGeometry(size.x, size.y, size.z); //创建一个立方体几何对象Geometry
  var material = new THREE.MeshLambertMaterial(material); //材质对象Material
  var mesh = new THREE.Mesh(geometry, material);
  mesh.position.set(position.x, position.y, position.z);
  mesh.id2 = id;
  return mesh; //网格模型对象Mesh
}
function initThree(height, width) {
  //创建场景
  let scene = markRaw(new THREE.Scene());
  //创建相机
  let camera = new THREE.PerspectiveCamera(50, width / height, 1, 2000);
  // 3.创建WebGLRenderer渲染器
  let renderer = new THREE.WebGLRenderer();
  /**
   * 光源设置
   */
  //点光源
  var point = new THREE.PointLight(0xfffffff);
  point.position.set(100, 100, 100); //点光源位置
  scene.add(point); //点光源添加到场景中
  //环境光
  var ambient = new THREE.AmbientLight(0x444444);
  scene.add(ambient);

  camera.position.set(0, 0, 550); //设置相机位置
  camera.lookAt(scene.position);
  renderer.setSize(width, height);
  renderer.domElement.id = "renderer";
  // 设置渲染位置
  map.value.appendChild(renderer.domElement);
  return { scene, camera, renderer };
}
function initCss3DScene(height, width) {
  const cssScene = new THREE.Scene();
  const cssRender = new CSS3DRenderer();
  cssRender.setSize(width, height);
  cssRender.domElement.style.position = "absolute";
  cssRender.domElement.style.top = 0;
  cssRender.domElement.className = "cssrender";
  document.body.appendChild(cssRender.domElement);
  //   const controls = new OrbitControls(ThreeObj.camera, cssRender.domElement);
  return {
    cssScene,
    cssRender,
  };
}
function setCssDom(cssThreeObj) {
  const dom = document.createElement("i");
  const domTag = document.createElement("div");
  dom.className = "iconfont icon-blue iconSize icon-dianliu";
  dom.style.fontSize = "10px";

  domTag.innerText = "电流";
  domTag.style.fontSize = "0.1rem";
  domTag.style.backgroundColor = "rgba(0,0,0,.5)";
  domTag.style.padding = "5px";
  domTag.style.borderRadius = "2px";
  nextTick(() => {
    domTag.style.transform = domTag.style.transform + "scale(" + 0.5 + ")";
  });

  //   setInterval(() => {
  //     console.log(dom.style.color);

  //     // if(dom.style.color=='rgb(32, 174, 197)'){
  //     //     dom.style.color='#fff'
  //     // }else{
  //     //     dom.style.color='#20aec5'
  //     // }

  //         //   swiper1.swipering();
  //         //   swiper2.swipering();
  //         }, 1000);
  //   dom.style.animation= 'redstarton 2s infinite'
  // dom.innerText = "红色正方体";
  const iDomCss3 = new CSS3DObject(dom);
  const iTagDomCss3 = new CSS3DObject(domTag);

  //   iDomCss3.scale.set(0.08, 0.08, 0.08);
  //   iDomCss3.position.set(100, 100, 50);
  //   iDomCss3.translateX(100);
  //   iDomCss3.translateY(100);
  //   iDomCss3.translateZ(30);
  // iDomCss3.rotateX(-Math.PI * 0.15);

  // const geometry = new THREE.ConeGeometry(10, 10);
  // geometry.translate(0, 0, 0);
  // var material = new THREE.MeshLambertMaterial(material); //材质对象Material
  // const mesh = new THREE.Mesh(geometry, material);
  //   mesh.translateZ(50);
  // mesh.add(iDomCss3);
  // mesh.add(iTagDomCss3);
  // 相对父对象局部坐标原点偏移80,刚好标注在圆锥顶部
  //   iDomCss3.position.y += 80;
  iDomCss3.position.z += 2;
  iTagDomCss3.position.z += 2;
  iTagDomCss3.position.y += 20;
  cssThreeObj.cssScene.add(iDomCss3);
  cssThreeObj.cssScene.add(iTagDomCss3);
}
/**
 * @函数功能:
 * @param {*} cssThreeObj 传入css画布对象
 * @param {*} item  接口获取的每一个传感器
 * @param {*} position 传感器位置
 * @param {*} icon 传感器图标
 * @出口参数:
 * @函数备注:
 */
function setIconDom(cssThreeObj, item, position, icon, size) {
  const dom = document.createElement("i");
  dom.className = "iconfont icon-blue iconSize icon-dianliu";
  dom.className = `iconfont ${
    item.status ? "icon-blue" : "icon-red"
  } iconSize ${icon}`;
  // dom.style.color = "#88e76a"
  if (size >= 10) {
    dom.style.fontSize = size + "px";
    var geometry = new THREE.BoxGeometry(size, size, size);
    //   nextTick(() => {
    //     dom.style.transform = dom.style.transform + "scale(" + 0.1 + ")";
    //     console.log(dom.style.transform);

    // });
  } else {
    dom.style.fontSize = "10px";
    var geometry = new THREE.BoxGeometry(size, size, size);
  }

  const iDomIcon = new CSS3DObject(dom);
  iDomIcon.position.x = 0;
  iDomIcon.position.y = 0;
  iDomIcon.position.z = 0;
  //创建一个立方体几何对象Geometry
  var material = new THREE.MeshLambertMaterial(MaterialObj); //材质对象Material
  var mesh = new THREE.Mesh(geometry, material);

  mesh.position.x = position.x;
  mesh.position.y = position.y;
  mesh.position.z = 1;

  mesh.devId = item.id;
  mesh.devName = item.name;
  mesh.devStatus = item.status;
  // mesh.visible = true;
  mesh.add(iDomIcon);

  cssThreeObj.cssScene.add(mesh);
  if (size <= 10) {
    nextTick(() => {
      dom.style.transform = dom.style.transform + "scale(" + size * 0.1 + ")";
    });
  }
}
/**
 * @函数功能:
 * @param {*} cssThreeObj 传入css画布对象
 * @出口参数:
 * @函数备注:
 */
function setTipDom(cssThreeObj) {
  const domTag = document.createElement("div");
  domTag.setAttribute("id2", "tipId");
  // domTag.innerText='电流'
  domTag.style.fontSize = "0.1rem";
  domTag.style.backgroundColor = "rgba(0,0,0,.5)";
  domTag.style.padding = "5px";
  domTag.style.borderRadius = "2px";
  domTag.style.color = "#fff";
  nextTick(() => {
    domTag.style.transform = domTag.style.transform + "scale(" + 0.5 + ")";
  });
  const iTagDomCss3 = new CSS3DObject(domTag);
  iTagDomCss3.position.z = 2;
  iTagDomCss3.position.y = 9999;
  cssThreeObj.cssScene.add(iTagDomCss3);
  saveTipDom = iTagDomCss3;
}
/**
 * @函数功能: 加载图片
 * @param {*} url 地图路径
 * @出口参数:
 * @函数备注:
 */
function loadImage(url, ThreeObj) {
  new THREE.TextureLoader().load(url, (texture) => {
    const SIZE = 1000;
    const img = texture.image;
    let height = (img && img.height) || SIZE;
    let width = (img && img.width) || SIZE;
    height = (SIZE / width) * height;
    width = SIZE;
    const mat = new THREE.MeshBasicMaterial({
      map: texture,
      side: THREE.DoubleSide,
      transparent: true,
    });
    const geom = new THREE.PlaneGeometry(width, height);
    const mesh = new THREE.Mesh(geom, mat);

    ThreeObj.scene.add(mesh);
    ThreeObj.renderer.render(ThreeObj.scene, ThreeObj.camera); //执行渲染操作
  });
}
// /**
//  * @函数功能: 监听鼠标点击事件
//  * @param {*} event
//  * @出口参数:
//  * @函数备注:
//  */
// function onDocumentMouseUp(e,ThreeObj) {
//     console.log(e);

//     e.preventDefault();

//     var mouse3D = getMousePosition(e.clientX, e.clientY,ThreeObj);
//     console.log(mouse3D.x + ' ' + mouse3D.y + ' ' + mouse3D.z);
// }
// function getMousePosition(clientX, clientY,ThreeObj) {
//     var mouse2D = new THREE.Vector3();
//     var mouse3D = new THREE.Vector3();
//     const projector = new Projector();
//     mouse2D.x = (clientX / window.innerWidth) * 2 - 1;
//     mouse2D.y = -(clientY / window.innerHeight) * 2 + 1;
//     mouse2D.z = 0.5;
//     mouse3D = projector.unprojectVector(mouse2D.clone(), ThreeObj.camera);
//     return mouse3D;

// }
function render(obj, cssThreeObj) {
  cssThreeObj.cssRender.render(cssThreeObj.cssScene, obj.camera);
  obj.renderer.render(obj.scene, obj.camera); //执行渲染操作

  //   requestAnimationFrame(render(ThreeObj,cssThreeObj));
}
function animate() {
  render(ThreeObj, cssThreeObj);
  // setTimeout(()=>{
  requestAnimationFrame(animate);
  // },16)
}
/**
 * @函数功能: 将异步加载出的mesh添加监听时间
 * @param {*} cssThreeObj htmldom画布对象
 * @param {*} ThreeObj  three创建的画布对象
 * @出口参数:
 * @函数备注:
 */
function sethoveMesh(cssThreeObj, ThreeObj) {
  //异步执行后要将渲染出来的mesh模型添加移入实践
  for (let i = 0; i < cssThreeObj.cssScene.children.length; i++) {
    if (cssThreeObj.cssScene.children[i].isMesh) {
      objects.push(cssThreeObj.cssScene.children[i]);
    }
  }
  dragControls = new DragControls(
    objects,
    ThreeObj.camera,
    cssThreeObj.cssRender.domElement
  );
  // dragControls.removeEventListener("hoveron",function (event) {
  //   console.log(event);

  //   saveTipDom.element.innerHTML = `${event.object.devName}:${
  //     event.object.devStatus ? "在线" : "离线"
  //   }`;
  //   saveTipDom.position.x = event.object.position.x;
  //   saveTipDom.position.y = event.object.position.y + 20;
  //   saveTipDom.visible = true;
  // })
  dragControls.addEventListener("hoveron", function (event) {
    
    saveTipDom.element.innerHTML = `${event.object.devName}:${
      event.object.devStatus ?t('messages.onLine') : t('messages.offline')
    }`;
    saveTipDom.position.x = event.object.position.x;
    saveTipDom.position.y = event.object.position.y + 20;
    saveTipDom.visible = true;
  });
  //   dragControls.removeEventListener("hoveroff", function (event) {
  //   console.log(event);
  //   saveTipDom.position.x = 0;
  //   saveTipDom.position.y = 9999;
  //   saveTipDom.visible = false;
  // });
  dragControls.addEventListener("hoveroff", function (event) {
    saveTipDom.position.x = 0;
    saveTipDom.position.y = 9999;
    saveTipDom.visible = false;
  });

  dragControls.addEventListener("dragend", function (event:any) {
      //console.log(event.object.position);
      console.log(`
      "x":${event.object.position.x.toFixed(2)},
      "y":${event.object.position.y.toFixed(2)}
      `);
      
      
  });
}
/**
 * @函数功能: 获取点击地图坐标
 * @param {*} x 屏幕坐标x
 * @param {*} y 屏幕坐标y
 * @出口参数:
 * @函数备注:
 */
function getclickMap(x, y) {
  var vector = new THREE.Vector3(); //三维坐标对象
  vector.set(
    (x / map.value.clientWidth) * 2 - 1,
    -(y / map.value.clientHeight) * 2 + 1,
    0.5
  );
  vector.unproject(ThreeObj.camera);

  var raycasterMap = new THREE.Raycaster(
    ThreeObj.camera.position,
    vector.sub(ThreeObj.camera.position).normalize()
  );
  var intersectsMap = raycasterMap.intersectObjects(ThreeObj.scene.children);
  if (intersectsMap.length > 0) {
    var selected = intersectsMap[0]; //取第一个物体
    console.log("x坐标:" + selected.point.x);
    console.log("y坐标:" + selected.point.y);
    console.log("z坐标:" + selected.point.z);
  }
}
/**
 * @函数功能: 点击地图跳转对应大屏
 * @param {*} px 屏幕坐标x
 * @param {*} py 屏幕坐标y
 * @出口参数:
 * @函数备注:
 */
function goPage(px, py) {
  //屏幕坐标px、py转标准设备坐标x、y
  //width、height表示canvas画布宽高度
  const x = (px / map.value.clientWidth) * 2 - 1;
  const y = -(py / map.value.clientHeight) * 2 + 1;

  raycaster.setFromCamera(new THREE.Vector2(x, y), ThreeObj.camera);
  const intersects = raycaster.intersectObjects(ThreeObj.scene.children, true);
  routeDataSet.forEach((res) => {
    if (intersects[0].object.id2 == res.id) {
      storeMechanics.changePage(res.router);
      router.push({
        name: "Mechanicschild",
        params: {
          id: res.router,
        },
      });
    }
  });
}
onMounted(() => {
  console.log(store.iconList);
  
  //初始化场景
  ThreeObj = initThree(map.value.clientHeight, map.value.clientWidth);
  cssThreeObj = initCss3DScene(map.value.clientHeight, map.value.clientWidth);
  setTipDom(cssThreeObj);
  //添加控制场景元素
  cssThreeObj["controls"] = new OrbitControls(
    ThreeObj.camera,
    cssThreeObj.cssRender.domElement
  );
  ThreeObj["controls"] = new OrbitControls(
    ThreeObj.camera,
    ThreeObj.renderer.domElement
  );
  cssThreeObj["controls"].mouseButtons = {
    LEFT: THREE.MOUSE.PAN,
    MIDDLE: THREE.MOUSE.DOLLY,
    // RIGHT: THREE.MOUSE.PAN
  };
  ThreeObj["controls"].mouseButtons = {
    LEFT: THREE.MOUSE.PAN,
    MIDDLE: THREE.MOUSE.DOLLY,
    // RIGHT: THREE.MOUSE.PAN
  };
  //监听鼠标事件
  ThreeObj.controls.addEventListener("change", () => {
    ThreeObj.renderer.render(ThreeObj.scene, ThreeObj.camera);
    cssThreeObj.cssRender.render(cssThreeObj.cssScene, ThreeObj.camera);
  });
  cssThreeObj.controls.addEventListener("change", () => {
    ThreeObj.renderer.render(ThreeObj.scene, ThreeObj.camera);
    cssThreeObj.cssRender.render(cssThreeObj.cssScene, ThreeObj.camera);
  });
  //添加物品
  routeDataSet.forEach((res) => {
    ThreeObj.scene.add(
      setMesh(res.size, res.MaterialObj, res.id, res.position)
    );
  });

  //初始化地图数据
  loadImage(mapPng, ThreeObj);

  document.getElementsByClassName("cssrender")[0].addEventListener(
    "click",
    (e: any) => {
      index++;
      const px = e.offsetX;
      const py = e.offsetY;

      //点击获取坐标系
      getclickMap(px, py);
      //页面跳转-------------------------------------------------------------
      goPage(px, py);
      // onDocumentMouseUp(e,ThreeObj)
    },
    false
  );

  //渲染场景

  animate();
});
onUnmounted(() => {
  document.getElementsByClassName("cssrender")[0].remove();
});
</script>

<style module>
.threemap {
  /* width: 100%;
  height: 100%; */
  display: flex;
  background-color: #aaa;
}
</style>
<style scoped>
@import url("@/assets/css/iconfont.css");
.icon-blue {
  color: #10606c;
  /* animation: redstarton 2s infinite; */
  /* position: relative; */
  /* top: -15px; */
}
.icon-red {
  color:#10606c
}
.iconSize {
  font-size: 1.2rem;
  /* color: #fff; */
}
@keyframes redstarton {
  0% {
  }
  50% {
    /* text-shadow: #fff 1px 0 5px; */
    color: #10606c;
  }
  100% {
  }
}
</style>

<style>
.icon-blue {
  color: #88e76a;
  animation: redstarton 2s infinite;
  /* position: relative; */
  /* top: -15px; */
}
.icon-red {
  color:#e32b2b
}
</style>
