import { useEffect } from "react";
import {
    useObjectPosition,
    useObjectRotation,
    useSelectedWallItem,
    useSocketStore,
    useWallItems,
    useSelectedItem,
    useToolMode,
} from "../../../store/builder/store";
import { Csg } from "../csg/csg";
import * as Types from "../../../types/world/worldTypes";
import * as CONSTANTS from "../../../types/world/worldConstants";
import * as THREE from "three";
import { useThree } from "@react-three/fiber";
import handleMeshMissed from "../eventFunctions/handleMeshMissed";
import DeleteWallItems from "../geomentries/walls/deleteWallItems";
import loadInitialWallItems from "../IntialLoad/loadInitialWallItems";
import AddWallItems from "../geomentries/walls/addWallItems";
import useModuleStore from "../../../store/useModuleStore";
import { useParams } from "react-router-dom";

const WallItemsGroup = ({
    currentWallItem,
    hoveredDeletableWallItem,
    selectedItemsIndex,
    setSelectedItemsIndex,
    CSGGroup,
}: any) => {
    const state = useThree();
    const { socket } = useSocketStore();
    const { pointer, camera, raycaster } = state;
    const { toolMode } = useToolMode();
    const { wallItems, setWallItems } = useWallItems();
    const { setObjectPosition } = useObjectPosition();
    const { setObjectRotation } = useObjectRotation();
    const { setSelectedWallItem } = useSelectedWallItem();
    const { activeModule } = useModuleStore();
    const { selectedItem } = useSelectedItem();
    const { projectId } = useParams();

    useEffect(() => {
        // Load Wall Items from the backend
        loadInitialWallItems(setWallItems, projectId);
    }, []);

    //////////  Update the Position value changes  in the selected item  //////////

    useEffect(() => {
        const canvasElement = state.gl.domElement;
        function handlePointerMove(e: any) {
            if (selectedItemsIndex !== null && toolMode === 'cursor' && e.buttons === 1) {
                const Raycaster = state.raycaster;
                const intersects = Raycaster.intersectObjects(CSGGroup.current?.children[0].children!, true);
                const Object = intersects.find((child) => child.object.name.includes("WallRaycastReference"));

                if (Object) {
                    (state.controls as any)!.enabled = false;
                    setWallItems((prevItems: any) => {
                        const updatedItems = [...prevItems];
                        let position: [number, number, number] = [0, 0, 0];

                        if (updatedItems[selectedItemsIndex].type === "fixed-move") {
                            position = [
                                Object!.point.x,
                                Math.floor(Object!.point.y / CONSTANTS.wallConfig.height) *
                                CONSTANTS.wallConfig.height,
                                Object!.point.z,
                            ];
                        } else if (updatedItems[selectedItemsIndex].type === "free-move") {
                            position = [Object!.point.x, Object!.point.y, Object!.point.z];
                        }

                        requestAnimationFrame(() => {
                            setObjectPosition(new THREE.Vector3(...position));
                            setObjectRotation({
                                x: THREE.MathUtils.radToDeg(Object!.object.rotation.x),
                                y: THREE.MathUtils.radToDeg(Object!.object.rotation.y),
                                z: THREE.MathUtils.radToDeg(Object!.object.rotation.z),
                            });
                        });

                        updatedItems[selectedItemsIndex] = {
                            ...updatedItems[selectedItemsIndex],
                            position: position,
                            quaternion: Object!.object.quaternion.clone() as Types.QuaternionType,
                        };

                        return updatedItems;
                    });
                }
            }
        }

        async function handlePointerUp() {
            const Raycaster = state.raycaster;
            const intersects = Raycaster.intersectObjects(
                CSGGroup.current?.children[0].children!,
                true
            );
            const Object = intersects.find((child) =>
                child.object.name.includes("WallRaycastReference")
            );
            if (Object) {
                if (selectedItemsIndex !== null) {
                    let currentItem: any = null;
                    setWallItems((prevItems: any) => {
                        const updatedItems = [...prevItems];
                        const WallItemsForStorage = updatedItems.map((item) => {
                            const { model, ...rest } = item;
                            return {
                                ...rest,
                                modelUuid: model?.uuid,
                            };
                        });

                        currentItem = updatedItems[selectedItemsIndex];
                        localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage));
                        return updatedItems;
                    });

                    setTimeout(async () => {
                        const email = localStorage.getItem("email");
                        const organization = email!.split("@")[1].split(".")[0];
                        const userId = localStorage.getItem("userId");

                        //REST

                        // await setWallItem(
                        //   organization,
                        //   currentItem?.model?.uuid,
                        //   currentItem.modelName,
                        //   currentItem.assetId,
                        //   currentItem.type!,
                        //   currentItem.csgposition!,
                        //   currentItem.csgscale!,
                        //   currentItem.position,
                        //   currentItem.quaternion,
                        //   currentItem.scale!,
                        // )

                        //SOCKET

                        const data = {
                            organization: organization,
                            modelUuid: currentItem.model?.uuid!,
                            assetId: currentItem.assetId,
                            modelName: currentItem.modelName!,
                            type: currentItem.type!,
                            csgposition: currentItem.csgposition!,
                            csgscale: currentItem.csgscale!,
                            position: currentItem.position!,
                            quaternion: currentItem.quaternion,
                            scale: currentItem.scale!,
                            socketId: socket.id,
                            projectId,
                            userId
                        };

                        // console.log('data: ', data);
                        socket.emit("v1:wallItems:set", data);
                    }, 0);
                    (state.controls as any)!.enabled = true;
                }
            }
        }

        canvasElement.addEventListener("pointermove", handlePointerMove);
        canvasElement.addEventListener("pointerup", handlePointerUp);

        return () => {
            canvasElement.removeEventListener("pointermove", handlePointerMove);
            canvasElement.removeEventListener("pointerup", handlePointerUp);
        };
    }, [selectedItemsIndex]);

    useEffect(() => {
        const canvasElement = state.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;
                if (!drag && toolMode === '3D-Delete' && activeModule === "builder") {
                    DeleteWallItems(
                        hoveredDeletableWallItem,
                        setWallItems,
                        wallItems,
                        socket, projectId
                    );
                }
            }
        };

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

        const onDrop = (event: any) => {
            if (selectedItem.category !== 'Fenestration') return;

            pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
            pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;

            raycaster.setFromCamera(pointer, camera);

            if (selectedItem.id) {
                if (selectedItem.subCategory) {
                    AddWallItems(
                        selectedItem,
                        raycaster,
                        CSGGroup,
                        setWallItems,
                        socket,
                        projectId
                    );
                }
                event.preventDefault();
            }
        };

        const onDragOver = (event: any) => {
            event.preventDefault();
        };

        canvasElement.addEventListener("mousedown", onMouseDown);
        canvasElement.addEventListener("mouseup", onMouseUp);
        canvasElement.addEventListener("mousemove", onMouseMove);
        canvasElement.addEventListener("drop", onDrop);
        canvasElement.addEventListener("dragover", onDragOver);

        return () => {
            canvasElement.removeEventListener("mousedown", onMouseDown);
            canvasElement.removeEventListener("mouseup", onMouseUp);
            canvasElement.removeEventListener("mousemove", onMouseMove);
            canvasElement.removeEventListener("drop", onDrop);
            canvasElement.removeEventListener("dragover", onDragOver);
        };
    }, [toolMode, wallItems, selectedItem, camera]);

    useEffect(() => {
        if (toolMode && activeModule === "builder") {
            handleMeshMissed(
                currentWallItem,
                setSelectedWallItem,
                setSelectedItemsIndex
            );
            setSelectedWallItem(null);
            setSelectedItemsIndex(null);
        }
    }, [toolMode]);

    return (
        <>
            {wallItems.map((item: Types.WallItem, index: number) => (
                <group
                    key={index}
                    position={item.position}
                    quaternion={item.quaternion}
                    scale={item.scale}
                >
                    <Csg
                        position={item.csgposition!}
                        scale={item.csgscale!}
                        model={item.model!}
                        hoveredDeletableWallItem={hoveredDeletableWallItem}
                    />
                </group>
            ))}
        </>
    );
};

export default WallItemsGroup;
