import { MathUtils, Vector3, BufferGeometry } from "three";
import { useActiveLayer } from "../../../../store/builder/store";
import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
import { wait } from "@testing-library/user-event/dist/utils";
type DXFData = any; // Replace with actual DXF data type
type DXFEntity = any; // Replace with actual DXF entity type
type WallLineVertex = [Vector3, string, number, string]; // Represents a wall segment with start point, ID, weight, and type
interface Props {
  parsedData?: DXFData; // Parsed DXF file data
  setDxfWallGenerate?: any; // Callback to set generated walls
  objValue: any; // Object position values for offset calculation
  wallThickness: number;
  wallHeight: number;
  outsideMaterial: string;
  insideMaterial: string;
  activeLayer: number; // Active layer for wall points
  addWall: (wall: Wall) => void; // Function to add a wall to the scene
  walls: Wall[]; // Array of walls to be processed
}

/**
 * Processes DXF entities to generate wall points for a blueprint.
 * Handles LINE, LWPOLYLINE, and ARC entity types, converting them to wall segments.
 * Applies unit conversion and positional offsets to all points.
 *
 * @param {Props} params - Configuration parameters
 * @param {DXFData} params.parsedData - Parsed DXF file data
 * @param {Function} params.setDxfWallGenerate - Callback to store generated walls
 * @param {Object} params.objValue - Contains x,y,z offsets for position adjustment
 */
