<template>
  <div class="model3d-view">
    <el-space :gutter="10" class="toolbar">
      <el-button type="primary" @click="test1">测试1</el-button>
      <div class="demo-color-block">
        <span class="demonstration">物体数:<el-text type="danger">{{ restate.objects }}</el-text></span>
        <span class="demonstration"> 顶点数:<el-text type="danger">{{ restate.vertices }}</el-text></span>
        <span class="demonstration"> 三角形数:<el-text type="danger">{{ restate.faces }}</el-text></span>
      </div>
    </el-space>
    <div class="main-content">
      <div class="canvas-container" ref="canvasContainer" />
    </div>
  </div>
</template>
<script setup lang="ts">
import * as THREE from 'three'
import { getCurrentInstance, nextTick, onBeforeUnmount, onMounted, reactive, ref, watch } from 'vue'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
import Stats from 'three/examples/jsm/libs/stats.module'
import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry'
import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial'
import { Line2 } from 'three/examples/jsm/lines/Line2'
import MeasureRenderer from '@/modules/measure/MeasureRenderer.ts'
import { LineSegmentsGeometry } from 'three/examples/jsm/lines/LineSegmentsGeometry'
import { LineSegments2 } from 'three/examples/jsm/lines/LineSegments2'

const canvasContainer = ref(null)
let resizeObserver: ResizeObserver | null = null
let scene: THREE.Scene | null = null
let renderer: THREE.WebGLRenderer | null = null
let viewerDom: HTMLElement | null = null
let camera: THREE.PerspectiveCamera | THREE.OrthographicCamera | null = null
let controls: OrbitControls | null = null
let axesHelper: THREE.AxesHelper | null = null
let gridHelper: THREE.GridHelper | null = null
let statsControls: Stats | null = null
let animationFrameId: number | null = null
let modelGroup = new THREE.Group()

const pointMaterial = new THREE.SpriteMaterial({
  color: 0xFFFF99, // 0x303133,
  transparent: true,
  side: THREE.DoubleSide,
  opacity: 1,
  sizeAttenuation: true
})
// const lineMaterial = new LineMaterial({
//   color: 0xFF8C00,
//   linewidth: 5,
//   vertexColors: false,
//   dashed: false
// })
const lineMaterial = new LineMaterial({
  color: 0xFF8C00,
  linewidth: 5
});

function test1() {
  const xcount = 100
  const zcount = 100
  const dist = 1.25
  const spacing = dist
  const y = 0.1

  const points = []

  // 创建所有点
  for (let z = 0; z < zcount; z++) {
    for (let x = 0; x < xcount; x++) {
      const px = x * dist
      const pz = z * dist
      const point = new THREE.Sprite(pointMaterial)
      point.position.set(px, y, pz)
      point.scale.set(0.25, 0.25, 1) // 设置大小
      scene.add(point)
      points.push(point.position.clone())
    }
  }

//   // 绘制线段
//   const lines = []
//
// // 绘制线段（每两个点一组）
//   for (let z = 0; z < zcount; z++) {
//     for (let x = 0; x < xcount - 1; x++) {
//       const i = z * xcount + x
//       drawLine(points[i], points[i + 1])
//     }
//   }
//
//   for (let z = 0; z < zcount - 1; z++) {
//     for (let x = 0; x < xcount; x++) {
//       const i = z * xcount + x
//       const belowIndex = (z + 1) * xcount + x
//       drawLine(points[i], points[belowIndex])
//     }
//   }
  const positions = [];

  // 横向连接（右）
  for (let z = 0; z < zcount; z++) {
    for (let x = 0; x < xcount - 1; x++) {
      const x1 = x * spacing;
      const z1 = z * spacing;
      const x2 = (x + 1) * spacing;
      const z2 = z * spacing;
      positions.push(x1, y, z1, x2, y, z2);
    }
  }

  // 纵向连接（下）
  for (let z = 0; z < zcount - 1; z++) {
    for (let x = 0; x < xcount; x++) {
      const x1 = x * spacing;
      const z1 = z * spacing;
      const x2 = x * spacing;
      const z2 = (z + 1) * spacing;
      positions.push(x1, y, z1, x2, y, z2);
    }
  }

  const geometry = new LineSegmentsGeometry();
  geometry.setPositions(positions); // [x1,y1,z1, x2,y2,z2, ...]

  const material = new LineMaterial({
    color: 0xFF8C00,
    linewidth: 5,
    vertexColors: false
  });

  const lineSegments = new LineSegments2(geometry, material);
  lineSegments.computeLineDistances(); // 必须调用一次
  lineSegments.name = 'grid-lines';
  scene.add(lineSegments);
}

