<template>
  <div class="canvas-container" :style="{'background-color': isConnected ? 'rgba(4, 33, 58, 70%)' : '#fff'}">
    <div ref="container" class="point-cloud-container"></div>
    <!-- <div  v-if="!isConnected" class="reload_bg"><el-button type="danger">刷新</el-button></div> -->
  </div>
</template>

<script>
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { mapGetters } from 'vuex'
import { points } from '../../config/point.js'
export default {
  /* eslint-disable */
  data () {
    return {
      isConnected: true,
      points: [], // 存储所有点云数据
      ws: null, // WebSocket 实例
      // Three.js 相关对象
      scene: null,
      camera: null,
      renderer: null,
      controls: null,
      pointCloud: null,
      vehicleSprite: null,
      // 渲染循环
      animationFrameId: null,
      // 性能优化
      pointsBuffer: [],
      bufferUpdateThreshold: 500,
      lastUpdateTime: 0,
      // 小车图片
      vehicleImage: require('../../images/new/agv.png'),
      // 2D视图参数
      viewSize: 20,
      minZoom: 0.5,
      maxZoom: 5
    }
  },
  computed: {
    ...mapGetters(['agvObj', 'position', 'rotation']),
  },
  watch: {
    agvObj: {
      handler() {
        this.updateVehiclePosition()
      },
      deep: true
    },
    position: {
      handler() {
        this.updateVehiclePosition()
      },
      deep: true
    },
    rotation: {
      handler() {
        this.updateVehiclePosition()
      },
      deep: true
    }
  },
  mounted () {
    this.initThreeJS()
    // this.initWebSocket()
    this.init()
    this.startRendering()
    window.addEventListener('resize', this.handleResize)
  },
  beforeDestroy () {
    if (this.ws) this.ws.close()
    window.removeEventListener('resize', this.handleResize)
    if (this.renderer) this.renderer.dispose()
    if (this.controls) {
      this.controls.dispose()
    }
  },
  methods: {
    initWebSocket() {
      const wsHost = process.env.VUE_APP_API_BASE_URL.replace(/^https?:\/\//, '')
      const sid = this.$store.getters.userInfo === 'true' ? 1 : 2
      this.ws = new WebSocket(`ws://${wsHost}/webSocket/PointCloudData/${sid}`)
      
      this.ws.onopen = () => {
        console.log('WebSocket connected')
      }
      
      this.ws.onmessage = (event) => {
        const newPoints = event.data
        // 确保所有点都在XY平面(z=0)
        const points2D = newPoints.map(p => ({ x: p.x, y: p.y, z: 0 }))
        this.processNewPoints(points2D)
      }
      
      this.ws.onerror = (error) => {
        console.error('WebSocket error:', error)
      }
      
      this.ws.onclose = () => {
        console.log('WebSocket disconnected')
      }
    },

    init () {
      this.isConnected = true
      const newPoints = points.data
      const points2D = newPoints.map(p => ({ x: p.x, y: p.y, z: 0 }))
      this.processNewPoints(points2D)
    },
    
    initThreeJS() {
      // viewSize: 控制视图范围大小，值越小看到的范围越小（视角越近）
      // camera.position.z: 相机Z轴位置，值越小视角越近
      // camera.zoom: 直接控制缩放级别，大于1放大，小于1缩小
      // 1. 创建场景
      this.scene = new THREE.Scene()
      
      // 2. 创建正交相机(2D视图)
      const container = this.$refs.container
      const aspect = container.clientWidth / container.clientHeight
      
      this.camera = new THREE.OrthographicCamera(
        -this.viewSize * aspect / 2,
        this.viewSize * aspect / 2,
        this.viewSize / 2,
        -this.viewSize / 2,
        0.1,
        1000
      )
      this.camera.position.set(0, 0, 40)
      this.camera.lookAt(0, 0, 0)
      
      // 3.创建渲染器 - 启用alpha通道实现透明背景
      this.renderer = new THREE.WebGLRenderer({ 
        antialias: true,
        alpha: true,  // 关键：启用alpha通道
        transparent: true  // 关键：允许透明
      });
      this.renderer.setPixelRatio(window.devicePixelRatio)
      this.renderer.setSize(container.clientWidth, container.clientHeight)
      // 可选：设置clearAlpha确保完全透明
      this.renderer.setClearAlpha(0);
      container.appendChild(this.renderer.domElement)
      
      // 4. 添加OrbitControls并配置为2D模式
      this.controls = new OrbitControls(this.camera, this.renderer.domElement)
      this.configure2DControls()
      
      // 5. 添加2D坐标轴辅助
      const axesHelper = new THREE.AxesHelper(10)
      this.scene.add(axesHelper)
      
      // 6. 初始化点云
      this.initPointCloud()
      
      // 7. 初始化车辆精灵
      this.initVehicleSprite()
    },
    
    configure2DControls() {
      // 禁用旋转
      this.controls.enableRotate = false
      
      // 启用平面平移
      this.controls.screenSpacePanning = true
      
      // 设置缩放限制
      this.controls.minZoom = this.minZoom
      this.controls.maxZoom = this.maxZoom
      
      // 启用阻尼效果
      this.controls.enableDamping = true
      this.controls.dampingFactor = 0.25
      
      // 确保相机保持2D视角
      this.controls.addEventListener('change', () => {
        this.camera.position.z = 40
        // this.camera.lookAt(this.controls.target)
      })
      
      // 修复触摸事件处理
      this.fixTouchEvents()
    },
    
    fixTouchEvents() {
      // 确保控制器的触摸处理函数存在
      if (!this.controls) return;
      
      // 备份原始触摸处理函数
      const originalOnTouchStart = this.controls.onTouchStart
      const originalOnTouchMove = this.controls.onTouchMove
      const originalOnTouchEnd = this.controls.onTouchEnd
      
      // 修复触摸开始事件
      this.controls.onTouchStart = (event) => {
        if (!event.touches) return
        if (originalOnTouchStart) originalOnTouchStart(event)
      }
      
      // 修复触摸移动事件
      this.controls.onTouchMove = (event) => {
        if (!event.touches || event.touches.length === 0) return
        if (event.touches[0] && event.touches[0].clientX !== undefined) {
          if (originalOnTouchMove) originalOnTouchMove(event)
        }
      }
      
      // 修复触摸结束事件
      this.controls.onTouchEnd = (event) => {
        if (!event.touches) return
        if (originalOnTouchEnd) originalOnTouchEnd(event)
      }
    },
    
    initPointCloud() {
      const geometry = new THREE.BufferGeometry()
      const material = new THREE.PointsMaterial({
        color: 0xffffff,
        size: 1,
        transparent: true,
        opacity: 1
      })
      
      this.pointCloud = new THREE.Points(geometry, material)
      this.scene.add(this.pointCloud)
    },
    
    initVehicleSprite() {
      const textureLoader = new THREE.TextureLoader()
      textureLoader.load(this.vehicleImage, (texture) => {
        // 97px × 67px图片的比例
        const imageAspect = 97 / 67
        const spriteWidth = 2
        const spriteHeight = spriteWidth / imageAspect
        
        this.vehicleSprite = new THREE.Sprite(
          new THREE.SpriteMaterial({ 
            map: texture,
            transparent: true,
            opacity: 0.9
          })
        )
        this.vehicleSprite.scale.set(spriteWidth, spriteHeight, 1)
        
        // 角度偏移（根据图片初始朝向调整）
        this.updateVehiclePosition()
        this.scene.add(this.vehicleSprite)
      })
    },
        
    processNewPoints(newPoints) {
      this.pointsBuffer.push(...newPoints)
      const now = performance.now()
      if (this.pointsBuffer.length >= this.bufferUpdateThreshold || now - this.lastUpdateTime > 1000) {
        this.updatePointCloudGeometry()
        this.lastUpdateTime = now
      }
    },
    
    updatePointCloudGeometry() {
      if (this.pointsBuffer.length === 0) return
      
      this.points = this.points.concat(this.pointsBuffer)
      this.pointsBuffer = []
      
      if (this.points.length > 50000) {
        this.points = this.points.slice(-40000)
      }
      
      const positions = new Float32Array(this.points.length * 3)
      for (let i = 0; i < this.points.length; i++) {
        positions[i * 3] = this.points[i].x
        positions[i * 3 + 1] = this.points[i].y
        positions[i * 3 + 2] = 0
      }
      
      this.pointCloud.geometry.dispose()
      this.pointCloud.geometry = new THREE.BufferGeometry()
      this.pointCloud.geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3))
    },
    
    updateVehiclePosition() {
      if (!this.vehicleSprite) return
      
      this.vehicleSprite.position.set(
        this.position.x,
        this.position.y,
        0
      )
      const radians = this.rotation * (Math.PI / 180)
      
      this.vehicleSprite.rotation.X = radians
    },
    
    startRendering() {
      const render = () => {
        this.controls.update()
        this.renderer.render(this.scene, this.camera)
        this.animationFrameId = requestAnimationFrame(render)
      }
      render()
    },
    
    handleResize() {
      const container = this.$refs.container
      const width = container.clientWidth
      const height = container.clientHeight
      const aspect = width / height
      
      this.camera.left = -this.viewSize * aspect / 2
      this.camera.right = this.viewSize * aspect / 2
      this.camera.top = this.viewSize / 2
      this.camera.bottom = -this.viewSize / 2
      this.camera.updateProjectionMatrix()
      
      this.renderer.setSize(width, height)
    },
    
    zoomToArea(minX, maxX, minY, maxY) {
      const width = maxX - minX
      const height = maxY - minY
      const centerX = (minX + maxX) / 2
      const centerY = (minY + maxY) / 2
      
      const margin = 0.1
      const targetViewSize = Math.max(width, height) * (1 + margin)
      
      // 计算合适的缩放级别
      const zoomLevel = this.viewSize / targetViewSize
      this.controls.target.set(centerX, centerY, 0)
      // 通过调整camera.zoom实现平滑缩放
      this.camera.zoom = Math.min(this.maxZoom, Math.max(this.minZoom, zoomLevel))
      this.camera.updateProjectionMatrix()
      this.controls.update()
    }
  }
}
</script>

<style lang="stylus" scoped>
.canvas-container
  position relative
  display flex
  justify-content: center;
  align-items: center;
  height calc(100% - 1rem)
  margin .14rem 0
  box-shadow inset 1px 1px 7px 2px #4d9bcd
  overflow hidden
.point-cloud-container
  width 100%
  height 100%
.reload_bg {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
  top: 0;
  left: 0;
}
</style>
