import * as THREE from 'three';
import { FontLoader } from 'three/examples/jsm/loaders/FontLoader';
import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry.js';
import helvetikerFont from 'three/examples/fonts/helvetiker_regular.typeface.json';
import { MeshLineGeometry, MeshLineMaterial } from 'meshline';
import StreamLoaderParserWorker from '../../packages/utils/StreamLoaderParser.worker.js';

export const GEOM_TYPES = {
  geom_3d: 53248,
  geom_3d_text: 53249,
  geom_3d_mtext: 53250,
  geom_3d_obj: 53251,
  geom_2d: 57344,
  geom_2d_text: 57345,
  geom_2d_mtext: 57346,
  geom_2d_circle: 57347,
  geom_2d_arc: 57348,
  geom_2d_ellipse: 57349,
  geom_2d_ellipseArc: 57350,
  geom_2d_others: 57351,
};

// 文本对齐枚举
const TextAlign = {
  TextLeftBottom: 0, // 左下角
  TextLeftMiddle: 1,
  TextLeftTop: 2,
  TextCenterBottom: 3,
  TextCenterMiddle: 4,
  TextCenterTop: 5,
  TextRightBottom: 6,
  TextRightMiddle: 7,
  TextRightTop: 8, // 右上角
  TextLeft: 9,
  TextCenter: 10,
  TextRight: 11,
  TextAligned: 12,
  TextMiddle: 13,
  TextFit: 14,
};

// 图元加载模式
const PRIMITIVE_TYPE = {
  full: 2, // 全量加载
  onlyBounding: 1, // 仅加载边界框
};

let drawObjMapInstance = {};
// 使用Set来跟踪已处理的drawObject，避免重复创建group
// let processedDrawObjects = new Set();
let instanceToInstancedMeshMap = new Map();
let instancedMappingWorker = null;
let instancedMappingWorkerRequestId = 0;
const instancedMappingWorkerRequests = new Map();

function ensureInstancedMappingWorker() {
  if (instancedMappingWorker) return instancedMappingWorker;
  try {
    instancedMappingWorker = new StreamLoaderParserWorker();
  } catch (e) {
    instancedMappingWorker = null;
    return null;
  }
  instancedMappingWorker.addEventListener('message', e => {
    const payload = e.data || {};
    const pending = instancedMappingWorkerRequests.get(payload.id);
    if (!pending) return;
    instancedMappingWorkerRequests.delete(payload.id);
    if (payload.type === 'success') {
      pending.resolve(payload.result);
    } else {
      pending.reject(new Error(payload.error));
    }
  });
  return instancedMappingWorker;
}

function requestInstancedMapping(instances, drawObjs) {
  const worker = ensureInstancedMappingWorker();
  if (!worker) {
    return Promise.reject(new Error('Worker is not initialized'));
  }
  return new Promise((resolve, reject) => {
    const id = instancedMappingWorkerRequestId++;
    instancedMappingWorkerRequests.set(id, { resolve, reject });
    worker.postMessage({
      id,
      type: 'buildInstancedMapping',
      data: { instances, drawObjs },
    });
  });
}

function getInstanceNormalSign(matrix) {
  if (!matrix || typeof matrix.determinant !== 'function') return 1;
  return matrix.determinant() < 0 ? -1 : 1;
}

function getMatrixVal(matrix) {
  const val = matrix && matrix.val ? matrix.val : matrix;
  return val && val.length >= 16 ? val : null;
}

function composeInstanceMatrix(instance, mesh, geometry) {
  const resultMatrix = new THREE.Matrix4();
  const meshMatrix = new THREE.Matrix4();
  const primitiveMatrix = new THREE.Matrix4();
  const meshMatrixVal = getMatrixVal(instance && instance.matrix);
  const primitiveMatrixVal = getMatrixVal(mesh && mesh.matrix);

  if (meshMatrixVal) {
    meshMatrix.fromArray(meshMatrixVal);
  }
  if (primitiveMatrixVal) {
    primitiveMatrix.fromArray(primitiveMatrixVal);
  }

  const { points, alignType } = mesh || {};
  if (mesh && isTextType(mesh.type) && points && points.length >= 3) {
    const positionMatrix = new THREE.Matrix4();
    const alignMatrix = createAlignedText(alignType, geometry);
    positionMatrix.identity().makeTranslation(points[0], points[1], points[2]);
    primitiveMatrix.multiply(alignMatrix).multiply(positionMatrix);
  }

  resultMatrix.multiplyMatrices(meshMatrix, primitiveMatrix);
  return resultMatrix;
}

/**
 * 重置处理状态，用于新的批量加载会话
 */
function resetProcessingState() {
  drawObjMapInstance = {};
  // instanceToInstancedMeshMap.clear();
  // processedDrawObjects.clear();
}

/**
 * 获取已构建的绘制对象实例映射（用于根据 instanceId 查找其几何数据）
 * @param {string} drawObjectId
 * @returns {Object|undefined} 返回包含 MapMesh/MapInstance/lodLevel 的对象
 */
function getDrawObjectInstance(drawObjectId) {
  return drawObjMapInstance[drawObjectId];
}