function drawLine(p1: THREE.Vector3, p2: THREE.Vector3) {
  const geometry = new LineGeometry();
  geometry.setPositions([p1.x, p1.y, p1.z, p2.x, p2.y, p2.z]);

  // const material = new LineMaterial({
  //   color: 0xFF8C00,
  //   linewidth: 5
  // });

  const line = new Line2(geometry, lineMaterial);
  line.computeLineDistances();

  scene.add(line)
}

const restate = reactive({
  targetColor: '#ff0000',
  loadScale: 1,
  mode: 'translate',
  objects: 0,
  vertices: 0,
  faces: 0
})

// 状态变量
const state = {
  showAxesHelper: true,
  showGridHelper: true,
  camera: {
    position: { x: 0, y: 5, z: 10 },
    rotation: { x: 0, y: 0, z: 0 }
  }
}
onMounted(() => {
  nextTick(() => {
    initThree()

    const viewerDom = canvasContainer.value
    if (resizeObserver) {
      resizeObserver.unobserve(viewerDom)
    }
    resizeObserver = new ResizeObserver(handleResize)
    resizeObserver.observe(viewerDom)

    window['cp'] = getCurrentInstance()
  })
})

onBeforeUnmount(() => {
  if (animationFrameId !== null) {
    cancelAnimationFrame(animationFrameId)
    animationFrameId = null
  }

  cleanupThree()

  const viewerDom = canvasContainer.value
  if (resizeObserver) {
    resizeObserver.unobserve(viewerDom)
  }

  window['cp'] = null
})

function initThree() {
  viewerDom = canvasContainer.value
  if (!viewerDom) {
    console.error('Viewer DOM element not found')
    return
  }

  // 场景
  scene = new THREE.Scene()
  scene.background = new THREE.Color(0xeeeeee)

  // 渲染器
  renderer = new THREE.WebGLRenderer({
    antialias: true,
    alpha: true,
    powerPreference: 'high-performance'
  })
  renderer.clearDepth()
  renderer.setPixelRatio(window.devicePixelRatio)
  renderer.setSize(viewerDom.clientWidth, viewerDom.clientHeight)
  viewerDom.appendChild(renderer.domElement)

  // 摄像机
  // initMode3DCamera()
  initMode2DCamera()

  // 辅助线
  axesHelper = new THREE.AxesHelper(5)
  scene.add(axesHelper)

  gridHelper = new THREE.GridHelper(1000, 1000)
  scene.add(gridHelper)
  gridHelper.visible = false

  // 光照
  const ambientLight = new THREE.AmbientLight(0xffffff, 1.5)
  scene.add(ambientLight)

  const directionalLight = new THREE.DirectionalLight(0xffffff, 1.5)
  directionalLight.position.set(5, 5, 5).multiplyScalar(3)
  directionalLight.castShadow = true
  scene.add(directionalLight)

  const hemisphereLight = new THREE.HemisphereLight(0xffffff, 0x444444, 1)
  scene.add(hemisphereLight)


  // 性能监控
  statsControls = new Stats()
  statsControls.showPanel(0)
  statsControls.dom.style.right = '0'
  statsControls.dom.style.left = 'auto'
  viewerDom.appendChild(statsControls.dom)

  animate()
}

// 动画循环
function animate() {
  animationFrameId = requestAnimationFrame(animate)
  renderView()
}

function handleResize(entries) {
  for (let entry of entries) {
    // entry.contentRect包含了元素的尺寸信息
    console.log('Element size changed:', entry.contentRect)

    const width = entry.contentRect.width
    const height = entry.contentRect.height

    if (camera instanceof THREE.PerspectiveCamera) {
      camera.aspect = width / height
      camera.updateProjectionMatrix()

    } else if (camera instanceof THREE.OrthographicCamera) {
      camera.left = width / -2
      camera.right = width / 2
      camera.top = height / 2
      camera.bottom = height / -2
      camera.updateProjectionMatrix()
    }
    renderer.setPixelRatio(window.devicePixelRatio)
    renderer.setSize(width, height)
    break
  }
}


/**
 * 初始化2D相机
 */
