import { useEffect, useRef } from 'react';
import { useDfxUpload, useSocketStore, useToggleView, useUpdateScene } from '../../../store/builder/store';
import { LineBasicMaterial, Line } from 'three';
import loadInitialPoint from '../IntialLoad/loadInitialPoint';
import loadInitialLine from '../IntialLoad/loadInitialLine';
import { TransformControls } from '@react-three/drei';
import { getWallPointsFromBlueprint } from './functions/getWallPointsFromBlueprint';
import * as Types from '../../../types/world/worldTypes';
import arrayLineToObject from '../geomentries/lines/lineConvertions/arrayLineToObject';
import { useParams } from 'react-router-dom';

// Interface defining the props for the DxfFile component
interface DxfFileProps {
    lines: Types.RefLines; // Reference to lines in the DXF file
    floorPlanGroupPoint: Types.RefGroup; // Reference to floor plan points group
    dragPointControls: Types.RefDragControl; // Reference to drag controls
    floorPlanGroupLine: Types.RefGroup; // Reference to floor plan lines group
    currentLayerPoint: Types.RefMeshArray; // Reference to current layer points
}

/**
 * DxfFile component handles the rendering and manipulation of DXf file data in a 3D scene.
 * It processes the DXF data to create points and lines representing walls and allows
 * transformation controls for interactive editing.
 */
const DxfFile = ({
    floorPlanGroupPoint,
    currentLayerPoint,
    dragPointControls,
    floorPlanGroupLine,
    lines,
}: DxfFileProps) => {
    // State management hooks
    const { dfxuploaded, dfxWallGenerate, setObjValue, objValue } = useDfxUpload();
    const { setUpdateScene } = useUpdateScene();
    const { toggleView } = useToggleView();
    const { socket } = useSocketStore();
    const { projectId } = useParams();

    // Refs for storing line objects
    const lineRefs = useRef<Line[]>([]);

    /**
     * Effect hook that runs when DXF wall generation is triggered.
     * Loads initial points and lines from the DXF data and updates the scene.
     */
    useEffect(() => {
        if (
            dfxWallGenerate &&
            dragPointControls &&
            floorPlanGroupPoint &&
            currentLayerPoint &&
            floorPlanGroupLine
        ) {
            // Store generated lines in ref
            lines.current.push(...dfxWallGenerate);
            dfxWallGenerate.map((line: any) => {
                const lineData = arrayLineToObject(line as Types.Line);
                const email = localStorage.getItem('email')
                const organization = (email!.split("@")[1]).split(".")[0];
                const userId = localStorage.getItem("userId");

                //REST

                // setLine(organization, lineData.layer!, lineData.line!, lineData.type!);

                //SOCKET

                const input = {
                    organization: organization,
                    layer: lineData.layer,
                    line: lineData.line,
                    type: lineData.type,
                    socketId: socket.id,
                    projectId,
                    userId
                }

                socket.emit('v1:Line:create', input);

            })

            // Load initial points and lines from DXF data
            loadInitialPoint(lines, floorPlanGroupPoint, currentLayerPoint, dragPointControls);
            loadInitialLine(floorPlanGroupLine, lines);

            // Trigger scene update
            setUpdateScene(true);
        }
    }, [
        lines,
        floorPlanGroupLine,
        floorPlanGroupPoint,
        currentLayerPoint,
        dragPointControls,
        dfxWallGenerate,
    ]);

    /**
     * Handles transformation changes for individual lines.
     * Updates the object value state with new position and recalculates wall points.
     * @param index - Index of the line being transformed
     */
    const handleTransformChange = (index: number) => {
        const line = lineRefs.current[index];
        if (!line) return;

        // Get current position of the line
        const position = line.position;

        // Update state with new position
        setObjValue({ x: position.x, y: position.y, z: position.z });

        // Recalculate wall points based on new position
        getWallPointsFromBlueprint({
            objValue: { x: position.x, y: position.y, z: position.z },
            setDfxGenerate: () => { },
        });
    };

    return (
        <>
            {/* Render DXF lines with transform controls when DXF data is available and view is toggled */}
            {dfxuploaded &&
                dfxuploaded.length > 0 &&
                toggleView &&
                dfxuploaded?.map((geometry: any, index: number) => {
                    // Create a new line object for each geometry in the DXF data
                    const line = new Line(geometry, new LineBasicMaterial({ color: 'red' }));
                    line.rotation.set(-Math.PI / 2, 0, 0);

                    // Store line reference
                    lineRefs.current[index] = line;

                    return (
                        <TransformControls
                            key={index}
                            object={line}
                            showY={false}
                            onMouseUp={() => handleTransformChange(index)}
                        >
                            {/* Render the line with current position from state */}
                            <primitive object={line} position={[objValue.x, objValue.y, objValue.z]} />
                        </TransformControls>
                    );
                })}
        </>
    );
};

export default DxfFile;