function mergeInstancedMappingResult(result) {
  if (!result) return;
  const { drawObjMapInstance: incomingMap, instanceToDrawObject } = result;

  if (incomingMap) {
    const keys = Object.keys(incomingMap);
    for (let i = 0; i < keys.length; i++) {
      const drawObjectId = keys[i];
      const incoming = incomingMap[drawObjectId];
      if (!incoming) continue;
      const existing = drawObjMapInstance[drawObjectId];
      if (!existing) {
        drawObjMapInstance[drawObjectId] = {
          MapInstance: Array.isArray(incoming.MapInstance) ? [...incoming.MapInstance] : [],
          MapMesh: incoming.MapMesh,
        };
      } else {
        if (!Array.isArray(existing.MapInstance)) existing.MapInstance = [];
        const existingIds = new Set();
        for (let j = 0; j < existing.MapInstance.length; j++) {
          const item = existing.MapInstance[j];
          if (item && item.instanceId != null) existingIds.add(item.instanceId);
        }
        const incomingInstances = Array.isArray(incoming.MapInstance) ? incoming.MapInstance : [];
        for (let j = 0; j < incomingInstances.length; j++) {
          const item = incomingInstances[j];
          if (item && !existingIds.has(item.instanceId)) {
            existing.MapInstance.push(item);
            existingIds.add(item.instanceId);
          }
        }
        if (!existing.MapMesh && incoming.MapMesh) {
          existing.MapMesh = incoming.MapMesh;
        }
      }
    }
  }

  if (Array.isArray(instanceToDrawObject)) {
    for (let i = 0; i < instanceToDrawObject.length; i++) {
      const item = instanceToDrawObject[i];
      if (!item || item.instanceId == null) continue;
      if (!instanceToInstancedMeshMap.get(item.instanceId)) {
        instanceToInstancedMeshMap.set(item.instanceId, {
          instanceId: item.instanceId,
          drawObjectId: item.drawObjectId,
        });
      }
    }
  }
}

/**
 * 处理 InstancedMesh 类型模型的核心方法（优化版本，支持批量处理）
 * @param {Object} modelGroup - 模型组对象
 * @param {Array} instances - 实例数组
 * @param {Array} drawObjs - 绘制对象数组，包含几何数据
 * @param {string} type - 类型
 * @param {Object} scene - 场景对象
 * @param {string} customColor - 自定义颜色
 * @param {Object} meshNameConfig - 网格名称配置
 * @param {string} customOpacity - 自定义透明度
 * @param {Object} options - 选项配置
 * @returns {Object} 模型组对象
 */
async function handleInstancedMeshModel(
  modelGroup,
  instances,
  drawObjs,
  type,
  scene,
  customColor,
  meshNameConfig,
  customOpacity,
  options = {}
) {
  // const getObjectByName = (name, passType = 'group') => {
  //   if (!scene) return [];
  //   const object = [];
  //   const instancedMeshProps = instanceToInstancedMeshMap.get(name);
  //   scene.traverse(item => {
  //     const tempName = instancedMeshProps ? instancedMeshProps.drawObjectId : name;
  //     if (item.name == tempName && item.type.toLowerCase() != passType.toLowerCase()) {
  //       object.push(item);
  //     }
  //   });
  //   return object;
  // };

  // 如果是新的加载会话，重置状态
  if (options.resetState) {
    resetProcessingState();
  }

  let mappingResult = null;
  if (Array.isArray(instances) && instances.length) {
    try {
      mappingResult = await requestInstancedMapping(instances, drawObjs || []);
    } catch (e) {
      mappingResult = null;
    }
  }

  if (mappingResult) {
    mergeInstancedMappingResult(mappingResult);
  } else {
    const batchSize = options.batchSize || 50;
    for (let i = 0; i < instances.length; i += batchSize) {
      const batch = instances.slice(i, i + batchSize);
      batch.forEach(instance => {
        formatInstancedMap(instance, drawObjs);
      });
    }

    for (let i = 0; i < instances.length; i++) {
      const instance = instances[i];
      const drawObjectId = instance.drawObject;

      if (!instanceToInstancedMeshMap.get(instance.instanceId)) {
        instanceToInstancedMeshMap.set(instance.instanceId, {
          instanceId: instance.instanceId,
          drawObjectId,
        });
      }
    }
  }

  // 第二阶段：遍历所有实例进行处理（增量渲染优化）
  // const processedInThisBatch = new Set();

  // 预先建立映射表，避免在循环中频繁调用 getObjectByName
  const existingGroupsMap = new Map();
  if (modelGroup && modelGroup.children) {
    modelGroup.children.forEach(child => {
      if (child.name) {
        existingGroupsMap.set(child.name, child);
      }
    });
  }

  const immediateUpdate = options.immediateUpdate || false;

  for (let i = 0; i < instances.length; i++) {
    const instance = instances[i];
    const drawObjectId = instance.drawObject;
    const instanceId = instance.instanceId;

    // 检查该drawObject是否已经在本批次或之前处理过
    // if (processedDrawObjects.has(drawObjectId) || processedInThisBatch.has(drawObjectId)) {
    //   continue; // 跳过已处理的drawObject
    // }

    const drawObjInstance = drawObjMapInstance[drawObjectId];

    if (drawObjInstance?.MapMesh?.length > 0) {
      // 检查modelGroup中是否已存在同名的group
      // const existingGroup = getObjectByName(drawObjectId)[0];
      const existingGroup = existingGroupsMap.get(drawObjectId);

      if (!existingGroup) {
        const group = createInstancedGroup(
          drawObjInstance,
          instance,
          meshNameConfig,
          customColor,
          customOpacity,
          options
        );

        if (group) {
          // console.log('add(group)')
          modelGroup.add(group);
          if (immediateUpdate) {
            // 立即更新矩阵世界，确保位置正确
            group.updateMatrixWorld(true);
          }

          // 更新映射表，以便后续循环能找到新添加的组
          if (group.name) {
            existingGroupsMap.set(group.name, group);
          }

          // 标记该drawObject已处理
          // processedDrawObjects.add(drawObjectId);
          // processedInThisBatch.add(drawObjectId);
        }
      } else {
        appendInstanceToInstancedGroup(existingGroup, drawObjInstance, instance, customColor);
      }
    }
  }

  // console.log(instanceToInstancedMeshMap)
  // return modelGroup;
}

