import * as THREE from 'three';
import * as CONSTANTS from '../../../../types/world/worldConstants';

import addPointToScene from '../points/addPointToScene';
import addLineToScene from './addLineToScene';
import splitLine from './splitLine';
import removeReferenceLine from './removeReferenceLine';
import getClosestIntersection from './getClosestIntersection';

import * as Types from "../../../../types/world/worldTypes";
import arrayLineToObject from './lineConvertions/arrayLineToObject';
// import { setLine } from '../../../../services/factoryBuilder/lines/setLineApi';
import { Socket } from 'socket.io-client';

async function drawWall(
    raycaster: THREE.Raycaster,
    plane: Types.RefMesh,
    floorPlanGroupPoint: Types.RefGroup,
    snappedPoint: Types.RefVector3,
    isSnapped: Types.RefBoolean,
    isSnappedUUID: Types.RefString,
    line: Types.RefLine,
    ispreSnapped: Types.RefBoolean,
    anglesnappedPoint: Types.RefVector3,
    isAngleSnapped: Types.RefBoolean,
    lines: Types.RefLines,
    floorPlanGroupLine: Types.RefGroup,
    floorPlanGroup: Types.RefGroup,
    ReferenceLineMesh: Types.RefMesh,
    LineCreated: Types.RefBoolean,
    currentLayerPoint: Types.RefMeshArray,
    dragPointControls: Types.RefDragControl,
    setNewLines: any,
    setDeletedLines: any,
    activeLayer: Types.Number,
    socket: Socket<any>
): Promise<void> {

    //////////  Creating lines Based on the positions clicked  //////////

    //////////  Allows the user lines that represents walls and roof, floor if forms a polygon  //////////


    if (!plane.current) return
    let intersects = raycaster.intersectObject(plane.current, true);

    let intersectsLines = raycaster.intersectObjects(floorPlanGroupLine.current.children, true);
    let intersectsPoint = raycaster.intersectObjects(floorPlanGroupPoint.current.children, true);

    const VisibleintersectsPoint = intersectsPoint.find(intersect => intersect.object.visible);
    const visibleIntersect = intersectsLines.find(intersect => intersect.object.visible && intersect.object.name !== CONSTANTS.lineConfig.referenceName && intersect.object.userData.linePoints[0][3] === CONSTANTS.lineConfig.wallName);

    if ((intersectsPoint.length === 0 || VisibleintersectsPoint === undefined) && intersectsLines.length > 0 && !isSnapped.current && !ispreSnapped.current) {

        //////////  Clicked on a preexisting Line  //////////

        if (visibleIntersect && intersects) {
            let IntersectsPoint = new THREE.Vector3(intersects[0].point.x, 0.01, intersects[0].point.z);

            if (isAngleSnapped.current && anglesnappedPoint.current) {
                IntersectsPoint = anglesnappedPoint.current;
            }
            if (visibleIntersect.object instanceof THREE.Mesh) {
                const ThroughPoint = (visibleIntersect.object.geometry.parameters.path).getPoints(CONSTANTS.lineConfig.lineIntersectionPoints);
                let intersectionPoint = getClosestIntersection(ThroughPoint, IntersectsPoint);

                if (intersectionPoint) {

                    const newLines = splitLine(visibleIntersect, intersectionPoint, currentLayerPoint, floorPlanGroupPoint, dragPointControls, isSnappedUUID, lines, setDeletedLines, floorPlanGroupLine, socket, CONSTANTS.pointConfig.wallOuterColor, CONSTANTS.lineConfig.wallColor, CONSTANTS.lineConfig.wallName);
                    setNewLines([newLines[0], newLines[1]]);

                    (line.current as Types.Line).push([new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z), isSnappedUUID.current!, activeLayer, CONSTANTS.lineConfig.wallName,]);

                    if (line.current.length >= 2 && line.current[0] && line.current[1]) {
                        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([newLines[0], newLines[1], line.current]);
                        lines.current.push(line.current as Types.Line);
                        addLineToScene(line.current[0][0], line.current[1][0], CONSTANTS.lineConfig.wallColor, line.current, floorPlanGroupLine);
                        let lastPoint = line.current[line.current.length - 1];
                        line.current = [lastPoint];
                    }
                    return;
                }
            }
        }
    }

    if (intersects && intersects.length > 0) {

        //////////  Clicked on a emply place or a point  //////////

        let intersectionPoint = intersects[0].point;

        if (isAngleSnapped.current && line.current.length > 0 && anglesnappedPoint.current) {
            intersectionPoint = anglesnappedPoint.current;
        }
        if (isSnapped.current && line.current.length > 0 && snappedPoint.current) {
            intersectionPoint = snappedPoint.current;
        }
        if (ispreSnapped.current && snappedPoint.current) {
            intersectionPoint = snappedPoint.current;
        }

        if (!isSnapped.current && !ispreSnapped.current) {
            addPointToScene(intersectionPoint, CONSTANTS.pointConfig.wallOuterColor, currentLayerPoint, floorPlanGroupPoint, dragPointControls, isSnappedUUID, CONSTANTS.lineConfig.wallName);
        } else {
            ispreSnapped.current = false;
            isSnapped.current = false;
        }

        (line.current as Types.Line).push([new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z), isSnappedUUID.current!, activeLayer, CONSTANTS.lineConfig.wallName,]);

        if (line.current.length >= 2 && line.current[0] && line.current[1]) {
            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])
            lines.current.push(line.current as Types.Line);
            addLineToScene(line.current[0][0], line.current[1][0], CONSTANTS.lineConfig.wallColor, line.current, floorPlanGroupLine);
            let lastPoint = line.current[line.current.length - 1];
            line.current = [lastPoint];
        }
        if (isSnapped.current) {
            removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line);
        }
    }
}

export default drawWall;
