<template>
  <div>
    <div id="viewPort" :style="{height: containerHeight,width: containerWidth}"></div>
    <div ref="modelProcess" style="position: absolute;top: 10px;left: 2px;color: white">正在加载模型0%</div>
    <div style="display: none">
      <audio controls loop id="alarm">
        <source src="./libs/alarm.mp3" type="audio/mpeg">
      </audio>
      <audio controls id="clash">
        <source src="./libs/alarm.mp3" type="audio/mpeg">
      </audio>
    </div>
    <div>
    </div>
    <!--      <div class="viewOperationParent" id="viewOperationParent">-->
    <!--        <div style="display:inline;text-align: center;background: #074492" id="viewOperationChild">-->
    <!--          <div style="text-align: center">-->
    <!--            &lt;!&ndash;            <el-checkbox v-model="checked" style="margin-right: 5px;color: #fff">设定</el-checkbox>&ndash;&gt;-->
    <!--            <el-button v-for="(item, index) in cameraData" :id="'cameraViewBtn' + item.焦点代码" :key=index style="height: 36px;white-space:normal;">{{ item.焦点说明 }}</el-button>-->
    <!--            <button id="setView" style="width: 20px;height: 20px;padding: 0;margin: 0;background: transparent;border: none;cursor: pointer;"></button>-->
    <!--          </div>-->
    <!--        </div>-->
    <!--      </div>-->
  </div>
</template>

<script>

import * as THREE from 'three'
import Stats from 'three/examples/jsm/libs/stats.module.js'
import { VRButton } from './VR/VRButton.js'
import { XRControllerModelFactory } from 'three/examples/jsm/webxr/XRControllerModelFactory.js'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader'

import axios from 'axios'
import $ from 'jquery'
import * as TWEEN from 'three/examples/jsm/libs/tween.module.js'

import { DmtControl } from './js/DmtControl.js'
import { connect } from './js/websocketConnect.js'
import { connectMqtt } from './js/MqttConnect.js'
import { PlaySoundCommand } from './js/PlaySoundCommand.js'
// import { Vector3 } from 'three'
// THREE.Object3D.DefaultUp = new Vector3(0, 0, 1)

let controller1, controller2
let controllerGrip1, controllerGrip2
const group = new THREE.Group()
let marker, floor, baseReferenceSpace
// const modelList = ['Cell3-转台', 'R-2000iC-210F-robot1', 'R-2000iC-210F-robot4', 'R-2000iC-270F-robot2', 'R-2000iC-270F-robot3', 'robot1底座', 'robot2-夹爪1台', 'robot2-夹爪2-台',
//   'robot2-底座', 'robot3-底座', '加工件-存放台A', '加工件-存放台B', '加工件-存放台C', '安全防护', '辊道-1', '辊道', '平面']
const modelList = ['R-2000iC-210F-robot1', 'robot1底座', 'robot2-夹爪1台', 'robot2-夹爪2-台',
  'robot2-底座', 'robot3-底座', '平面']