/**
 * 创建实例化组（从handleInstancedMeshModel中提取的逻辑）
 * @param {Object} drawObj - 绘制对象数据
 * @param {Object} instance - 实例数据
 * @param {Object} meshNameConfig - 网格名称配置
 * @param {string} customColor - 自定义颜色
 * @param {string} customOpacity - 自定义透明度
 * @param {Object} options - 选项配置
 * @returns {THREE.Group} 创建的组对象
 */
function createInstancedGroup(
  drawObj,
  instance,
  meshNameConfig,
  customColor,
  customOpacity,
  options
) {
  const group = new THREE.Group();

  // 设置组的基本属性
  for (const key in meshNameConfig) {
    group.userData[key] = meshNameConfig[key];
  }

  // 可配置的用户数据
  for (const key in options.userData) {
    group.userData[key] = options.userData[key];
  }

  // group.name = options.defineGroupPreName ? `${options.defineGroupPreName}:${instance.drawObject}` : instance.drawObject;
  group.name = instance.drawObject;
  group.userData.isInstancedMeshGroup = true;
  group.userData.category = instance.category;
  group.userData.instanceId = instance.drawObject;

  // const instanceCount = drawObj.MapInstance.length;
  const instanceCount = 100; // 预分配容量，动态增加实例
  const activeInstanceCount = Array.isArray(drawObj.MapInstance) ? drawObj.MapInstance.length : 0;

  // 处理每个网格
  drawObj.MapMesh?.forEach(mesh => {
    // console.log(mesh)
    // console.log(instance)
    // if(mesh.prop.color[0] == 0 && mesh.prop.color[1] == 142 && mesh.prop.color[2] == 142){
    //   return
    // }
    // customColor 是原本初始化整个模型颜色的 这里暂时放弃
    // (mesh, instance.drawObject, instanceCount, customColor, customOpacity
    let color = options.colorConfig.get(instance.instanceId);

    const model = drawModel(mesh, instance.drawObject, instanceCount, color, customOpacity, {
      // lodLevel: drawObj.lodLevel || 2,
      activeInstanceCount,
      ...options,
    });

    if (!model) {
      return;
    }

    // 设置网格名称
    let meshName = '';
    for (const key in meshNameConfig) {
      model.userData[key] = meshNameConfig[key];
      // meshName += ':' + meshNameConfig[key];
    }

    // 批量设置实例矩阵和颜色（性能优化）
    // setInstanceMatricesAndColors(model, drawObj, mesh, meshName, customColor, options);
    setInstanceMatricesAndColors(model, drawObj, mesh, meshName, color, options);

    group.add(model);
  });

  return group;
}

/**
 * 批量设置实例矩阵和颜色（性能优化版本）
 * @param {THREE.InstancedMesh} model - 实例化网格模型
 * @param {Object} drawObj - 绘制对象数据
 * @param {Object} mesh - 网格数据
 * @param {string} meshName - 网格名称
 * @param {string} customColor - 自定义颜色
 */
function setInstanceMatricesAndColors(model, drawObj, mesh, meshName, customColor, options) {
  const instances = drawObj.MapInstance;
  const { color } = mesh.prop;
  const sourceVisible = mesh.prop?.sourceVisible === false ? false : true;

  // 预计算颜色
  const meshColor = customColor
    ? new THREE.Color(customColor)
    : new THREE.Color(`rgb(${color[0]}, ${color[1]}, ${color[2]})`);

  // 批量处理实例
  instances.forEach((item, index) => {
    // 设置用户数据
    model.userData.instanceIndex = index;
    model.userData.instanceId = item.instanceId;
    model.userData.primId = mesh.prmid;
    // model.userData.lodLevel = drawObj.lodLevel || 2;
    if (index == 0) {
      model.name = meshName !== '' ? item.instanceId + meshName : item.instanceId;
    }

    let instanceProps = {
      instanceIndex: index, // 序号来定位到底是哪个instancedMesh
      instancedMeshId: model.name, // 多个instancedMesh共用一个name，用于查找模型
      instanceId: item.instanceId, // instancedMesh实际的modelId
      primId: mesh.prmid,
      sourceVisible,
      visible: sourceVisible,
      // lodLevel: drawObj.lodLevel || 2,
    };
    if (!model.userData.instancesMap) {
      model.userData.instancesMap = new Map([[item.instanceId, instanceProps]]);
    } else {
      model.userData.instancesMap.set(item.instanceId, instanceProps);
    }

    // const instancedMesh = instanceToInstancedMeshMap.get(item.instanceId);

    const m4 = composeInstanceMatrix(item, mesh, model.geometry);
    model.setMatrixAt(index, m4);

    const normalSignAttr = model.geometry && model.geometry.getAttribute('instanceNormalSign');
    if (normalSignAttr && normalSignAttr.array && index < normalSignAttr.array.length) {
      normalSignAttr.array[index] = getInstanceNormalSign(m4);
    }

    const copyMatrix = new THREE.Matrix4().copy(m4);
    model.userData.copyMatrix = copyMatrix;

    const temp = model.userData.instancesMap.get(item.instanceId);
    temp.copyMatrix = copyMatrix;
    if (sourceVisible === false) {
      const offsetMatrix = new THREE.Matrix4()
        .copy(copyMatrix)
        .makeTranslation(9999999, 9999999, 9999999);
      model.setMatrixAt(index, offsetMatrix);
    }

    // 设置颜色
    model.setColorAt(index, meshColor);
  });

  // 标记需要更新
  if (model.instanceMatrix) {
    model.instanceMatrix.needsUpdate = true;
  }
  if (model.instanceColor) {
    model.instanceColor.needsUpdate = true;
  }
  const normalSignAttr = model.geometry && model.geometry.getAttribute('instanceNormalSign');
  if (normalSignAttr) {
    normalSignAttr.needsUpdate = true;
  }

  if (Array.isArray(instances)) {
    const capacity =
      model.instanceMatrix && typeof model.instanceMatrix.count === 'number'
        ? model.instanceMatrix.count
        : model.count;
    model.count = Math.min(instances.length, capacity);
    model.userData.instanceCapacity = capacity;
    model.userData.instanceCount = model.count;
    model.userData.sourceVisible = sourceVisible;
  }
}

