import fs from "node:fs";

interface Vertex {
  x: number;
  y: number;
  z: number;
}

interface Face {
  v1: number;
  v2: number;
  v3: number;
  v4: number;
}

function convertDatToObj(datFilename: string, objFilename: string): void {
  const lines: string[] = fs.readFileSync(datFilename, "utf-8").split("\n");

  // 检查对称性标志
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  // @ts-expect-error
  const symmetryFlag: boolean = lines[0].split()[1] === "1";
  const vertices: Vertex[] = [];
  const faces: Face[] = [];

  // 开始转换为 .obj 格式
  const objFile = fs.createWriteStream(objFilename);

  // 写入顶点数据
  for (let i = 1; i < lines.length; i++) {
    // 跳过第一行
    if (lines[i].trim() === "0 0. 0. 0.") {
      // 节点表结束标志
      break;
    }
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    // @ts-expect-error
    const parts: string[] = lines[i].split();
    const vertex: Vertex = {
      x: parseFloat(parts[1]),
      y: parseFloat(parts[2]),
      z: parseFloat(parts[3]),
    };
    vertices.push(vertex);
    objFile.write(`v ${vertex.x} ${vertex.y} ${vertex.z}\n`);
  }

  // 如果模型是对称的，添加镜像顶点
  if (symmetryFlag) {
    for (const v of vertices) {
      objFile.write(`v ${v.x} ${-v.y} ${v.z}\n`);
    }
  }

  // 跳过中间的0行和连接表的标题行
  const connectionStartIndex: number = lines.indexOf("0 0. 0. 0.\n") + 2;

  // 写入面数据
  for (let i = connectionStartIndex; i < lines.length; i++) {
    if (lines[i].trim() === "0 0 0 0") {
      // 连接表结束标志
      break;
    }
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    // @ts-expect-error
    const parts: string[] = lines[i].split();
    const face: Face = {
      v1: parseInt(parts[0]),
      v2: parseInt(parts[1]),
      v3: parseInt(parts[2]),
      v4: parseInt(parts[3]),
    };
    faces.push(face);
    objFile.write(`f ${face.v1} ${face.v2} ${face.v3} ${face.v4}\n`);
  }

  // 如果模型是对称的，添加镜像面
  if (symmetryFlag) {
    const offset: number = vertices.length;
    for (const f of faces) {
      // 注意：我们需要改变顶点的顺序来保持法线方向正确
      objFile.write(
        `f ${f.v1 + offset} ${f.v4 + offset} ${f.v3 + offset} ${f.v2 + offset}\n`
      );
    }
  }

  objFile.end();
}

export { convertDatToObj };