/* ── 点睛 3D 特效:three.js 自定义图层 ──
   与 MapLibre 共享同一 WebGL 上下文(renderingMode:'3d'),不另开 canvas、不经过 React。
   内容:小普陀上空盘旋的海鸥群 + 洱海湖面若隐若现的浮光微尘。
   可一键关闭(关闭后停止 triggerRepaint,地图回到静止,零额外开销)。 */
(function () {
  const FX_REF = [100.19, 25.74];          // 局部坐标原点(大理中心)
  const GULL_AT = [100.245, 25.800];        // 小普陀:红嘴鸥成群
  const LAKE_BBOX = [100.10, 25.66, 100.29, 25.90]; // 洱海大致范围(撒浮尘)

  let enabled = true;
  let added = false;
  let repaintPending = false;
  let state = null; // { scene,camera,renderer,REF,scale,birds,motes,t0 }

  /* 海鸥剪影纹理(canvas 画一只展翅的鸥)*/
  function birdTexture() {
    const c = document.createElement("canvas"); c.width = 72; c.height = 40;
    const g = c.getContext("2d");
    g.strokeStyle = "rgba(252,250,244,0.96)"; g.lineWidth = 5;
    g.lineCap = "round"; g.lineJoin = "round";
    g.beginPath();
    g.moveTo(7, 28); g.quadraticCurveTo(24, 6, 36, 24);
    g.quadraticCurveTo(48, 6, 65, 28); g.stroke();
    // 翼尖一点深色,像红嘴鸥
    g.strokeStyle = "rgba(60,52,40,0.55)"; g.lineWidth = 4;
    g.beginPath(); g.moveTo(7, 28); g.lineTo(13, 23); g.moveTo(65, 28); g.lineTo(59, 23); g.stroke();
    const t = new THREE.CanvasTexture(c); t.needsUpdate = true; return t;
  }
  /* 柔光圆点纹理(浮尘/湖面碎光)*/
  function moteTexture() {
    const c = document.createElement("canvas"); c.width = 48; c.height = 48;
    const g = c.getContext("2d");
    const grd = g.createRadialGradient(24, 24, 0, 24, 24, 24);
    grd.addColorStop(0, "rgba(255,250,235,0.95)");
    grd.addColorStop(0.4, "rgba(255,244,214,0.45)");
    grd.addColorStop(1, "rgba(255,244,214,0)");
    g.fillStyle = grd; g.beginPath(); g.arc(24, 24, 24, 0, Math.PI * 2); g.fill();
    const t = new THREE.CanvasTexture(c); t.needsUpdate = true; return t;
  }

  function toLocal(REF, scale, lng, lat, alt) {
    const mc = maplibregl.MercatorCoordinate.fromLngLat([lng, lat], alt);
    return new THREE.Vector3((mc.x - REF.x) / scale, (REF.y - mc.y) / scale, (mc.z - REF.z) / scale);
  }

  function build(map) {
    const REF = maplibregl.MercatorCoordinate.fromLngLat(FX_REF, 0);
    const scale = REF.meterInMercatorCoordinateUnits();
    const scene = new THREE.Scene();
    const camera = new THREE.Camera();

    // ── 海鸥群:绕小普陀盘旋 ──
    const gullCenter = toLocal(REF, scale, GULL_AT[0], GULL_AT[1], 0);
    const tex = birdTexture();
    const birds = [];
    for (let i = 0; i < 30; i++) {
      const mat = new THREE.SpriteMaterial({ map: tex, transparent: true, depthTest: false, opacity: 0.92 });
      const sp = new THREE.Sprite(mat);
      const b = {
        sprite: sp,
        ang: Math.random() * Math.PI * 2,
        r: 180 + Math.random() * 620,        // 盘旋半径 180~800m
        h: 70 + Math.random() * 150,          // 高度 70~220m
        sp: (0.18 + Math.random() * 0.22) * (Math.random() < 0.5 ? 1 : -1),
        size: 26 + Math.random() * 18,
        bob: Math.random() * Math.PI * 2,
      };
      birds.push(b); scene.add(sp);
    }

    // ── 湖面浮光微尘 ──
    const N = 70, pos = new Float32Array(N * 3), motes = [];
    for (let i = 0; i < N; i++) {
      const lng = LAKE_BBOX[0] + Math.random() * (LAKE_BBOX[2] - LAKE_BBOX[0]);
      const lat = LAKE_BBOX[1] + Math.random() * (LAKE_BBOX[3] - LAKE_BBOX[1]);
      const v = toLocal(REF, scale, lng, lat, 8 + Math.random() * 40);
      pos[i * 3] = v.x; pos[i * 3 + 1] = v.y; pos[i * 3 + 2] = v.z;
      motes.push({ phase: Math.random() * Math.PI * 2, drift: 6 + Math.random() * 14, baseX: v.x, baseY: v.y });
    }
    const geo = new THREE.BufferGeometry();
    geo.setAttribute("position", new THREE.BufferAttribute(pos, 3));
    const pmat = new THREE.PointsMaterial({
      map: moteTexture(), size: 90, transparent: true, depthTest: false,
      blending: THREE.AdditiveBlending, opacity: 0.5, sizeAttenuation: true,
    });
    const points = new THREE.Points(geo, pmat);
    scene.add(points);

    return { REF, scale, scene, camera, birds, gullCenter, points, motes, geo, t0: performance.now() };
  }

  const layer = {
    id: "fx3d", type: "custom", renderingMode: "3d",
    onAdd(map, gl) {
      state = build(map);
      state.renderer = new THREE.WebGLRenderer({ canvas: map.getCanvas(), context: gl, antialias: true });
      state.renderer.autoClear = false;
      this.map = map;
    },
    render(gl, matrix) {
      if (!state) return;
      const now = performance.now(), t = (now - state.t0) / 1000;

      // 海鸥:盘旋 + 上下浮动 + 拍翼(轻微纵向缩放)
      state.birds.forEach((b) => {
        const a = b.ang + t * b.sp;
        const x = state.gullCenter.x + Math.cos(a) * b.r;
        const y = state.gullCenter.y + Math.sin(a) * b.r;
        const z = b.h + Math.sin(t * 0.7 + b.bob) * 18;
        b.sprite.position.set(x, y, z);
        const flap = 0.78 + 0.22 * Math.abs(Math.sin(t * 6 + b.bob));
        b.sprite.scale.set(b.size, b.size * flap, 1);
      });
      // 浮尘:缓慢漂移 + 呼吸明灭
      const arr = state.geo.attributes.position.array;
      state.motes.forEach((m, i) => {
        arr[i * 3] = m.baseX + Math.cos(t * 0.15 + m.phase) * m.drift;
        arr[i * 3 + 1] = m.baseY + Math.sin(t * 0.12 + m.phase) * m.drift;
      });
      state.geo.attributes.position.needsUpdate = true;
      state.points.material.opacity = 0.4 + 0.18 * Math.sin(t * 0.6);

      const l = new THREE.Matrix4()
        .makeTranslation(state.REF.x, state.REF.y, state.REF.z)
        .scale(new THREE.Vector3(state.scale, -state.scale, state.scale));
      state.camera.projectionMatrix = new THREE.Matrix4().fromArray(matrix).multiply(l);

      state.renderer.resetState();
      state.renderer.render(state.scene, state.camera);

      // 仅在开启时驱动重绘,并节流到 ~30fps(海鸥足够顺,省一半地图重绘开销)
      if (enabled && !repaintPending) {
        repaintPending = true;
        setTimeout(() => { repaintPending = false; if (state) this.map.triggerRepaint(); }, 33);
      }
    },
  };

  function initFx3d(map) {
    if (added) return;
    added = true;
    map.addLayer(layer);   // 叠在最顶,海鸥/浮尘浮在路线之上
  }

  window.initFx3d = initFx3d;
  window.FX3D = {
    get enabled() { return enabled; },
    setEnabled(b) {
      enabled = !!b;
      if (!state) return;
      state.scene.visible = enabled;
      if (layer.map) layer.map.triggerRepaint(); // 关:重绘一次清掉海鸥后静止;开:重新进入动画循环
    },
  };
})();