function appendInstanceToInstancedGroup(group, drawObj, instance, customColor) {
  if (!group || !drawObj || !instance) return;
  const meshes = Array.isArray(drawObj.MapMesh) ? drawObj.MapMesh : [];
  if (meshes.length === 0) return;
  const meshByPrimId = new Map();
  for (let i = 0; i < meshes.length; i++) {
    const m = meshes[i];
    if (m && m.prmid !== undefined) meshByPrimId.set(m.prmid, m);
  }

  const children = Array.isArray(group.children) ? group.children : [];
  for (let i = 0; i < children.length; i++) {
    const obj = children[i];
    if (!obj || !obj.isInstancedMesh) continue;
    const primId = obj.userData ? obj.userData.primId : undefined;
    const mesh = meshByPrimId.get(primId);
    if (!mesh) continue;
    appendInstanceToInstancedMesh(obj, drawObj, mesh, instance, customColor);
  }
}

function appendInstanceToInstancedMesh(model, drawObj, mesh, instance, customColor) {
  if (!model || !model.isInstancedMesh) return;
  if (!instance || !instance.instanceId) return;

  const capacity =
    model.instanceMatrix && typeof model.instanceMatrix.count === 'number'
      ? model.instanceMatrix.count
      : model.count;
  const currentCount = typeof model.count === 'number' ? model.count : 0;
  if (currentCount >= capacity) return;

  if (!model.userData) model.userData = {};
  if (!model.userData.instancesMap) model.userData.instancesMap = new Map();
  if (model.userData.instancesMap.has(instance.instanceId)) return;

  const rawColor = mesh && mesh.prop ? mesh.prop.color : undefined;
  const sourceVisible = mesh && mesh.prop && mesh.prop.sourceVisible === false ? false : true;
  const colorArr = Array.isArray(rawColor)
    ? rawColor
    : typeof rawColor === 'string'
    ? rawColor.split(',')
    : [255, 255, 255];
  const meshColor = customColor
    ? new THREE.Color(customColor)
    : new THREE.Color(`rgb(${colorArr[0]}, ${colorArr[1]}, ${colorArr[2]})`);

  if (!mesh) return;

  const m4 = composeInstanceMatrix(instance, mesh, model.geometry);
  const renderMatrix =
    sourceVisible === false
      ? new THREE.Matrix4().copy(m4).makeTranslation(9999999, 9999999, 9999999)
      : m4;
  model.setMatrixAt(currentCount, renderMatrix);
  if (model.instanceMatrix) model.instanceMatrix.needsUpdate = true;

  const normalSignAttr = model.geometry && model.geometry.getAttribute('instanceNormalSign');
  if (normalSignAttr && normalSignAttr.array && currentCount < normalSignAttr.array.length) {
    normalSignAttr.array[currentCount] = getInstanceNormalSign(m4);
    normalSignAttr.needsUpdate = true;
  }

  const copyMatrix = new THREE.Matrix4().copy(m4);
  model.userData.copyMatrix = copyMatrix;
  const instanceProps = {
    instanceIndex: currentCount,
    instancedMeshId: model.name,
    instanceId: instance.instanceId,
    primId: mesh.prmid,
    sourceVisible,
    visible: sourceVisible,
    // lodLevel: drawObj.lodLevel || 2,
    copyMatrix,
  };
  model.userData.instancesMap.set(instance.instanceId, instanceProps);

  model.setColorAt(currentCount, meshColor);
  if (model.instanceColor) model.instanceColor.needsUpdate = true;

  const opacityAttr =
    model.geometry && model.geometry.getAttribute
      ? model.geometry.getAttribute('opacity')
      : undefined;
  if (opacityAttr && opacityAttr.array && currentCount < opacityAttr.array.length) {
    opacityAttr.array[currentCount] = opacityAttr.array[0] !== undefined ? opacityAttr.array[0] : 1;
    opacityAttr.needsUpdate = true;
  }

  model.count = currentCount + 1;
  model.userData.instanceCapacity = capacity;
  model.userData.instanceCount = model.count;
  model.userData.sourceVisible = sourceVisible;
}

/**
 * 构建实例模型映射表
 * @param {Object} instance - 实例对象，包含绘制对象ID和实例ID等数据
 * @param {Array} drawObjs - 绘制对象数组，包含几何数据
 */
function formatInstancedMap(instance, drawObjs) {
  const { drawObject } = instance; // 提取绘制对象ID

  // 检查是否已存在该绘制对象的映射条目
  if (drawObjMapInstance[drawObject]) {
    // 查找是否已存在相同实例ID的记录
    const hasInstance = drawObjMapInstance[drawObject]['MapInstance'].find(item => {
      return item.instanceId == instance.instanceId;
    });

    // 不存在则添加新实例
    if (!hasInstance) {
      drawObjMapInstance[drawObject]['MapInstance'].push(instance);
    }
  } else {
    // 新建绘制对象条目
    drawObjMapInstance[drawObject] = {
      MapInstance: [instance], // 存储实例数组
    };

    // 关联绘制对象的几何数据
    drawObjs.forEach(item => {
      let hasMesh = false;
      if (item && Array.isArray(item.geoms)) {
        const found = item.geoms.some(g => g.prmid === drawObject);
        if (found) {
          hasMesh = true;
        }
      }
      if (hasMesh) {
        // 将几何数据映射到对应的绘制对象
        drawObjMapInstance[drawObject].MapMesh = item.geoms;
        // drawObjMapInstance[drawObject].lodLevel = item.lodLevel || 2;
      }
    });
  }
}

