import * as THREE from 'three'
import { useEffect, useMemo, useRef, useState } from 'react'
import { useThree } from '@react-three/fiber';
import { useActiveLayer, useSocketStore, useToggleView, useToolMode } from '../../../../store/builder/store';
import { useBuilderStore } from '../../../../store/builder/useBuilderStore';
import { useParams } from 'react-router-dom';
import { useVersionContext } from '../../version/versionContext';
import { useSceneContext } from '../../../scene/sceneContext';
import ReferenceAisle from './referenceAisle';
import ReferencePoint from '../../point/reference/referencePoint';
import { getUserData } from '../../../../functions/getUserData';

// import { upsertAisleApi } from '../../../../services/factoryBuilder/aisle/upsertAisleApi';

function AisleCreator() {
    const { scene, camera, raycaster, gl, pointer } = useThree();
    const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
    const { toggleView } = useToggleView();
    const { toolMode } = useToolMode();
    const { activeLayer } = useActiveLayer();
    const { socket } = useSocketStore();
    const { aisleStore } = useSceneContext();
    const { addAisle, getAislePointById } = aisleStore();
    const drag = useRef(false);
    const isLeftMouseDown = useRef(false);
    const { selectedVersionStore } = useVersionContext();
    const { selectedVersion } = selectedVersionStore();
    const { userId, organization } = getUserData();
    const { projectId } = useParams();

    const [tempPoints, setTempPoints] = useState<Point[]>([]);
    const [isCreating, setIsCreating] = useState(false);
    const { aisleType, aisleWidth, aisleColor, dashLength, gapLength, dotRadius, aisleLength, isFlipped, snappedPosition, snappedPoint, setSnappedPosition, setSnappedPoint } = useBuilderStore();

    useEffect(() => {
        const canvasElement = gl.domElement;

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

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

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

        const onMouseClick = () => {
            if (drag.current || !toggleView) return;

            raycaster.setFromCamera(pointer, camera);
            const intersectionPoint = new THREE.Vector3();
            let position = raycaster.ray.intersectPlane(plane, intersectionPoint);
            if (!position) return;

            const intersects = raycaster.intersectObjects(scene.children).find((intersect) => intersect.object.name === 'Aisle-Point');

            const newPoint: Point = {
                pointUuid: THREE.MathUtils.generateUUID(),
                pointType: 'Aisle',
                position: [position.x, position.y, position.z],
                layer: activeLayer
            };

            if (snappedPosition && snappedPoint) {
                newPoint.pointUuid = snappedPoint.pointUuid;
                newPoint.position = snappedPosition;
                newPoint.layer = snappedPoint.layer;
            }

            if (snappedPoint && snappedPoint.pointUuid === tempPoints[0]?.pointUuid) { return }

            if (snappedPosition && !snappedPoint) {
                newPoint.position = snappedPosition;
            }

            if (intersects && !snappedPoint) {
                const point = getAislePointById(intersects.object.uuid);
                if (point) {
                    newPoint.pointUuid = point.pointUuid;
                    newPoint.position = point.position;
                    newPoint.layer = point.layer;
                }
            }

            if (aisleType === 'solid-aisle') {

                if (tempPoints.length === 0) {
                    setTempPoints([newPoint]);
                    setIsCreating(true);
                } else {
                    const aisle: Aisle = {
                        aisleUuid: THREE.MathUtils.generateUUID(),
                        points: [tempPoints[0], newPoint],
                        type: {
                            aisleType: 'solid-aisle',
                            aisleColor: aisleColor,
                            aisleWidth: aisleWidth
                        }
                    };
                    addAisle(aisle);
                    if (projectId) {

                        // API 

                        // upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')

                        // SOCKET

                        socket.emit('v1:model-aisle:add', {
                            projectId: projectId,
                            versionId: selectedVersion?.versionId || '',
                            userId: userId,
                            organization: organization,
                            aisleUuid: aisle.aisleUuid,
                            points: aisle.points,
                            type: aisle.type
                        })
                    }
                    setTempPoints([newPoint]);
                }
            } else if (aisleType === 'dashed-aisle') {

                if (tempPoints.length === 0) {
                    setTempPoints([newPoint]);
                    setIsCreating(true);
                } else {
                    const aisle: Aisle = {
                        aisleUuid: THREE.MathUtils.generateUUID(),
                        points: [tempPoints[0], newPoint],
                        type: {
                            aisleType: 'dashed-aisle',
                            aisleColor: aisleColor,
                            aisleWidth: aisleWidth,
                            dashLength: dashLength,
                            gapLength: gapLength
                        }
                    };
                    addAisle(aisle);
                    if (projectId) {

                        // API 

                        // upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')

                        // SOCKET

                        socket.emit('v1:model-aisle:add', {
                            projectId: projectId,
                            versionId: selectedVersion?.versionId || '',
                            userId: userId,
                            organization: organization,
                            aisleUuid: aisle.aisleUuid,
                            points: aisle.points,
                            type: aisle.type
                        })
                    }
                    setTempPoints([newPoint]);
                }
            } else if (aisleType === 'dotted-aisle') {

                if (tempPoints.length === 0) {
                    setTempPoints([newPoint]);
                    setIsCreating(true);
                } else {
                    const aisle: Aisle = {
                        aisleUuid: THREE.MathUtils.generateUUID(),
                        points: [tempPoints[0], newPoint],
                        type: {
                            aisleType: 'dotted-aisle',
                            aisleColor: aisleColor,
                            dotRadius: dotRadius,
                            gapLength: gapLength
                        }
                    };
                    addAisle(aisle);
                    if (projectId) {

                        // API 

                        // upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')

                        // SOCKET

                        socket.emit('v1:model-aisle:add', {
                            projectId: projectId,
                            versionId: selectedVersion?.versionId || '',
                            userId: userId,
                            organization: organization,
                            aisleUuid: aisle.aisleUuid,
                            points: aisle.points,
                            type: aisle.type
                        })
                    }
                    setTempPoints([newPoint]);
                }
            } else if (aisleType === 'arrow-aisle') {

                if (tempPoints.length === 0) {
                    setTempPoints([newPoint]);
                    setIsCreating(true);
                } else {
                    const aisle: Aisle = {
                        aisleUuid: THREE.MathUtils.generateUUID(),
                        points: [tempPoints[0], newPoint],
                        type: {
                            aisleType: 'arrow-aisle',
                            aisleColor: aisleColor,
                            aisleWidth: aisleWidth
                        }
                    };
                    addAisle(aisle);
                    if (projectId) {

                        // API 

                        // upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')

                        // SOCKET

                        socket.emit('v1:model-aisle:add', {
                            projectId: projectId,
                            versionId: selectedVersion?.versionId || '',
                            userId: userId,
                            organization: organization,
                            aisleUuid: aisle.aisleUuid,
                            points: aisle.points,
                            type: aisle.type
                        })
                    }
                    setTempPoints([newPoint]);
                }
            } else if (aisleType === 'arrows-aisle') {

                if (tempPoints.length === 0) {
                    setTempPoints([newPoint]);
                    setIsCreating(true);
                } else {
                    const aisle: Aisle = {
                        aisleUuid: THREE.MathUtils.generateUUID(),
                        points: [tempPoints[0], newPoint],
                        type: {
                            aisleType: 'arrows-aisle',
                            aisleColor: aisleColor,
                            aisleWidth: aisleWidth,
                            aisleLength: aisleLength,
                            gapLength: gapLength
                        }
                    };
                    addAisle(aisle);
                    if (projectId) {

                        // API 

                        // upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')

                        // SOCKET

                        socket.emit('v1:model-aisle:add', {
                            projectId: projectId,
                            versionId: selectedVersion?.versionId || '',
                            userId: userId,
                            organization: organization,
                            aisleUuid: aisle.aisleUuid,
                            points: aisle.points,
                            type: aisle.type
                        })
                    }
                    setTempPoints([newPoint]);
                }
            } else if (aisleType === 'arc-aisle') {

                if (tempPoints.length === 0) {
                    setTempPoints([newPoint]);
                    setIsCreating(true);
                } else {
                    const aisle: Aisle = {
                        aisleUuid: THREE.MathUtils.generateUUID(),
                        points: [tempPoints[0], newPoint],
                        type: {
                            aisleType: 'arc-aisle',
                            aisleColor: aisleColor,
                            aisleWidth: aisleWidth,
                            isFlipped: isFlipped
                        }
                    };
                    addAisle(aisle);
                    if (projectId) {

                        // API 

                        // upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')

                        // SOCKET

                        socket.emit('v1:model-aisle:add', {
                            projectId: projectId,
                            versionId: selectedVersion?.versionId || '',
                            userId: userId,
                            organization: organization,
                            aisleUuid: aisle.aisleUuid,
                            points: aisle.points,
                            type: aisle.type
                        })
                    }
                    setTempPoints([newPoint]);
                }
            } else if (aisleType === 'circle-aisle') {

                if (tempPoints.length === 0) {
                    setTempPoints([newPoint]);
                    setIsCreating(true);
                } else {
                    const aisle: Aisle = {
                        aisleUuid: THREE.MathUtils.generateUUID(),
                        points: [tempPoints[0], newPoint],
                        type: {
                            aisleType: 'circle-aisle',
                            aisleColor: aisleColor,
                            aisleWidth: aisleWidth
                        }
                    };
                    addAisle(aisle);
                    if (projectId) {

                        // API 

                        // upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')

                        // SOCKET

                        socket.emit('v1:model-aisle:add', {
                            projectId: projectId,
                            versionId: selectedVersion?.versionId || '',
                            userId: userId,
                            organization: organization,
                            aisleUuid: aisle.aisleUuid,
                            points: aisle.points,
                            type: aisle.type
                        })
                    }
                    setTempPoints([newPoint]);
                }
            } else if (aisleType === 'junction-aisle') {

                if (tempPoints.length === 0) {
                    setTempPoints([newPoint]);
                    setIsCreating(true);
                } else {
                    const aisle: Aisle = {
                        aisleUuid: THREE.MathUtils.generateUUID(),
                        points: [tempPoints[0], newPoint],
                        type: {
                            aisleType: 'junction-aisle',
                            aisleColor: aisleColor,
                            aisleWidth: aisleWidth,
                            isFlipped: isFlipped
                        }
                    };
                    addAisle(aisle);
                    if (projectId) {

                        // API 

                        // upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')

                        // SOCKET

                        socket.emit('v1:model-aisle:add', {
                            projectId: projectId,
                            versionId: selectedVersion?.versionId || '',
                            userId: userId,
                            organization: organization,
                            aisleUuid: aisle.aisleUuid,
                            points: aisle.points,
                            type: aisle.type
                        })
                    }
                    setTempPoints([newPoint]);
                }
            }
        };

        const onContext = (event: any) => {
            event.preventDefault();
            if (isCreating) {
                setTempPoints([]);
                setIsCreating(false);
            }
        };

        if (toolMode === "Aisle" && toggleView) {
            if (tempPoints.length === 0) {
                setSnappedPosition(null);
                setSnappedPoint(null);
            }
            canvasElement.addEventListener("mousedown", onMouseDown);
            canvasElement.addEventListener("mouseup", onMouseUp);
            canvasElement.addEventListener("mousemove", onMouseMove);
            canvasElement.addEventListener("click", onMouseClick);
            canvasElement.addEventListener("contextmenu", onContext);
        } else {
            if (tempPoints.length > 0 || isCreating) {
                setTempPoints([]);
                setIsCreating(false);
            }
            canvasElement.removeEventListener("mousedown", onMouseDown);
            canvasElement.removeEventListener("mouseup", onMouseUp);
            canvasElement.removeEventListener("mousemove", onMouseMove);
            canvasElement.removeEventListener("click", onMouseClick);
            canvasElement.removeEventListener("contextmenu", onContext);
        }

        return () => {
            canvasElement.removeEventListener("mousedown", onMouseDown);
            canvasElement.removeEventListener("mouseup", onMouseUp);
            canvasElement.removeEventListener("mousemove", onMouseMove);
            canvasElement.removeEventListener("click", onMouseClick);
            canvasElement.removeEventListener("contextmenu", onContext);
        };
    }, [gl, camera, scene, raycaster, pointer, plane, toggleView, toolMode, activeLayer, socket, tempPoints, isCreating, addAisle, getAislePointById, aisleType, aisleWidth, aisleColor, dashLength, gapLength, dotRadius, aisleLength, snappedPosition, snappedPoint, selectedVersion?.versionId]);

    return (
        <>
            {toggleView &&
                <>
                    <group name='Aisle-Reference-Points-Group'>
                        {tempPoints.map((point) => (
                            <ReferencePoint key={point.pointUuid} point={point} />
                        ))}
                    </group>

                    {tempPoints.length > 0 &&
                        <ReferenceAisle tempPoints={tempPoints} />
                    }
                </>
            }
        </>
    );
}

export default AisleCreator;