function initMode2DCamera() {
  if (camera) {
    scene.remove(camera)
  }

  // ============================ 创建正交相机
  const cameraNew = new THREE.OrthographicCamera(
    viewerDom.clientWidth / -2,
    viewerDom.clientWidth / 2,
    viewerDom.clientHeight / 2,
    viewerDom.clientHeight / -2,
    1,
    500
  )
  cameraNew.position.set(0, 60, 0)
  cameraNew.lookAt(0, 0, 0)
  cameraNew.zoom = 60
  camera = cameraNew
  scene.add(camera)

  // ============================ 创建控制器
  const controlsNew = new OrbitControls(
    camera,
    renderer.domElement
  )
  controlsNew.enableDamping = false
  controlsNew.enableZoom = true
  controlsNew.enableRotate = false
  controlsNew.mouseButtons = { LEFT: THREE.MOUSE.PAN, RIGHT: THREE.MOUSE.PAN } // 鼠标中键平移
  controlsNew.screenSpacePanning = false // 定义平移时如何平移相机的位置 控制不上下移动
  controlsNew.listenToKeyEvents(viewerDom) // 监听键盘事件
  controlsNew.keys = { LEFT: 'KeyA', UP: 'KeyW', RIGHT: 'KeyD', BOTTOM: 'KeyS' }
  controlsNew.panSpeed = 1
  controlsNew.keyPanSpeed = 20 // normal 7
  controlsNew.minDistance = 0.1
  controlsNew.maxDistance = 1000
  controls = controlsNew

  cameraNew.updateProjectionMatrix()
}

function initMode3DCamera() {
  if (camera) {
    scene.remove(camera)
  }

  const viewerDom = canvasContainer.value

  // ============================ 创建透视相机
  const cameraNew = new THREE.PerspectiveCamera(25, viewerDom.clientWidth / viewerDom.clientHeight, 0.1, 2000)
  cameraNew.position.set(5, 5, 5)
  cameraNew.lookAt(0, 0, 0)

  camera = cameraNew
  scene.add(camera)

  const controlsNew = new OrbitControls(camera, viewerDom)
  controlsNew.mouseButtons = { LEFT: THREE.MOUSE.PAN, RIGHT: THREE.MOUSE.ROTATE } // 鼠标中键平移
  controlsNew.enableDamping = false
  controlsNew.screenSpacePanning = false // 定义平移时如何平移相机的位置 控制不上下移动
  controlsNew.minDistance = 2
  controlsNew.addEventListener('change', syncCameraState)
  controls = controlsNew
  controls.update()

  camera.updateProjectionMatrix()

  syncCameraState()
}

/**
 * 重新加载相机状态到全局状态
 */
function syncCameraState() {
  if (camera) {
    state.camera.position.x = camera.position.x
    state.camera.position.y = camera.position.y
    state.camera.position.z = camera.position.z

    state.camera.rotation.x = camera.rotation.x
    state.camera.rotation.y = camera.rotation.y
    state.camera.rotation.z = camera.rotation.z
  }
}

function renderView() {
  statsControls?.update()
  renderer?.render(scene, camera)
}


function cleaupModel() {
  if (modelGroup) {
    scene.remove(modelGroup)
  }
  tcontrols.detach()
  transformEditCtl.value.detach()
}

function cleanupThree() {
  // 移除旧模型
  if (scene) {
    scene.traverse((obj: THREE.Mesh) => {
      // 释放几何体
      if (obj.geometry) {
        obj.geometry.dispose()
      }

      // 释放材质
      if (obj.material) {
        if (Array.isArray(obj.material)) {
          obj.material.forEach(m => m.dispose())
        } else {
          obj.material.dispose()
        }
      }

      // 释放纹理
      if (obj.texture) {
        obj.texture.dispose()
      }

      // 释放渲染目标
      if (obj.renderTarget) {
        obj.renderTarget.dispose()
      }

      // 移除事件监听（如 OrbitControls）
      if (obj.dispose) {
        obj.dispose()
      }
    })

    if (modelGroup) {
      scene.remove(modelGroup)
    }
    // 清空场景
    scene.children = []

    modelGroup = null
  }

  if (statsControls) {
    statsControls.dom.remove()
  }

  if (renderer) {
    renderer.dispose()
    renderer.forceContextLoss()
    console.log('WebGL disposed, memory:', renderer.info.memory)
    renderer.domElement = null
  }
}


</script>
<style scoped lang="less">
.model3d-view {
  display: flex;
  flex-direction: column;
  flex-grow: 1;
  overflow: hidden;

  .main-content {
    display: flex;
    flex: 1;
    overflow: hidden;

    .model3d-content {
      height: 100%;
      display: flex;
      flex-direction: row;
    }
  }

  .canvas-container {
    width: 100%;
    height: 100%;
    position: relative;
  }
}

</style>
