import * as THREE from 'three';
import * as  Types from '../../../types/world/worldTypes';
import * as CONSTANTS from '../../../types/world/worldConstants';
import { useThree } from "@react-three/fiber";
import { useToggleView, useActiveLayer, useSocketStore, useDeletePointOrLine, useMovePoint, useUpdateScene, useNewLines, useToolMode } from "../../../store/store";
import { useEffect } from "react";
import removeSoloPoint from "../geomentries/points/removeSoloPoint";
import removeReferenceLine from "../geomentries/lines/removeReferenceLine";
import getClosestIntersection from "../geomentries/lines/getClosestIntersection";
import addPointToScene from "../geomentries/points/addPointToScene";
import arrayLineToObject from '../geomentries/lines/lineConvertions/arrayLineToObject';
import addLineToScene from "../geomentries/lines/addLineToScene";
import loadAisles from '../geomentries/aisles/loadAisles';


const FloorGroupAilse = ({ floorGroupAisle, plane, floorPlanGroupLine, floorPlanGroupPoint, line, lines, currentLayerPoint, dragPointControls, floorPlanGroup, ReferenceLineMesh, LineCreated, isSnapped, ispreSnapped, snappedPoint, isSnappedUUID, isAngleSnapped, anglesnappedPoint }: any) => {
    const { toggleView, setToggleView } = useToggleView();
    const { deletePointOrLine, setDeletePointOrLine } = useDeletePointOrLine();
    const { toolMode, setToolMode } = useToolMode();
    const { movePoint, setMovePoint } = useMovePoint();
    const { socket } = useSocketStore();
    const { activeLayer } = useActiveLayer();
    const { gl, raycaster, camera, pointer } = useThree();
    const { updateScene, setUpdateScene } = useUpdateScene();
    const { newLines, setNewLines } = useNewLines();

    useEffect(() => {
        if (updateScene) {
            loadAisles(lines, floorGroupAisle);
            setUpdateScene(false);
        }
    }, [updateScene])

    useEffect(() => {
        if (toolMode === "Aisle") {
            setDeletePointOrLine(false);
            setMovePoint(false);
        } else {
            removeSoloPoint(line, floorPlanGroupLine, floorPlanGroupPoint);
            removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line);
        }
    }, [toolMode]);

    useEffect(() => {

        const canvasElement = gl.domElement;

        let drag = false;
        let isLeftMouseDown = false;

        const onMouseDown = (evt: any) => {
            if (evt.button === 0) {
                isLeftMouseDown = true;
                drag = false;
            }
        };

        const onMouseUp = (evt: any) => {
            if (evt.button === 0) {
                isLeftMouseDown = false;
            }
        }

        const onMouseMove = () => {
            if (isLeftMouseDown) {
                drag = true;
            }
        };

        const onContextMenu = (e: any) => {
            e.preventDefault();
            if (toolMode === "Aisle") {
                removeSoloPoint(line, floorPlanGroupLine, floorPlanGroupPoint);
                removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line);
            }
        };

        const onMouseClick = (evt: any) => {
            if (!plane.current || drag) return;

            const intersects = raycaster.intersectObject(plane.current, true);
            let intersectionPoint = intersects[0].point;
            const points = floorPlanGroupPoint.current?.children ?? [];
            const intersectsPoint = raycaster.intersectObjects(points, true).find(intersect => intersect.object.visible);
            let intersectsLines: any = raycaster.intersectObjects(floorPlanGroupLine.current.children, true);


            if (intersectsLines.length > 0 && intersects && intersects.length > 0 && !intersectsPoint) {
                const lineType = intersectsLines[0].object.userData.linePoints[0][3];
                if (lineType === CONSTANTS.lineConfig.aisleName) {
                    // console.log("intersected a aisle line");
                    const ThroughPoint = (intersectsLines[0].object.geometry.parameters.path).getPoints(CONSTANTS.lineConfig.lineIntersectionPoints);
                    let intersection = getClosestIntersection(ThroughPoint, intersectionPoint);
                    if (!intersection) return;
                    const point = addPointToScene(intersection, CONSTANTS.pointConfig.aisleOuterColor, currentLayerPoint, floorPlanGroupPoint, dragPointControls, undefined, CONSTANTS.lineConfig.aisleName);
                    (line.current as Types.Line).push([new THREE.Vector3(intersection.x, 0.01, intersection.z), point.uuid, activeLayer, CONSTANTS.lineConfig.aisleName,]);
                    if (line.current.length >= 2 && line.current[0] && line.current[1]) {
                        lines.current.push(line.current as Types.Line);

                        const data = arrayLineToObject(line.current as Types.Line);

                        const email = localStorage.getItem('email')
                        const organization = (email!.split("@")[1]).split(".")[0];

                        //REST

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

                        //SOCKET

                        const input = {
                            organization: organization,
                            layer: data.layer,
                            line: data.line,
                            type: data.type,
                            socketId: socket.id
                        }

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

                        setNewLines([line.current]);

                        addLineToScene(line.current[0][0], line.current[1][0], CONSTANTS.pointConfig.aisleOuterColor, line.current, floorPlanGroupLine);
                        let lastPoint = line.current[line.current.length - 1];
                        line.current = [lastPoint];
                    }
                }
            } else if (intersectsPoint && intersects && intersects.length > 0) {
                if (intersectsPoint.object.userData.type === CONSTANTS.lineConfig.aisleName) {
                    // console.log("intersected a aisle point");
                    intersectionPoint = intersectsPoint.object.position;
                    (line.current as Types.Line).push([new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z), intersectsPoint.object.uuid, activeLayer, CONSTANTS.lineConfig.aisleName,]);
                    if (line.current.length >= 2 && line.current[0] && line.current[1]) {
                        lines.current.push(line.current as Types.Line);

                        const data = arrayLineToObject(line.current as Types.Line);

                        const email = localStorage.getItem('email')
                        const organization = (email!.split("@")[1]).split(".")[0];

                        //REST

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

                        //SOCKET

                        const input = {
                            organization: organization,
                            layer: data.layer,
                            line: data.line,
                            type: data.type,
                            socketId: socket.id
                        }

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

                        setNewLines([line.current]);

                        addLineToScene(line.current[0][0], line.current[1][0], CONSTANTS.pointConfig.aisleOuterColor, line.current, floorPlanGroupLine);
                        let lastPoint = line.current[line.current.length - 1];
                        line.current = [lastPoint];
                        ispreSnapped.current = false;
                        isSnapped.current = false;
                    }
                }
            } else if (intersects && intersects.length > 0) {
                // console.log("intersected a empty area");
                let uuid: string = "";
                if (isAngleSnapped.current && anglesnappedPoint.current && line.current.length > 0) {
                    intersectionPoint = anglesnappedPoint.current;
                    const point = addPointToScene(intersectionPoint, CONSTANTS.pointConfig.aisleOuterColor, currentLayerPoint, floorPlanGroupPoint, dragPointControls, undefined, CONSTANTS.lineConfig.aisleName);
                    uuid = point.uuid;
                } else if (isSnapped.current && snappedPoint.current && line.current.length > 0) {
                    intersectionPoint = snappedPoint.current;
                    uuid = isSnappedUUID.current!;
                } else if (ispreSnapped.current && snappedPoint.current) {
                    intersectionPoint = snappedPoint.current;
                    uuid = isSnappedUUID.current!;
                } else {
                    const point = addPointToScene(intersectionPoint, CONSTANTS.pointConfig.aisleOuterColor, currentLayerPoint, floorPlanGroupPoint, dragPointControls, undefined, CONSTANTS.lineConfig.aisleName);
                    uuid = point.uuid;
                }
                (line.current as Types.Line).push([new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z), uuid, activeLayer, CONSTANTS.lineConfig.aisleName,]);

                if (line.current.length >= 2 && line.current[0] && line.current[1]) {
                    lines.current.push(line.current as Types.Line);

                    const data = arrayLineToObject(line.current as Types.Line);

                    const email = localStorage.getItem('email')
                    const organization = (email!.split("@")[1]).split(".")[0];

                    //REST

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

                    //SOCKET

                    const input = {
                        organization: organization,
                        layer: data.layer,
                        line: data.line,
                        type: data.type,
                        socketId: socket.id
                    }

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

                    setNewLines([line.current]);

                    addLineToScene(line.current[0][0], line.current[1][0], CONSTANTS.pointConfig.aisleOuterColor, line.current, floorPlanGroupLine);
                    let lastPoint = line.current[line.current.length - 1];
                    line.current = [lastPoint];
                    ispreSnapped.current = false;
                    isSnapped.current = false;
                }
            }
        }


        if (toolMode === 'Aisle') {
            canvasElement.addEventListener("mousedown", onMouseDown);
            canvasElement.addEventListener("mouseup", onMouseUp);
            canvasElement.addEventListener("mousemove", onMouseMove);
            canvasElement.addEventListener("click", onMouseClick);
            canvasElement.addEventListener("contextmenu", onContextMenu);
        }

        return () => {
            canvasElement.removeEventListener("mousedown", onMouseDown);
            canvasElement.removeEventListener("mouseup", onMouseUp);
            canvasElement.removeEventListener("mousemove", onMouseMove);
            canvasElement.removeEventListener("click", onMouseClick);
            canvasElement.removeEventListener("contextmenu", onContextMenu);
        };
    }, [toolMode])


    return (
        <group ref={floorGroupAisle} visible={!toggleView} name="floorGroupAisle">
        </group>
    )
}

export default FloorGroupAilse;