/**
 * 将数组数据转换为键值对形式的 JSON 对象
 * @param {Array} data - 包含对象的数组，每个对象都有一个 drawObjId 属性
 * @returns {Object}
 */
function formatDrawObjs(data) {
  const obj = {};
  data.forEach(item => {
    obj[item.drawObjId] = item;
  });
  return obj;
}
/**
 * 根据几何体类型绘制对应的3D模型
 * @param {Object} geom - 几何数据对象，包含类型、属性等绘制信息
 * @param {String} instanceName - 实例名称，用于标识模型实例
 * @param {Number} instanceCount - 实例化渲染的数量（用于InstancedMesh）
 * @returns {THREE.Object3D} 返回创建的3D模型对象
 */
function drawModel(geom, instanceName, instanceCount, nColor, nOpacity, options = {}) {
  let model;
  // 处理二维几何体（普通2D图形和特殊2D图形）
  if (geom.type == GEOM_TYPES.geom_2d || geom.type == GEOM_TYPES.geom_2d_others) {
    model = draw2Dmodel(geom, instanceName, instanceCount, nColor, nOpacity, options); // TODO 该类型调试中
    // 处理二维文本类型
  } else if (isTextType(geom.type)) {
    model = drawText(geom, instanceName, instanceCount, options);
    // 处理各种曲线类型（圆形、圆弧、椭圆、椭圆弧）
  } else if (
    geom.type == GEOM_TYPES.geom_2d_circle ||
    geom.type == GEOM_TYPES.geom_2d_arc ||
    geom.type == GEOM_TYPES.geom_2d_ellipse ||
    geom.type == GEOM_TYPES.geom_2d_ellipseArc
  ) {
    model = drawCurves(geom, instanceName, instanceCount, nColor, nOpacity, options); // TODO 该类型调试中
    // 处理三维几何体（普通3D模型和OBJ模型）
  } else if (geom.type == GEOM_TYPES.geom_3d || geom.type == GEOM_TYPES.geom_3d_obj) {
    model = draw3Dmodel(geom, instanceName, instanceCount, nColor, nOpacity, options);
  }
  return model;
}

/**
 * 判断几何类型是否为文本类型
 * @param {number} type - 几何类型枚举值，参考GEOM_TYPES中的定义
 * @returns {boolean} 是否为文本类型（2D/3D 单行或多行文本）
 */
function isTextType(type) {
  return (
    type == GEOM_TYPES.geom_2d_text ||
    type == GEOM_TYPES.geom_2d_mtext ||
    type == GEOM_TYPES.geom_3d_text ||
    type == GEOM_TYPES.geom_3d_mtext
  );
}

/**
 * 绘制曲线
 *
 * @param {Object} geom- 包含曲线信息的几何体对象
 * @param {String} instanceName- 曲线实例的名称
 * @return {Object}- 包含曲线模型和曲线信息的对象
 */
function drawCurves(geom, instanceName, instanceCount, nColor, nOpacity, options = {}) {
  let { points, normals } = geom;
  let aX = points[0];
  let aY = points[1];
  let aZ = points[2];
  let xrad = points[3];
  let yrad = points[4];
  let startAngle = points[5] ? (points[5] * Math.PI) / 180 : 0;
  let endAngle = points[6] ? (points[6] * Math.PI) / 180 : 0;

  let curve = new THREE.EllipseCurve(
    0,
    0,
    xrad,
    yrad,
    startAngle,
    endAngle,
    false // 曲线方向为逆时针
  );
  let curvePoints = curve.getPoints(50);
  let list = [];
  for (let i = 0; i < curvePoints.length; i++) {
    const { x, y } = curvePoints[i];
    list.push(x);
    list.push(parseFloat(y));

    // // 根据角度计算动态 Z 值（例如正弦波动）
    // const angle = Math.atan2(y, x); // 当前点的极角
    // const z = Math.sin(angle * 2) * 2; // Z轴动态变化
    // list.push(z); // 将原始的 z 坐标添加到列表中
    list.push(parseFloat(0)); // 将原始的 z 坐标添加到列表中
  }

  const model = draw2Dmodel(
    {
      ...geom,
      points: list,
      normals,
    },
    instanceName,
    instanceCount,
    nColor,
    nOpacity,
    options
  );
  // model.rotation.x = -Math.PI / 2;
  // model.position.set(aX, aY, aZ);
  const matrix = new THREE.Matrix4();
  matrix.identity().makeTranslation(aX, aY, aZ);
  model.applyMatrix4(matrix);

  model.userData.instanceName = instanceName;
  return model;
}
/**
 * 创建三维模型实例化网格
 * @param {Object} geom - 几何数据对象，包含顶点、法线、材质等信息
 * @param {String} instanceName - 实例唯一标识名称
 * @param {Number} instanceCount - 需要创建的实例数量
 * @returns {THREE.InstancedMesh} - 返回创建的三维实例化网格对象
 */