let INTERSECTION
const tempMatrix = new THREE.Matrix4()
let stats
let container, clock, scene, camera, axesHelper, renderer, Plane
let modelCount = 0
const editor = {
  clock: null,
  robotInfo: {
    'B3FD789E-E018-4006-91AD-4824830E6557': {
      joint: {
        'J1': 999.99,
        'J2': 999.99,
        'J3': 999.99,
        'J4': 999.99,
        'J5': 999.99,
        'J6': 999.99
      },
      tcp: {
        'tx': 999.99,
        'ty': 999.99,
        'tz': 999.99,
        'rx': 999.99,
        'ry': 999.99,
        'rz': 999.99
      },
      speed: 100,
      alarm: [
        {
          'AlarmID': 2,
          'AlarmNumber': 78,
          'CauseAlarmID': 0,
          'CauseAlarmNumber': 0,
          'Severity': 0,
          'Time': '2020-03-12T15:34:18',
          'AlarmMessage': 'FILE-078 ﾗﾔｶｯｱｸｷﾝﾍ?ﾉ',
          'CauseAlarmMessage': '',
          'SeverityMessage': 'WARN'
        },
        {
          'AlarmID': 2,
          'AlarmNumber': 77,
          'CauseAlarmID': 0,
          'CauseAlarmNumber': 0,
          'Severity': 0,
          'Time': '2020-03-12T15:30:12',
          'AlarmMessage': 'FILE-077 ﾗﾔｶｯｱｸｷﾝｿｪﾊｼ (FRA:\\)',
          'CauseAlarmMessage': '',
          'SeverityMessage': 'WARN'
        },
        {
          'AlarmID': 76,
          'AlarmNumber': 125,
          'CauseAlarmID': 0,
          'CauseAlarmNumber': 0,
          'Severity': 34,
          'Time': '2020-03-12T15:27:06',
          'AlarmMessage': 'DNET-125 ｴﾓｶｯﾖ眞ｬｽﾓﾏﾐﾖﾃ: Bd 2',
          'CauseAlarmMessage': '',
          'SeverityMessage': 'PAUSE.G'
        }
      ]
    },
    'A769F461-4011-46A4-BBC2-2AFB39EFD9C2': {
      joint: {
        'J1': 888.88,
        'J2': 888.88,
        'J3': 888.88,
        'J4': 888.88,
        'J5': 888.88,
        'J6': 888.88
      },
      tcp: {
        'tx': 888.88,
        'ty': 888.88,
        'tz': 888.88,
        'rx': 888.88,
        'ry': 888.88,
        'rz': 888.88
      },
      speed: 99,
      alarm: [
        {
          'AlarmID': 2,
          'AlarmNumber': 78,
          'CauseAlarmID': 0,
          'CauseAlarmNumber': 0,
          'Severity': 0,
          'Time': '2020-03-12T15:34:18',
          'AlarmMessage': 'FILE-078 ﾗﾔｶｯｱｸｷﾝﾍ?ﾉ',
          'CauseAlarmMessage': '',
          'SeverityMessage': 'WARN'
        },
        {
          'AlarmID': 2,
          'AlarmNumber': 77,
          'CauseAlarmID': 0,
          'CauseAlarmNumber': 0,
          'Severity': 0,
          'Time': '2020-03-12T15:30:12',
          'AlarmMessage': 'FILE-077 ﾗﾔｶｯｱｸｷﾝｿｪﾊｼ (FRA:\\)',
          'CauseAlarmMessage': '',
          'SeverityMessage': 'WARN'
        },
        {
          'AlarmID': 76,
          'AlarmNumber': 125,
          'CauseAlarmID': 0,
          'CauseAlarmNumber': 0,
          'Severity': 34,
          'Time': '2020-03-12T15:27:06',
          'AlarmMessage': 'DNET-125 ｴﾓｶｯﾖ眞ｬｽﾓﾏﾐﾖﾃ: Bd 2',
          'CauseAlarmMessage': '',
          'SeverityMessage': 'PAUSE.G'
        }
      ]
    },
    '04A6D8F9-7019-4C92-8845-B3CFDDF4A433': {
      joint: {
        'J1': 777.77,
        'J2': 777.77,
        'J3': 777.77,
        'J4': 777.77,
        'J5': 777.77,
        'J6': 777.77
      },
      tcp: {
        'tx': 777.77,
        'ty': 777.77,
        'tz': 777.77,
        'rx': 777.77,
        'ry': 777.77,
        'rz': 777.77
      },
      speed: 98,
      alarm: [
        {
          'AlarmID': 2,
          'AlarmNumber': 78,
          'CauseAlarmID': 0,
          'CauseAlarmNumber': 0,
          'Severity': 0,
          'Time': '2020-03-12T15:34:18',
          'AlarmMessage': 'FILE-078 ﾗﾔｶｯｱｸｷﾝﾍ?ﾉ',
          'CauseAlarmMessage': '',
          'SeverityMessage': 'WARN'
        },
        {
          'AlarmID': 2,
          'AlarmNumber': 77,
          'CauseAlarmID': 0,
          'CauseAlarmNumber': 0,
          'Severity': 0,
          'Time': '2020-03-12T15:30:12',
          'AlarmMessage': 'FILE-077 ﾗﾔｶｯｱｸｷﾝｿｪﾊｼ (FRA:\\)',
          'CauseAlarmMessage': '',
          'SeverityMessage': 'WARN'
        },
        {
          'AlarmID': 76,
          'AlarmNumber': 125,
          'CauseAlarmID': 0,
          'CauseAlarmNumber': 0,
          'Severity': 34,
          'Time': '2020-03-12T15:27:06',
          'AlarmMessage': 'DNET-125 ｴﾓｶｯﾖ眞ｬｽﾓﾏﾐﾖﾃ: Bd 2',
          'CauseAlarmMessage': '',
          'SeverityMessage': 'PAUSE.G'
        }
      ]
    },
    'B2BF5C42-B6ED-46D8-A7C3-046968D39805': {
      joint: {
        'J1': 666.66,
        'J2': 666.66,
        'J3': 666.66,
        'J4': 666.66,
        'J5': 666.66,
        'J6': 666.66
      },
      tcp: {
        'tx': 666.66,
        'ty': 666.66,
        'tz': 666.66,
        'rx': 666.66,
        'ry': 666.66,
        'rz': 666.66
      },
      speed: 97,
      alarm: [
        {
          'AlarmID': 2,
          'AlarmNumber': 78,
          'CauseAlarmID': 0,
          'CauseAlarmNumber': 0,
          'Severity': 0,
          'Time': '2020-03-12T15:34:18',
          'AlarmMessage': 'FILE-078 ﾗﾔｶｯｱｸｷﾝﾍ?ﾉ',
          'CauseAlarmMessage': '',
          'SeverityMessage': 'WARN'
        },
        {
          'AlarmID': 2,
          'AlarmNumber': 77,
          'CauseAlarmID': 0,
          'CauseAlarmNumber': 0,
          'Severity': 0,
          'Time': '2020-03-12T15:30:12',
          'AlarmMessage': 'FILE-077 ﾗﾔｶｯｱｸｷﾝｿｪﾊｼ (FRA:\\)',
          'CauseAlarmMessage': '',
          'SeverityMessage': 'WARN'
        },
        {
          'AlarmID': 76,
          'AlarmNumber': 125,
          'CauseAlarmID': 0,
          'CauseAlarmNumber': 0,
          'Severity': 34,
          'Time': '2020-03-12T15:27:06',
          'AlarmMessage': 'DNET-125 ｴﾓｶｯﾖ眞ｬｽﾓﾏﾐﾖﾃ: Bd 2',
          'CauseAlarmMessage': '',
          'SeverityMessage': 'PAUSE.G'
        }
      ]
    }
  },
  showTagList: [{
    title: '工件：QY16KC',
    ModelId: 'A113AD62-9CE7-4ACF-8D0C-8E8A597A8768',
    object: null
  }],
  ip: '',
  WeldLight1: '',
  WeldLightVisible1: false,
  WeldLight2: '',
  WeldLightVisible2: false,
  scene: null,
  objectIdUUidMap: new Map(),
  opname: '',
  connectType: 1,
  BSport: '',
  IsAllowConnect: true,
  service: axios.create({
    baseURL: './submit/MESCommonBase.ashx',
    timeout: 1500000 // 请求超时时间
  }),
  selected: null,
  socket: null,
  mqttClient: {
    connected: false
  },
  ProjectCode: null,
  sceneConfig: null,
  resourcesTree: null,
  attachments: null,
  resources: null,
  cameraState: null,
  cameraStateAll: [],
  isOk: false,
  objectIdSet: new Map(),
  animOperations: null,
  CraftList: {},
  moveTrigger: null,
  camera: null,
  cameraPosition: 10,
  currentButton: 1,
  cameraControls: null,
  TagActList: {}, // 存放tag对应的类型
  worker: {}, // 播放工艺的线程
  RotationWorker: {}, // 自传工艺的线程
  ModelRotateWorker: {}, // 自传工艺的的状态数据
  rotateSpeed: 5 * Math.PI / 180,
  getObjectById: null, // 方法 根据ModelId获取模型
  solveAttachModel: null, // 方法 处理attach问题
  removeObject: null, // 方法 移除模型
  setModelWireFrame: null, // 方法 设置线框
  setTransparent: null, // 方法 设置透明
  showMessage: null, // 方法 显示消息
  playSoundCommand: new PlaySoundCommand(), //  方法 警告
  attachList: new Map(), // 记录attach列表
  objMaterial: new Map(),
  WareHouseList: [],
  WareHouse: new Map(), // 立库库存表
  WareHouseBasicModel: new Map(), // 立库库存基础 零件模型需要命名为warehousepart1-100 立库定位模型需要命名为warehouse1000-1009
  ProtocolIdentifiers: {
    Robot_7: 'Robot_7',
    Device_3: 'Device_3',
    Agv_3: 'Agv_3',
    Device_1: 'Device_1',
    FirstPosition: 'FirstPosition',
    WareHousePart: 'WareHousePart',
    Robot_6: 'Robot_6',
    RobotTcp: 'RobotTcp',
    DrawPath: 'DrawPath',
    ReLoadData: 'ReLoadData',
    PlayAct: 'PlayAct',
    CraftCurrOperation: 'CraftCurrOperation',
    Position: 'Position',
    Select: 'Select',
    DragMove: 'DragMove',
    ModelTransparent: 'ModelTransparent',
    Visible: 'Visible',
    Frames: 'Frames',
    ModelRotation: 'ModelRotation',
    GoHome: 'GoHome',
    GetJointAxisInfo: 'GetJointAxisInfo',
    GetDeviceBaseTool: 'GetDeviceBaseTool',
    GetJointValue: 'GetJointValue',
    C_B_ImportModel: 'C_B_ImportModel',
    SendURDF: 'SendURDF',
    SendDeviceJson: 'SendDeviceJson',
    GetDeviceJson: 'GetDeviceJson',
    SendMotionInfo: 'SendMotionInfo',
    C_B_ImportLayout: 'C_B_ImportLayout',
    GetPoseLocation: 'GetPoseLocation',
    C_B_SetProjectCode: 'C_B_SetProjectCode',
    C_B_TagIDTrigger: 'C_B_TagIDTrigger',
    C_B_ReLoad_TagIDHandler: 'C_B_ReLoad_TagIDHandler',
    C_B_SetCurrSignalList: 'C_B_SetCurrSignalList',
    SendClearModelInfo: 'SendClearModelInfo',
    C_B_SaveProjectSimulationData: 'C_B_SaveProjectSimulationData',
    C_B_GetProjectSimulationData: 'C_B_GetProjectSimulationData',
    C_B_KinematicsEditing: 'C_B_KinematicsEditing',
    C_B_SaveModel: 'C_B_SaveModel',
    C_B_ObjectAlarm: 'C_B_ObjectAlarm',
    JointMoveTo: 'JointMoveTo' // DT|JointMoveTo|modelCode|{"J1":"1","J2":"2","J3":"3","J4":"4","J5":"5","J6":"6","J7":"7","J8":"8","J9":"9"}
  },
  craftPlaySolveType: {
    visible: 'visible',
    rotation: 'rotation',
    craft: 'craft',
    signalwrite: 'signalwrite',
    wait: 'wait',
    FrameData: 'FrameData',
    attach: 'attach',
    warning: 'warning'
  },
  FrameOperation: {
    playCraft: true,
    visibleObject: true,
    rotationObject: true,
    writeSignal: true,
    waitSignal: true,
    attach: true,
    warning: true
  },
  signalSolveType: {
    visible: 'visible',
    rotation: 'rotation',
    craft: 'craft',
    targetLocation: 'targetlocation',
    attach: 'attach',
    warning: 'warning'
  }
}
// eslint-disable-next-line no-unused-vars
let ModelListTransParentList = []
const ModelList = []
const ModelListId = []
// eslint-disable-next-line no-unused-vars
const timer = null
// eslint-disable-next-line no-unused-vars
const lastIntersectModel = null
// eslint-disable-next-line no-unused-vars
const onUpPosition = new THREE.Vector2()