export function getWallPointsFromBlueprint({
  parsedData,
  setDxfWallGenerate,
  objValue,
  wallThickness,
  wallHeight,
  outsideMaterial,
  insideMaterial,
  activeLayer,
  addWall,
  walls,
}: Props) {
  // Early return if no data is provided
  if (!parsedData) return;
  if (!parsedData.entities) return;

  const unit = 1000; // Conversion factor from millimeters to meters
  const wallVertex: any[] = []; // Array to store wall vertices
  const findExistingPoint = (vec: Vector3): Point | undefined => {
    for (const wall of wallVertex) {
      for (const pt of wall.points) {
        const pos = new Vector3(...pt.position);
        if (pos.equals(vec)) return pt;
      }
    }
    return undefined;
  };

  // Process each entity in the DXF file
  parsedData.entities.forEach((entity: DXFEntity) => {
    // Handle LINE entities
    if (entity.type === "LINE" && entity.vertices) {
      // Create start and end vectors with unit conversion and position offset
      const startVec = new Vector3(
        entity.vertices[0].x / unit,
        0.01, // Slightly above ground to avoid z-fighting
        -entity.vertices[0].y / unit // Invert Y-axis to match Three.js coordinate system
      ).add(new Vector3(objValue.x, 0, objValue.z));

      const endVec = new Vector3(
        entity.vertices[1].x / unit,
        0.01,
        -entity.vertices[1].y / unit
      ).add(new Vector3(objValue.x, 0, objValue.z));

      // Create start and end points
      const existingStart = findExistingPoint(startVec);
      const startPoint: Point = existingStart || {
        pointUuid: MathUtils.generateUUID(),
        pointType: "Wall",
        position: [startVec.x, startVec.y, startVec.z],
        layer: activeLayer,
      };

      const existingEnd = findExistingPoint(endVec);
      const endPoint: Point = existingEnd || {
        pointUuid: MathUtils.generateUUID(),
        pointType: "Wall",
        position: [endVec.x, endVec.y, endVec.z],
        layer: activeLayer,
      };

      // Create the wall
      const wallSet: Wall = {
        wallUuid: MathUtils.generateUUID(),
        points: [startPoint, endPoint], // Store start and end points
        outsideMaterial: insideMaterial,
        insideMaterial: outsideMaterial,
        wallThickness: wallThickness,
        wallHeight: wallHeight,
        decals: [],
      };
      wallVertex.push(wallSet); // Store wall segment in array
      // Add the wall to the scene
      // addWall(wallSet);
    }

    // Handle LWPOLYLINE entities (connected line segments)
    else if (entity.type === "LWPOLYLINE" && entity.vertices) {
      let firstPoint: Point | undefined; // Store first point for closing the polyline

      // Process each vertex pair in the polyline
      for (let i = 0; i < entity.vertices.length - 1; i++) {
        // Convert vertices to Three.js vectors with offset
        const startVec = new Vector3(
          entity.vertices[i].x / unit,
          0.01,
          -entity.vertices[i].y / unit
        ).add(new Vector3(objValue.x, 0, objValue.z));

        const endVec = new Vector3(
          entity.vertices[i + 1].x / unit,
          0.01,
          -entity.vertices[i + 1].y / unit
        ).add(new Vector3(objValue.x, 0, objValue.z));

        // Create start and end points
        const existingStart = findExistingPoint(startVec);
        const startPoint: Point = existingStart || {
          pointUuid: MathUtils.generateUUID(), // Generate unique ID for new points
          pointType: "Wall", // Type identifier
          position: [startVec.x, startVec.y, startVec.z], // Position in 3D space
          layer: activeLayer,
        };

        const existingEnd = findExistingPoint(endVec);
        const endPoint: Point = existingEnd || {
          pointUuid: MathUtils.generateUUID(), // Generate unique ID for new points
          pointType: "Wall", // Type identifier
          position: [endVec.x, endVec.y, endVec.z], // Position in 3D space
          layer: activeLayer,
        };

        // Create the wall segment
        const wallSet: Wall = {
          wallUuid: MathUtils.generateUUID(),
          points: [startPoint, endPoint], // Store start and end points
          outsideMaterial: insideMaterial,
          insideMaterial: outsideMaterial,
          wallThickness: wallThickness,
          wallHeight: wallHeight,
          decals: [],
        };

        // Add the wall segment
        // addWall(wallSet);
        wallVertex.push(wallSet);
        // Store first point and create closing segment if this is the last vertex
        if (i === 0) firstPoint = startPoint;
        if (i === entity.vertices.length - 2 && firstPoint) {
          const closingWallSet: Wall = {
            wallUuid: MathUtils.generateUUID(),
            points: [endPoint, firstPoint], // Create closing segment
            outsideMaterial: insideMaterial,
            insideMaterial: outsideMaterial,
            wallThickness: wallThickness,
            wallHeight: wallHeight,
            decals: [],
          };
          // Add the closing wall
          wallVertex.push(closingWallSet);
          // addWall(closingWallSet);
        }
      }
    }

    // Handle ARC entities
    else if (entity.type === "ARC") {
      const { center, radius, startAngle, endAngle } = entity;

      // Validate required ARC properties
      if (
        !center ||
        radius === undefined ||
        startAngle === undefined ||
        endAngle === undefined
      ) {
        return;
      }

      // Convert ARC to series of line segments
      const numSegments = 16; // Number of segments to approximate the arc
      const angleStep = (endAngle - startAngle) / numSegments;
      const arcPoints: Vector3[] = []; // Stores points along the arc

      // Generate points along the arc
      for (let i = 0; i <= numSegments; i++) {
        const angle = startAngle + i * angleStep;
        // Calculate arc point in DXF coordinate system
        const x = center.x + radius * Math.cos(angle);
        const y = -center.y + radius * Math.sin(angle); // Invert Y-axis

        // Convert to Three.js vector with offset
        const vec = new Vector3(x / unit, 0.01, y / unit).add(
          new Vector3(objValue.x, 0, objValue.z)
        );

        arcPoints.push(vec);
      }

      // Create line segments between arc points
      for (let i = 0; i < arcPoints.length - 1; i++) {
        const startVec = arcPoints[i];
        const endVec = arcPoints[i + 1];

        // Create start and end points
        const existingStart = findExistingPoint(startVec);
        const startPoint: Point = existingStart || {
          pointUuid: MathUtils.generateUUID(),
          pointType: "Wall",
          position: [startVec.x, startVec.y, startVec.z],
          layer: activeLayer,
        };

        const existingEnd = findExistingPoint(endVec);
        const endPoint: Point = existingEnd || {
          pointUuid: MathUtils.generateUUID(),
          pointType: "Wall",
          position: [endVec.x, endVec.y, endVec.z],
          layer: activeLayer,
        };

        // Create the wall segment
        const wallSet: Wall = {
          wallUuid: MathUtils.generateUUID(),
          points: [startPoint, endPoint],
          outsideMaterial: insideMaterial,
          insideMaterial: outsideMaterial,
          wallThickness: wallThickness,
          wallHeight: wallHeight,
          decals: [],
        };

        // Add the wall segment
        // addWall(wallSet);
        wallVertex.push(wallSet);
      }
    }

    // Log unsupported entity types
    else {
      console.error("Unsupported entity type:", entity.type);
    }
  });
  console.log("wallVertex: ", wallVertex);
  // Return the generated walls through callback if provided
  setDxfWallGenerate && setDxfWallGenerate(wallVertex);
} 