function draw3Dmodel(
  geom,
  instanceName,
  instanceCount,
  nColor,
  nOpacity,
  options = {},
  targetMesh = undefined
) {
  // const { lodLevel } = options;

  // 解构几何数据中的自定义几何体和材质
  const {
    geometry: customGeometry,
    material: customMaterial,
    triangles,
    points,
    normals,
    prop = {},
    max,
    min,
    type,
  } = geom;

  // 如果传入了现有 mesh，则进行几何体切换（不重新创建 Mesh）
  // if (targetMesh && targetMesh.isInstancedMesh) {
  //   // 计算透明度，若现有材质已设置则沿用
  //   let opacityFromMat = (targetMesh.material && targetMesh.material.userData && targetMesh.material.userData.nOpacity) ? targetMesh.material.userData.nOpacity : undefined;
  //   let colors = Array.isArray(prop.color) ? prop.color : (typeof prop.color === 'string' ? prop.color.split(',') : [255, 255, 255, 1]);
  //   let fallbackOpacity = colors[3] !== undefined ? colors[3] : 1;
  //   const opacity = opacityFromMat !== undefined ? opacityFromMat : (nOpacity !== undefined ? nOpacity : fallbackOpacity);

  //   // 根据目标 lodLevel 切换几何体
  //   if (lodLevel === PRIMITIVE_TYPE.full) {
  //     const bufGeo = new THREE.BufferGeometry();
  //     // 设置索引
  //     if (triangles && triangles.length) {
  //       bufGeo.setIndex(triangles);
  //     } else {
  //       bufGeo.setIndex(null);
  //     }
  //     // 设置位置
  //     if (points && points.length) {
  //       const position = new Float32Array(points);
  //       bufGeo.setAttribute('position', new THREE.BufferAttribute(position, 3));
  //     }
  //     // 设置法线或计算
  //     if (normals && normals.length) {
  //       const normal = new Float32Array(normals);
  //       bufGeo.setAttribute('normal', new THREE.BufferAttribute(normal, 3));
  //     } else {
  //       bufGeo.computeVertexNormals();
  //     }

  //     // 绑定实例透明度属性
  //     const opacities = new Float32Array(instanceCount);
  //     for (let i = 0; i < instanceCount; i++) opacities[i] = opacity;
  //     bufGeo.setAttribute('opacity', new THREE.InstancedBufferAttribute(opacities, 1));

  //     // 包围体
  //     bufGeo.computeBoundingBox();
  //     bufGeo.computeBoundingSphere();

  //     // 替换旧几何体
  //     if (targetMesh.geometry) targetMesh.geometry.dispose();
  //     targetMesh.geometry = bufGeo;
  //     targetMesh.userData.lodLevel = PRIMITIVE_TYPE.full;
  //     return; // 更新完成，无需返回新mesh
  //   }

  //   if (lodLevel === PRIMITIVE_TYPE.onlyBounding) {
  //     // 使用 min/max 或从现有几何体计算包围盒
  //     let bbox;
  //     if (Array.isArray(min) && Array.isArray(max) && min.length === 3 && max.length === 3) {
  //       bbox = { min: { x: min[0], y: min[1], z: min[2] }, max: { x: max[0], y: max[1], z: max[2] } };
  //     } else {
  //       // 从现有几何体计算
  //       const geo = targetMesh.geometry;
  //       geo.computeBoundingBox();
  //       const bb = geo.boundingBox;
  //       bbox = { min: bb.min, max: bb.max };
  //     }
  //     const width = Math.max(0.0001, bbox.max.x - bbox.min.x);
  //     const height = Math.max(0.0001, bbox.max.y - bbox.min.y);
  //     const depth = Math.max(0.0001, bbox.max.z - bbox.min.z);
  //     const cx = (bbox.min.x + bbox.max.x) / 2;
  //     const cy = (bbox.min.y + bbox.max.y) / 2;
  //     const cz = (bbox.min.z + bbox.max.z) / 2;
  //     const bboxGeometry = new THREE.BoxGeometry(width, height, depth);
  //     bboxGeometry.translate(cx, cy, cz);

  //     // 绑定实例透明度属性（保持现有透明度）
  //     const opacities = new Float32Array(instanceCount);
  //     for (let i = 0; i < instanceCount; i++) opacities[i] = opacity;
  //     bboxGeometry.setAttribute('opacity', new THREE.InstancedBufferAttribute(opacities, 1));

  //     if (targetMesh.geometry) targetMesh.geometry.dispose();
  //     targetMesh.geometry = bboxGeometry;
  //     targetMesh.userData.lodLevel = PRIMITIVE_TYPE.onlyBounding;
  //     return; // 更新完成，无需返回新mesh
  //   }

  //   // 其它模式不处理
  //   return;
  // }

  // 未传入现有 mesh：按原逻辑创建新 InstancedMesh
  let geometry = customGeometry || new THREE.BufferGeometry();
  // if (lodLevel == PRIMITIVE_TYPE.onlyBounding) {
  //   if (Array.isArray(min) && Array.isArray(max) && min.length === 3 && max.length === 3) {
  //     const width = Math.max(0.0001, max[0] - min[0]);
  //     const height = Math.max(0.0001, max[1] - min[1]);
  //     const depth = Math.max(0.0001, max[2] - min[2]);
  //     const cx = (min[0] + max[0]) / 2;
  //     const cy = (min[1] + max[1]) / 2;
  //     const cz = (min[2] + max[2]) / 2;
  //     const bboxGeometry = new THREE.BoxGeometry(width, height, depth);
  //     bboxGeometry.translate(cx, cy, cz);
  //     geometry = bboxGeometry;
  //   }
  // } else {
  //   if (triangles && triangles.length) {
  //     geometry.setIndex(triangles);
  //   }
  //   if (points && points.length) {
  //     const position = new Float32Array(points);
  //     geometry.setAttribute('position', new THREE.BufferAttribute(position, 3));
  //   }
  //   if (normals && normals.length) {
  //     const normal = new Float32Array(normals);
  //     geometry.setAttribute('normal', new THREE.BufferAttribute(normal, 3));
  //   }
  // }

  // triangle int16Array 索引时，需要转换为 uint16Array
  if (!customGeometry) {
    if (triangles && triangles.length) {
      geometry.setIndex(triangles instanceof Int16Array ? Array.from(triangles.buffer) : triangles);
    }
    if (points && points.length) {
      const position = new Float32Array(points);
      geometry.setAttribute('position', new THREE.BufferAttribute(position, 3));
    }
    if (normals && normals.length) {
      const normal = new Float32Array(normals);
      geometry.setAttribute('normal', new THREE.BufferAttribute(normal, 3));
    }
  }

  const { color, transparent } = prop;
  let material, mesh, colors, opacity;
  if (Array.isArray(color) && color.length) {
    colors = color;
    opacity = colors[3] || 1;
  } else if (typeof color === 'string') {
    colors = color.split(',');
    opacity = colors[3] || 1;
  } else {
    colors = [255, 255, 255];
    opacity = 1;
  }

  // 处理transparent透明度
  opacity = 1 - transparent;

  const finalOpacity =
    nOpacity !== undefined && nOpacity !== null && nOpacity !== '' ? nOpacity : opacity;

  // 判断是否全透明
  const isTransparent = finalOpacity < 1.0;

  let materialOptions = {
    userData: {
      nColor: nColor
        ? new THREE.Color(nColor)
        : new THREE.Color(`rgb(${colors[0]}, ${colors[1]}, ${colors[2]})`),
      nOpacity: finalOpacity,
      // 这里记录模型原本的颜色  做颜色配置时 恢复原本的颜色用的
      oColor: new THREE.Color(`rgb(${colors[0]}, ${colors[1]}, ${colors[2]})`),
    },
    // side: THREE.DoubleSide,
    // transparent: true,
    // forceSinglePass: true,
    side: THREE.DoubleSide,
    transparent: true,
    opacity: finalOpacity,
    depthWrite: true,
    forceSinglePass: true,
  };

  customMaterial && Object.assign(customMaterial, materialOptions);
  material =
    customMaterial ||
    new THREE.MeshStandardMaterial({
      ...materialOptions,
      roughness: 0.6,
      metalness: 0.5,
      envMapIntensity: 1,
    });

  const activeInstanceCount = Math.max(
    0,
    Math.min(
      instanceCount,
      typeof options.activeInstanceCount === 'number' ? options.activeInstanceCount : instanceCount
    )
  );

  const opacities = new Float32Array(instanceCount);
  const instanceNormalSigns = new Float32Array(instanceCount);
  for (let i = 0; i < instanceCount; i++) {
    opacities[i] = opacity;
    instanceNormalSigns[i] = 1;
  }
  geometry.setAttribute('opacity', new THREE.InstancedBufferAttribute(opacities, 1));
  geometry.setAttribute(
    'instanceNormalSign',
    new THREE.InstancedBufferAttribute(instanceNormalSigns, 1)
  );

  if (!customMaterial) {
    material.onBeforeCompile = shader => {
      const normalFragmentBegin = THREE.ShaderChunk.normal_fragment_begin.replace(
        'float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;',
        'float faceDirection = (gl_FrontFacing ? 1.0 : - 1.0) * vInstanceNormalSign;'
      );

      shader.vertexShader = `
          attribute float opacity; // 实例透明度属性
          attribute float instanceNormalSign; // 镜像矩阵法线修正
          varying float vAlpha;
          varying float vInstanceNormalSign;
          ${shader.vertexShader}
      `.replace(
        '#include <begin_vertex>',
        `
          #include <begin_vertex>
          vAlpha = opacity; // 传递透明度到片段着色器
          vInstanceNormalSign = instanceNormalSign;
          `
      );
      shader.fragmentShader = `
          varying float vAlpha;
          varying float vInstanceNormalSign;
          ${shader.fragmentShader}
      `
        .replace('#include <normal_fragment_begin>', normalFragmentBegin)
        .replace(
          '#include <alphatest_fragment>',
          `
          #include <alphatest_fragment>
          diffuseColor.a *= vAlpha; // 应用实例透明度
          `
        );
    };
    material.customProgramCacheKey = () => 'instance-opacity-normal-sign-v2';
  }

  // 针对 MeshLineMaterial 开启实例化支持
  if (material.type === 'MeshLineMaterial') {
    material.defines = material.defines || {};
    material.defines.USE_INSTANCING = '';

    if (!material.userData.meshlineInstancingPatched) {
      material.vertexShader = material.vertexShader.replace(
        'mat4 m = projectionMatrix * modelViewMatrix;',
        'mat4 m = projectionMatrix * modelViewMatrix * instanceMatrix;'
      );
      material.userData.meshlineInstancingPatched = true;
      material.needsUpdate = true;
    }
  }

  mesh = new THREE.InstancedMesh(geometry, material, instanceCount);
  mesh.count = activeInstanceCount;
  const { visible, sourceVisible } = prop;
  mesh.visible = visible !== undefined ? visible : true;
  mesh.userData.drawObjectId = instanceName;
  mesh.userData.sourceVisible = sourceVisible === false ? false : true;
  mesh.userData.is3D = type == GEOM_TYPES.geom_3d || type == GEOM_TYPES.geom_3d_obj;
  mesh.userData.transparent = isTransparent;
  mesh.userData.instanceCapacity = instanceCount;
  mesh.userData.instanceCount = activeInstanceCount;
  return mesh;
}

