import { Line } from "@react-three/drei";
import { useMemo } from "react";
import * as THREE from "three";
import { useSelectedAssets } from "../../../../store/builder/store";

interface BoundingBoxProps {
    boundingBoxRef?: any;
    isPerAsset?: boolean;
}

const getBoxLines = (min: THREE.Vector3, max: THREE.Vector3) => [
    [min.x, min.y, min.z], [max.x, min.y, min.z],
    [max.x, min.y, min.z], [max.x, max.y, min.z],
    [max.x, max.y, min.z], [min.x, max.y, min.z],
    [min.x, max.y, min.z], [min.x, min.y, min.z],

    [min.x, min.y, max.z], [max.x, min.y, max.z],
    [max.x, min.y, max.z], [max.x, max.y, max.z],
    [max.x, max.y, max.z], [min.x, max.y, max.z],
    [min.x, max.y, max.z], [min.x, min.y, max.z],

    [min.x, min.y, min.z], [min.x, min.y, max.z],
    [max.x, min.y, min.z], [max.x, min.y, max.z],
    [max.x, max.y, min.z], [max.x, max.y, max.z],
    [min.x, max.y, min.z], [min.x, max.y, max.z],
];

const BoundingBox = ({ boundingBoxRef, isPerAsset = true }: BoundingBoxProps) => {
    const { selectedAssets } = useSelectedAssets();
    const savedTheme: string = localStorage.getItem("theme") || "light";

    const boxes = useMemo(() => {
        if (selectedAssets.length === 0) return [];

        if (isPerAsset) {
            return selectedAssets.map((obj: THREE.Object3D) => {
                const position = obj.position;
                const rotation = obj.getWorldQuaternion(new THREE.Quaternion());
                const clone = obj.clone();
                clone.position.set(0, 0, 0);
                clone.rotation.set(0, 0, 0);
                const box = new THREE.Box3().setFromObject(clone);
                const size = new THREE.Vector3();
                const center = new THREE.Vector3();
                box.getSize(size);
                box.getCenter(center);

                const halfSize = size.clone().multiplyScalar(0.5);
                const min = center.clone().sub(halfSize);
                const max = center.clone().add(halfSize);

                return {
                    points: getBoxLines(min, max),
                    position: [position.x, center.y, position.z],
                    rotation: rotation.toArray(),
                    size: size.toArray(),
                };
            });
        } else {
            const box = new THREE.Box3();
            selectedAssets.forEach((obj: any) => box.expandByObject(obj.clone()));
            const size = new THREE.Vector3();
            const center = new THREE.Vector3();
            box.getSize(size);
            box.getCenter(center);

            const halfSize = size.clone().multiplyScalar(0.5);
            const min = center.clone().sub(halfSize);
            const max = center.clone().add(halfSize);

            return [
                {
                    points: getBoxLines(min, max),
                    position: center.toArray(),
                    rotation: [0, 0, 0, 1],
                    size: size.toArray(),
                },
            ];
        }
    }, [selectedAssets, isPerAsset]);

    return (
        <>
            {boxes.map((box: any, index: number) => (
                <group
                    key={index}
                    name="SelectionGroupBoundingBoxLine"
                >
                    <Line
                        name="SelectionGroupBoundingBox"
                        depthWrite={false}
                        points={box.points}
                        color={savedTheme === "dark" ? "#c4abf1" : "#6f42c1"}
                        lineWidth={2.7}
                        segments
                        position={[box.position[0], 0, box.position[2]]}
                        quaternion={new THREE.Quaternion(...box.rotation)}
                    />
                    <mesh
                        name="SelectionGroupBoundingLine"
                        ref={index === 0 ? boundingBoxRef : null}
                        visible={false}
                        position={box.position}
                        quaternion={new THREE.Quaternion(...box.rotation)}
                    >
                        <boxGeometry args={box.size} />
                        <meshBasicMaterial />
                    </mesh>
                </group>
            ))}
        </>
    );
};

export default BoundingBox;