var raycaster = new THREE.Raycaster()
var mouse = new THREE.Vector2()
window.editor = editor

export default {
  name: 'DemoVR',
  props: {
    containerHeight: {
      type: String,
      default: '100vh'
    },
    containerWidth: {
      type: String,
      default: '100vw'
    }
  },
  mounted() {
    editor.objectIdSet = new Map()
    editor.objMaterial = new Map()
    editor.attachList = new Map()
    this.getConfig().then(res => {
      if (Object.hasOwnProperty.call(res, 'robotList')) {
        editor.robotList = res.robotList
      }
      if (Object.hasOwnProperty.call(res, 'WareHouseList')) {
        editor.WareHouseList = res.WareHouseList
      }
      if (Object.hasOwnProperty.call(res, 'transParentList')) {
        ModelListTransParentList = res.transParentList
      }
      if (Object.hasOwnProperty.call(res, 'connectType')) {
        editor.connectType = res.connectType
      }
      editor.mqttHost = res.MQTTHost
      editor.mqttPort = res.MQTTPort
      editor.ip = res.webSocketIp
      editor.opname = res.webSocketOpName
      editor.BSport = res.webSocketBSport
      editor.rootIp = res.NodeRootIp
      this.getProjectConfig()
    })
  },
  methods: {
    getConfig() {
      return new Promise((resolve, reject) => {
        axios.get('./DMT_WEB/config/config.json').then(res => {
          const configData = res.data
          resolve(configData)
        }).catch(err => {
          reject(err)
        })
      })
    },
    /**
       * 获取项目配置文件，用于初始隐藏模型
       */
    getProjectConfig() {
      const P1 = new Promise(function(resolve, reject) {
        axios({
          method: 'get',
          url: './DMT_WEB/models/DTDATA.json'
        }).then((res) => {
          editor.animOperations = {}
          editor.moveTrigger = {}
          res.data.forEach(n => {
            Object.keys(n).forEach(function(key) {
              /**
                 * 获取播放数据并解析数据
                 */
              if (key === 'OperationTree') {
                n[key].forEach(CraftData => {
                  editor.CraftList[CraftData.CraftCode] = {}
                  editor.CraftList[CraftData.CraftCode]['CraftName'] = CraftData.CraftName
                  editor.CraftList[CraftData.CraftCode]['Varieties'] = CraftData.Varieties
                  editor.CraftList[CraftData.CraftCode]['CurrPlay'] = CraftData.CurrPlay
                  if (CraftData.CraftPlayData.length < 2) {
                    editor.animOperations[CraftData.CraftCode] = ''
                  } else {
                    editor.animOperations[CraftData.CraftCode] = JSON.parse(CraftData.CraftPlayData)
                  }
                  editor.moveTrigger[CraftData.CraftCode] = {
                    moveStatus: 0,
                    myVarSetInterval: null,
                    doAnimation: false,
                    currentFrame: 0,
                    pausedFrame: 0,
                    animOperations: editor.animOperations[CraftData.CraftCode],
                    simPaceTime: 20,
                    moveStatusPosition: 0
                  }
                })
              }
              /**
                 * HandlerType: 1:显隐,2:自转,3行为
                 * HandlerCode: 模型或者工艺代码
                 * HandlerValue: 显隐：0/1 ,自传：正负转速&axis,行为暂停播放：0/1
                 * TagValue:信号值
                 */
              if (key === 'TagTriggerHandler') {
                n[key].forEach(TagActListValue => {
                  if (editor.TagActList[TagActListValue.TagID]) {
                    editor.TagActList[TagActListValue.TagID].push({
                      HandlerType: TagActListValue.HandlerType,
                      HandlerCode: TagActListValue.HandlerCode,
                      HandlerValue: TagActListValue.HandlerValue,
                      TagValue: TagActListValue.TagValue,
                      JointType: TagActListValue.JointType,
                      Axis: TagActListValue.Axis,
                      Flip: TagActListValue.Flip,
                      Value: TagActListValue.Value,
                      ValueFactor: TagActListValue.ValueFactor
                    })
                  } else {
                    editor.TagActList[TagActListValue.TagID] = []
                    editor.TagActList[TagActListValue.TagID].push({
                      HandlerType: TagActListValue.HandlerType,
                      HandlerCode: TagActListValue.HandlerCode,
                      HandlerValue: TagActListValue.HandlerValue,
                      TagValue: TagActListValue.TagValue,
                      JointType: TagActListValue.JointType,
                      Axis: TagActListValue.Axis,
                      Flip: TagActListValue.Flip,
                      Value: TagActListValue.Value,
                      ValueFactor: TagActListValue.ValueFactor
                    })
                  }
                })
              }
            })
          })
          resolve(1)
        })
      })
      const P2 = new Promise(function(resolve, reject) {
        axios({
          method: 'get',
          url: './DMT_WEB/models/RobotPlan_Process.json'
        }).then((res) => {
          editor.sceneConfig = res.data.sceneConfig // 场景配置
          editor.attachments = res.data.attachments // 附加物体
          editor.resources = res.data.resources // 场景模型资源
          editor.resourcesTree = res.data.resourcesTree // 模型树
          editor.cameraState = res.data.cameraState // 场景相机位置
          editor.ProjectCode = res.data.ProjectCode // 项目代码
          editor.resourcesTree.forEach(res => {
            if (res.treeType === 'OriginModel') {
              ModelList.push(res.name)
            }
          })
          editor.resources.forEach(res => {
            editor.objectIdUUidMap.set(res.id, res)
          })
          editor.attachments.forEach(res => {
            editor.attachList.set(res.RootId, res.attachList)
          })
          resolve(1)
        }).catch((error) => { console.log(error) })
      })
      Promise.all([P1, P2]).then(res => {
        this.init()
        // this.getCameraData()
      })
    },
    /**
       * @name: ZhangShun
       * @date: 2022/9/24
       * @explain: 初始三维化场景
       */
    init() {
      clock = new THREE.Clock()
      editor.clock = clock
      const scope = this
      container = document.getElementById('viewPort')
      stats = new Stats()
      container.appendChild(stats.dom)
      scene = this.initScene()
      editor.scene = scene

      camera = this.initCamera()
      editor.camera = camera

      group.rotation.x = -0.5 * Math.PI
      group.position.y = -0.4
      scene.add(group)

      axesHelper = new THREE.AxesHelper(1)
      scene.add(axesHelper)

      scene.add(new THREE.HemisphereLight(0x606060, 0x404040))
      const light = new THREE.DirectionalLight(0xffffff)
      light.position.set(1, 1, 1).normalize()
      scene.add(light)

      marker = new THREE.Mesh(
        new THREE.CircleGeometry(0.25, 32).rotateX(-Math.PI / 2),
        new THREE.MeshBasicMaterial({ color: 0x808080 })
      )
      scene.add(marker)

      raycaster = new THREE.Raycaster()

      renderer = new THREE.WebGLRenderer({
        antialias: true,
        alpha: true,
        logarithmicDepthBuffer: true,
        preserveDrawingBuffer: true
      })
      renderer.setPixelRatio(window.devicePixelRatio)
      renderer.setSize(container.clientWidth, container.clientHeight)
      renderer.outputEncoding = THREE.sRGBEncoding
      renderer.setClearColor(0x666666, 0)
      renderer.toneMapping = THREE.ACESFilmicToneMapping
      renderer.toneMappingExposure = 0.8
      renderer.shadowMap.enabled = true
      renderer.hadowMapEnabled = true
      renderer.shadowMap.type = THREE.PCFSoftShadowMap
      renderer.textureEncoding = THREE.sRGBEncoding
      renderer.xr.addEventListener('sessionstart', function() {
        baseReferenceSpace = renderer.xr.getReferenceSpace()
      })
      renderer.xr.enabled = true
      container.appendChild(renderer.domElement)
      window.addEventListener('resize', this.onWindowResize, false)

      editor.showMessage = function(message, type, time = 2000) {
        scope.$message({
          message: message,
          type: type,
          duration: time,
          center: true
        })
      }
      editor.getObjectById = function(ModelId) {
        let currentModel = null
        const currentModelData = editor.objectIdSet.get(ModelId)
        if (currentModelData) currentModel = currentModelData.object
        return currentModel
      }
      editor.solveAttachModel = function(ModelId, attach = true) {
        const attachList = editor.attachList
        attachList.forEach(function(value, key) {
          const RootModel = editor.getObjectById(key)
          if (RootModel) {
            for (const attachData of value) {
              const attachModel = editor.getObjectById(attachData.ModelId)
              let parentObject = null
              attachData['ParentId'] ? parentObject = editor.getObjectById(attachData.ParentId) : parentObject = editor.scene
              if (attachModel && parentObject) {
                if (attach) {
                  RootModel.attach(attachModel)
                } else {
                  parentObject.attach(attachModel)
                }
              }
            }
          }
        })
      }
      editor.removeObject = function(object) {
        if (object === null) return
        if (object.parent === null) return
        object.parent.remove(object)
      }
      editor.setModelWireFrame = function(currentObject, WireframeValue) {
        currentObject.traverse(obj => {
          if (obj instanceof THREE.Mesh) {
            obj.material = editor.objMaterial.get(obj.id).clone()
            obj.material['wireframe'] = WireframeValue
            obj.material.needsUpdate = true
          }
        })
      }
      editor.setTransparent = function(ModelId, Opacity = 0.3) {
        new Promise((resolve, reject) => {
          const TransModel = editor.getObjectById(ModelId)
          if (!TransModel) {
            console.warn('模型不存在！（setTransparent）')
            reject(false)
          } else {
            TransModel.traverse(obj => {
              if (obj.material) {
                const material_yuan = editor.objMaterial.get(obj.id).clone()
                obj.material = material_yuan
                if (Opacity !== 1) {
                  obj.material = new THREE.MeshStandardMaterial({
                    color: material_yuan.color,
                    side: 2,
                    transparent: true,
                    opacity: Opacity
                  })
                }
              }
            })
            resolve(true)
          }
        })
      }

      // region 手柄控制器的设定
      controller1 = renderer.xr.getController(0)
      controller1.addEventListener('selectstart', this.onSelectStart)
      controller1.addEventListener('selectend', this.onSelectEnd)
      controller1.addEventListener('connected', function(event) {
        this.add(scope.buildController(event.data))
      })
      controller1.addEventListener('disconnected', function() {
        this.remove(this.children[ 0 ])
      })
      scene.add(controller1)

      controller2 = renderer.xr.getController(1)
      controller2.addEventListener('selectstart', this.onSelectStart)
      controller2.addEventListener('selectend', this.onSelectEnd)
      controller2.addEventListener('connected', function(event) {
        this.add(scope.buildController(event.data))
      })
      controller2.addEventListener('disconnected', function() {
        this.remove(this.children[ 0 ])
      })
      scene.add(controller2)

      // The XRControllerModelFactory will automatically fetch controller models
      // that match what the user is holding as closely as possible. The models
      // should be attached to the object returned from getControllerGrip in
      // order to match the orientation of the held device.

      const controllerModelFactory = new XRControllerModelFactory()

      controllerGrip1 = renderer.xr.getControllerGrip(0)
      controllerGrip1.add(controllerModelFactory.createControllerModel(controllerGrip1))
      scene.add(controllerGrip1)

      controllerGrip2 = renderer.xr.getControllerGrip(1)
      controllerGrip2.add(controllerModelFactory.createControllerModel(controllerGrip2))
      scene.add(controllerGrip2)

      // #endregion

      // region 相机控制器的设定
      editor.cameraControls = new DmtControl(editor.camera, renderer.domElement)
      editor.cameraControls.listenToKeyEvents(window) // optional
      editor.cameraControls.update()
      // endregion

      // region 加载模型
      const pmremGenerator = new THREE.PMREMGenerator(renderer)
      pmremGenerator.compileEquirectangularShader()
      const loader = new GLTFLoader().setPath('./DMT_WEB/models/')
      const dracoLoader = new DRACOLoader()
      new RGBELoader().setDataType(THREE.FloatType)
        .load('./DMT_WEB/assets/venice_sunset_1k.hdr', function(texture) {
          scene.environment = pmremGenerator.fromEquirectangular(texture).texture
          scene.background = new THREE.Color('#081f48')
          texture.dispose()
          pmremGenerator.dispose()
        })
      dracoLoader.setDecoderPath('./DMT_WEB/draco/')
      loader.setDRACOLoader(dracoLoader)
      for (let i = 0; i < ModelList.length; i++) {
        loader.load(ModelList[i] + '.glb', function(gltf) {
          const currentModel = gltf.scene.children[0]
          if (currentModel.name === '平面') {
            floor = currentModel
          }
          currentModel.traverse(child => {
            if (child['material']) {
              child['material'].metalness = 1
              editor.objMaterial.set(child.id, child['material'])
            }
          })
          group.add(currentModel)
          scope.setObjectByConfig(currentModel)
          ModelListId.push(gltf.scene.id)
          modelCount += 1
          scope.$refs.modelProcess.innerText = '正在加载模型' + (modelCount / ModelList.length * 100).toFixed(2) + '%'
          if (modelCount === ModelList.length) {
            container.appendChild(VRButton.createButton(renderer))
            scope.$refs.modelProcess.style.display = 'none'
            scope.lookObject(scene)
            scope.setModelSates()
            scope.connectService()
          }
        }, (xhr) => {
          // eslint-disable-next-line handle-callback-err
        }, (error) => {
          modelCount += 1
          console.log(`加载模型${ModelList[i].ModelName}出错!`)
          if (modelCount === ModelList.length) {
            container.appendChild(VRButton.createButton(renderer))
            scope.$refs.modelProcess.style.display = 'none'
            scope.lookObject(scene)
            scope.setModelSates()
            scope.connectService()
          }
        })
      }
      // endregion
      this.animate()
      this.render()
    },
    /**
       * @name: ZhangShun
       * @date: 2022/9/24
       * @explain: 初始化场景
       */
    initScene() {
      const sceneInit = new THREE.Scene()
      sceneInit.background = new THREE.Color(0x505050)
      return sceneInit
    },

    /**
       * @name: ZhangShun
       * @date: 2022/9/24
       * @explain: 初始化相机
       */
    initCamera() {
      const cameraInit = new THREE.PerspectiveCamera(50, container.clientWidth / container.clientHeight, 0.01, 10000)
      cameraInit.position.set(editor.cameraPosition, editor.cameraPosition, editor.cameraPosition)
      cameraInit.position.set(5, 5, 9)
      return cameraInit
    },

    /**
       * @name: ZhangShun
       * @date: 2022/9/24
       * @explain: 手柄扳机键按下
       */
    onSelectStart(event) {
      console.log('onSelectStart', event)
      event.target.userData.isSelecting = true
    },
    /**
       * @name: ZhangShun
       * @date: 2022/9/24
       * @explain: 手柄扳机键松开
       */
    onSelectEnd(event) {
      console.log('onSelectEnd', event)
      event.target.userData.isSelecting = false

      if (INTERSECTION) {
        const offsetPosition = { x: -INTERSECTION.x, y: -INTERSECTION.y, z: -INTERSECTION.z, w: 1 }
        const offsetRotation = new THREE.Quaternion()
        // eslint-disable-next-line no-undef
        const transform = new XRRigidTransform(offsetPosition, offsetRotation)
        const teleportSpaceOffset = baseReferenceSpace.getOffsetReferenceSpace(transform)
        renderer.xr.setReferenceSpace(teleportSpaceOffset)
      }
    },

    /**
       * 创建手柄控制器
       *
       */
    buildController(data) {
      let geometry, material
      switch (data.targetRayMode) {
        case 'tracked-pointer':
          geometry = new THREE.BufferGeometry()
          geometry.setAttribute('position', new THREE.Float32BufferAttribute([0, 0, 0, 0, 0, -1], 3))
          geometry.setAttribute('color', new THREE.Float32BufferAttribute([0.5, 0.5, 0.5, 0, 0, 0], 3))
          material = new THREE.LineBasicMaterial({ vertexColors: true, blending: THREE.AdditiveBlending })
          return new THREE.Line(geometry, material)
        case 'gaze':
          geometry = new THREE.RingGeometry(0.02, 0.04, 32).translate(0, 0, -1)
          material = new THREE.MeshBasicMaterial({ opacity: 0.5, transparent: true })
          return new THREE.Mesh(geometry, material)
      }
    },

    /**
       * @name: ZhangShun
       * @date: 2022/9/24
       * @explain: 自适应窗口尺寸
       */
    onWindowResize() {
      camera.aspect = container.clientWidth / container.clientHeight
      camera.updateProjectionMatrix()
      renderer.setSize(container.clientWidth, container.clientHeight)
    },

    animate() {
      // this.render()
      // requestAnimationFrame(this.animate)
      renderer.setAnimationLoop(this.render)
    },

    render() {
      TWEEN.update()
      renderer.render(scene, camera)
      this.vrTeleport()
      stats.update()
    },
    /**
       * @name: ZhangShun
       * @date: 2022/9/24
       * @explain: VR传送瞬移功能
       */
    vrTeleport() {
      INTERSECTION = undefined
      if (controller1.userData.isSelecting === true) {
        tempMatrix.identity().extractRotation(controller1.matrixWorld)
        raycaster.ray.origin.setFromMatrixPosition(controller1.matrixWorld)
        raycaster.ray.direction.set(0, 0, -1).applyMatrix4(tempMatrix)
        const intersects = raycaster.intersectObjects([floor])
        if (intersects.length > 0) {
          INTERSECTION = intersects[ 0 ].point
        }
      } else if (controller2.userData.isSelecting === true) {
        tempMatrix.identity().extractRotation(controller2.matrixWorld)
        raycaster.ray.origin.setFromMatrixPosition(controller2.matrixWorld)
        raycaster.ray.direction.set(0, 0, -1).applyMatrix4(tempMatrix)
        const intersects = raycaster.intersectObjects([floor])
        if (intersects.length > 0) {
          INTERSECTION = intersects[ 0 ].point
        }
      }
      if (INTERSECTION) {
        marker.position.copy(INTERSECTION)
        marker.position.y += 0.01
      }
      marker.visible = INTERSECTION !== undefined
    },

    // region 自定义功能
    /**
       * 根据有配置文件设置模型初始化属性
       * @param object
       */
    setObjectByConfig(object) {
      const objectId = object.userData['ModelId']
      const objectResource = editor.objectIdUUidMap.get(objectId)
      if (objectResource) {
        object.position.copy(
          new THREE.Vector3(parseFloat(objectResource.location.position.x),
            parseFloat(objectResource.location.position.y),
            parseFloat(objectResource.location.position.z)
          ))
        object.quaternion.copy(
          new THREE.Quaternion(parseFloat(objectResource.location.quaternion.x),
            parseFloat(objectResource.location.quaternion.y),
            parseFloat(objectResource.location.quaternion.z),
            parseFloat(objectResource.location.quaternion.w)
          ))
        object.visible = Boolean(parseInt(objectResource.visible))
      }
    },
    /**
       * 连接方式选择
       */
    connectService() {
      switch (editor.connectType) {
        case 1:
          connect(editor)
          break
        case 2:
          connectMqtt(editor)
          break
        default:
          break
      }
    },
    drawWeldLight() {
      const geometry = new THREE.BufferGeometry()
      const vertices = []
      const textureLoader = new THREE.TextureLoader()
      const sprite1 = textureLoader.load('./css/lensflare0.png')
      const x = 0
      const y = 0.3
      const z = -0.07
      const materials = []
      vertices.push(x, y, z)
      geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3))
      const parameters = [
        [[1.0, 1, 1], sprite1, 50]
      ]
      const sprite = parameters[ 0 ][ 1 ]
      const size = parameters[ 0 ][ 2 ]

      materials[ 0 ] = new THREE.PointsMaterial({ size: size, map: sprite, blending: THREE.AdditiveBlending, depthTest: false, transparent: true })
      return new THREE.Points(geometry, materials[0])
    },
    /**
       * 解析模型
       * @param object
       */
    lookObject(object) {
      object.traverse(function(child) {
        if (!child) return
        // 避免modelId重复
        if (Object.hasOwnProperty.call(child.userData, 'ModelId')) {
          if (editor.objectIdSet.has(child.userData['ModelId'])) {
            child.userData['ModelId'] = child.uuid
            editor.objectIdSet.set(child.uuid, {
              ModelId: child.id,
              Name: child.name,
              position: JSON.parse(JSON.stringify(child.position)),
              rotation: JSON.parse(JSON.stringify(child.rotation)),
              quaternion: JSON.parse(JSON.stringify(child.quaternion)),
              object: child,
              matrix: child.matrix.clone()
            })
          } else {
            editor.objectIdSet.set(child.userData['ModelId'], {
              ModelId: child.id,
              Name: child.name,
              position: JSON.parse(JSON.stringify(child.position)),
              rotation: JSON.parse(JSON.stringify(child.rotation)),
              quaternion: JSON.parse(JSON.stringify(child.quaternion)),
              object: child,
              matrix: child.matrix.clone()
            })
          }
        }
      })
      for (const robotListInfo in editor.robotList) {
        for (const info of editor.robotList[robotListInfo]) {
          info.object = editor.getObjectById(info.ModelId)
          info.matrix = info.object ? info.object.matrix.clone() : null
          info.lastValue = null
        }
      }
    },
    /**
       * 获取预置焦点
       */
    getCameraData() {
      var param = []
      param[0] = ['ProjectCode', editor.ProjectCode]
      var Data = this.CreateData('3', 'select * from dbo.[基础数据_焦点预置]', param)
      this.ExecDatabase(Data).then(response => {
        this.cameraData = response.data
        // this.setViewCamera()
      })
    },
    /**
       * 点击后 到达预置焦点
       */
    setViewCamera() {
      if (this.cameraData.length === 0) return
      const scope = this
      const viewOperation = document.getElementById('viewOperationParent')
      const viewOperationChild = document.getElementById('viewOperationChild')
      viewOperation.onmouseover = function() {
        viewOperationChild.style.display = 'block'
      }
      viewOperation.onmouseout = function() {
        viewOperationChild.style.display = 'none'
      }
      setTimeout(() => {
        for (const info of this.cameraData) {
          $('#cameraViewBtn' + info.焦点代码).on('click', function(e) {
            const data = JSON.parse(info.焦点位置)
            const target = data.target
            const position = data.position
            const zoom0 = data.zoom0
            const id = info.焦点代码
            $('#cameraViewBtn' + info.焦点代码).css({ 'background': '#00893d', 'color': '#fff' })
            editor.cameraControls.resetState(target, position, zoom0)
            for (const infoColor of scope.cameraData) {
              if (id !== infoColor.焦点代码) {
                $('#cameraViewBtn' + infoColor.焦点代码).css({ 'background': '#fff', 'color': '#606266' })
              }
            }
          })
        }
      }, 1000)
    },

    getMousePosition(dom, x, y) {
      const rect = dom.getBoundingClientRect()
      return [(x - rect.left) / rect.width, (y - rect.top) / rect.height]
    },
    ondblclick(event) {
      const array = this.getMousePosition(container, event.clientX, event.clientY)
      onUpPosition.fromArray(array)
      let intersects = this.getIntersects(onUpPosition, editor.scene.children)
      intersects = intersects.filter(res => {
        return res.object.visible
      })
      if (intersects.length > 0) {
        const rootObjId = intersects[0].object.userData['RootId']
        editor.selected = editor.getObjectById(rootObjId)
        this.sendClickModel(editor.selected)
      } else {
        editor.selected = null
        this.sendClickModel(null)
      }
    },
    onMouseMove(event) {
      // const array = this.getMousePosition(container, event.clientX, event.clientY)
      // onUpPosition.fromArray(array)
      // if (!timer) {
      //   timer = setTimeout(() => {
      //     let intersects = this.getIntersects(onUpPosition, editor.scene.children)
      //     intersects = intersects.filter(res => {
      //       return res.object.visible
      //     })
      //     if (intersects.length > 0) {
      //       if (lastIntersectModel !== intersects[0]) {
      //         if (['6E90DC77-8E67-46CF-8B70-319D62E748E3', '2ED26E76-CD2C-4325-8DBA-7B54D9A4B81D'].indexOf(intersects[0].object.userData['ModelId']) !== -1) {
      //           const rootObjId = intersects[0].object.userData['RootId']
      //           editor.selected = editor.getObjectById(rootObjId)
      //         } else {
      //           editor.selected = null
      //         }
      //       }
      //     } else {
      //       editor.selected = null
      //     }
      //     clearTimeout(timer)
      //     timer = null
      //   }, 200)
      // }
      // updateTag(editor.selected, 'showText')
      // updateTag(part2, 'showText2')
    },
    getIntersects(point, objects) {
      mouse.set((point.x * 2) - 1, -(point.y * 2) + 1)
      raycaster.setFromCamera(mouse, camera)
      return raycaster.intersectObjects(objects, true)
    },
    sendCameraState(state) {
      this.$emit('changeCameraState', state)// 自定义事件  传递值“子向父组件传值”
    },
    sendClickModel(object) {
    },
    updatePosition() {
      if (editor.selected) {
        const targetPosition = editor.selected.getWorldPosition(new THREE.Vector3()).clone().project(camera)
        const halfWidth = window.innerWidth / 2
        const halfHeight = window.innerHeight / 2
        const position = {
          left: targetPosition.x * halfWidth + halfWidth - 200,
          top: -targetPosition.y * halfHeight + halfHeight - 500
        }
        this.$emit('clickModel', editor.selected, position)// 自定义事件  传递值“子向父组件传值”
      }
    },
    updateLabelInfoJoint(ModelId, robotData) {
      for (const robotDatum of Object.keys(robotData)) {
        editor.robotInfo[ModelId]['joint'][robotDatum] = robotData[robotDatum]
        if (this.robotInfo.id === ModelId) {
          this.robotInfo['joint'][robotDatum] = robotData[robotDatum]
        }
      }
      // if (this.robotInfo.id === ModelId) {
      //   console.log(robotData)
      //   for (const robotDatum of Object.keys(robotData)) {
      //     this.robotInfo['joint'][robotDatum] = robotData[robotDatum]
      //   }
      // }
    },
    updateLabelInfoSpeedPose(ModelId, tcpData, speedData, alarmInfo) {
      for (const robotDatum of Object.keys(tcpData)) {
        editor.robotInfo[ModelId]['tcp'][robotDatum] = tcpData[robotDatum]
        if (this.robotInfo.id === ModelId) {
          this.robotInfo['tcp'][robotDatum] = tcpData[robotDatum]
        }
      }
      editor.robotInfo[ModelId]['speed'] = speedData
      editor.robotInfo[ModelId]['alarm'] = alarmInfo
      if (this.robotInfo.id === ModelId) {
        this.robotInfo['speed'] = speedData
        this.robotInfo['alarm'] = alarmInfo
      }
    },
    /**
       * 设定模型初始状态
       */
    setModelSates() {
      // 模型的显示隐藏
      editor.resourcesTree.forEach(res => {
        if (res.visible === '0') {
          if (editor.getObjectById(res.id)) {
            editor.getObjectById(res.id).visible = !!(parseInt(res.visible))
          }
        }
      })
      const treeRes = editor.resourcesTree
      for (const treeResValue of treeRes) {
        if (treeResValue.treeType !== 'folder') {
          const currentModel = editor.getObjectById(treeResValue.id)

          if (Object.hasOwnProperty.call(treeResValue, 'WireFrame') && treeResValue.WireFrame) {
            editor.setModelWireFrame(currentModel, true)
          }
          if (Object.hasOwnProperty.call(treeResValue, 'transParent') && treeResValue.transParent) {
            editor.setTransparent(treeResValue.id, 0.3)
          }
          if (currentModel) currentModel.visible = !!parseInt(treeResValue.visible)
        }
      }
    },

    /**
       * 设定场景初始状态
       * @param type
       */
    setSceneStates(type) {
      switch (type) {
        case '0':
          scene.background = new THREE.Color('#dcdcdc')
          break
        case '1':
          scene.background = new THREE.Color(editor.sceneConfig.RenderColorModel.color)
          break
        case '2':
          if (editor.sceneConfig.RenderColorModel.image === '') {
            editor.scene.background = new THREE.Color(editor.sceneConfig.RenderColorModel.color)
            return
          }
          new THREE.TextureLoader().load(editor.sceneConfig.RenderColorModel.image === '', function(texture) {
            scene.background = texture
            texture.dispose()
          })
          break
        default:
          scene.background = new THREE.Color('#dcdcdc')
          break
      }
    }
    // endregion
  }
}
</script>

<style scoped>

</style>