/**
 * 绘制 2D 模型的方法
 *
 * @param {Object} geom - 包含几何体信息的对象
 * @param {String} instanceName - 模型实例的名称
 * @returns {Object} - 包含所有 2D 模型的组对象
 */
function draw2Dmodel(geom, instanceName, instanceCount, nColor, nOpacity, options = {}) {
  const points = geom.points;
  const normals = geom.normals;
  const geometry = new THREE.BufferGeometry();

  if (points && points.length) {
    const position = new Float32Array(points);
    geometry.setAttribute('position', new THREE.BufferAttribute(position, 3));
  }

  if (normals && normals.length) {
    const normal = new Float32Array(normals);
    geometry.setAttribute('normal', new THREE.BufferAttribute(normal, 3));
  }

  const { color, linewidth } = geom.prop;
  const formatLinewidth = (linewidth < 1 ? linewidth * 50 : linewidth) || 5;
  const material = new MeshLineMaterial({
    color: new THREE.Color(`rgb(${color[0]}, ${color[1]}, ${color[2]})`),
    lineWidth: formatLinewidth,
  });

  const lineGeometry = new MeshLineGeometry();
  lineGeometry.setPoints(geometry);

  const model = draw3Dmodel(
    {
      prop: geom.prop,
      geometry: lineGeometry,
      material,
    },
    instanceName,
    instanceCount,
    nColor,
    nOpacity,
    options
  );
  // mesh.raycast = raycast;

  model.userData.instanceName = instanceName;
  // group.add(line);

  return model;
}

// drawText 方法，用于渲染 2D 或 3D 文字
function drawText(geom, instanceName, instanceCount, options = {}) {
  const { prop, text, points, normals } = geom;
  const { color, linewidth, fontsize, fontname, rotate, italic, widthscale } = prop;

  var loader = new FontLoader();
  var font = loader.parse(helvetikerFont);
  options = {
    font: font, // 字体格式
    size: fontsize / 2 || 20, // 字体大小 TODO
    height: 1, // 字体深度
    curveSegments: 11, // 曲线控制点数
    bevelEnabled: true, // 斜角
    bevelThickness: 0.1, // 斜角的深度
    bevelSize: 1, // 斜角的大小
    depth: 1,
    bevelSegments: 1, // 斜角段数
  };

  let geometry = new TextGeometry(`${text}`, options);

  const mesh = draw3Dmodel(
    {
      prop,
      geometry,
      normals,
    },
    instanceName,
    instanceCount,
    options
  );

  // 创建平移矩阵并应用
  // const matrix = new THREE.Matrix4();
  // matrix.identity().makeTranslation(points[0], points[1], points[2]);
  // mesh.applyMatrix4(matrix);
  // points && mesh.position.set(points[0], points[1], points[2]);

  // if (stageId == STAGE_MODEL_TYPE.PID) {
  //   mesh.translateX(-(fontsize / 2));
  //   mesh.translateY(-(fontsize / 2));
  // }

  // points && mesh.position.set(points[0], points[1], points[2]);
  // if (rotate) {
  //   mesh.rotateY(rotate);
  // }
  // mesh.rotateX(-Math.PI / 2);
  // mesh.translateX(-(fontsize / 2.5));
  // mesh.translateY(-(fontsize / 2.5));

  mesh.userData.instanceName = instanceName;
  return mesh;
}

/**
 *
 * @param {number} align 对齐方式
 * @param {object} geometry 几何体
 * @returns
 */
function createAlignedText(align = TextAlign.TextLeftBottom, geometry) {
  // 计算几何体包围盒用于对齐计算
  geometry.computeBoundingBox();
  const bbox = geometry.boundingBox;

  // 初始化水平和垂直偏移量
  let offsetX = 0;
  let offsetY = 0;

  // 水平对齐处理（X轴方向）
  switch (align) {
    // 左对齐系列（文本左边界对齐原点）
    case TextAlign.TextLeft:
    case TextAlign.TextLeftBottom:
    case TextAlign.TextLeftMiddle:
    case TextAlign.TextLeftTop:
      offsetX = -bbox.min.x; // 左边界对齐
      break;

    // 居中对齐系列（文本中心对齐原点）
    case TextAlign.TextCenter:
    case TextAlign.TextCenterBottom:
    case TextAlign.TextCenterMiddle:
    case TextAlign.TextCenterTop:
      offsetX = -(bbox.min.x + bbox.max.x) / 2; // 水平居中
      break;

    // 右对齐系列（文本右边界对齐原点）
    case TextAlign.TextRight:
    case TextAlign.TextRightBottom:
    case TextAlign.TextRightMiddle:
    case TextAlign.TextRightTop:
      offsetX = -bbox.max.x; // 右边界对齐
      break;
  }

  // 垂直对齐处理（Y轴方向）
  switch (align) {
    // 垂直居中系列
    case TextAlign.TextMiddle:
    case TextAlign.TextLeftMiddle:
    case TextAlign.TextCenterMiddle:
    case TextAlign.TextRightMiddle:
      offsetY = -(bbox.min.y + bbox.max.y) / 2; // 垂直居中
      break;

    // 顶部对齐系列
    case TextAlign.TextTop:
    case TextAlign.TextLeftTop:
    case TextAlign.TextCenterTop:
    case TextAlign.TextRightTop:
      offsetY = -bbox.max.y; // 顶部对齐
      break;

    // 底部对齐系列
    case TextAlign.TextBottom:
    case TextAlign.TextLeftBottom:
    case TextAlign.TextCenterBottom:
    case TextAlign.TextRightBottom:
      offsetY = -bbox.min.y; // 底部对齐
      break;
  }

  // 创建对齐变换矩阵
  const alignMatrix = new THREE.Matrix4();
  alignMatrix.identity().makeTranslation(offsetX, offsetY, 0);

  return alignMatrix;
}

export {
  handleInstancedMeshModel,
  resetProcessingState,
  PRIMITIVE_TYPE,
  draw3Dmodel,
  getDrawObjectInstance,
  instanceToInstancedMeshMap,
};
