import { observer } from "mobx-react-lite";
import type { ObjectType, RuntimeObjectInstance } from "../types";
import { forwardRef, useMemo } from "react";
import type { Group } from "three";
import { Instance, Instances } from "@react-three/drei";
import type { ThreeEvent } from "@react-three/fiber";
import { state } from "../state";
import { TrimeshCollider } from "@react-three/rapier";
import { SyncRigidBody } from "./SyncRigidBody";
import { runInAction } from "mobx";
import { buildObjectTrimesh } from "../utils/graphics/mesh";

type ObjectViewInternalProps = {
    object: Omit<RuntimeObjectInstance, 'typeId'>;
    objectType: ObjectType;
    onClick?: (e: ThreeEvent<MouseEvent>) => void;
}

export const ObjectViewInternal = observer(forwardRef<Group | null, ObjectViewInternalProps>(
    function ({ object, objectType, onClick }, ref) {
        const trimeshArgs = useMemo(
            () => buildObjectTrimesh(objectType, state.world.data.voxelTypes),
            // eslint-disable-next-line react-hooks/exhaustive-deps
            [objectType.id]
        );

        return (
            <SyncRigidBody
                colliders={false}
                gravityScale={object.physics ? 1 : 0.1}
                onSync={(data) => {
                    runInAction(() => {
                        const obj = state.game?.scene.objects[object.id];
                        if (obj) {
                            obj.position = data.position;
                            obj.rotation = data.rotation;
                            obj.linearVelocity = data.linearVelocity;
                            obj.radialVelocity = data.radialVelocity;
                        }
                    });
                }}
            >
                <group
                    ref={ref}
                    name={`${object.id} (${objectType.id} instance)`}
                    position={object.position}
                    rotation={object.rotation}
                    scale={object.scale}
                    onClick={onClick}
                >
                    {
                        object.cache.voxelGroups.map((vg) =>
                            <Instances key={vg.id} limit={vg.positions.length}>
                                <boxGeometry args={[1, 1, 1]} />
                                <meshStandardMaterial color={vg.color} opacity={vg.opacity} transparent={vg.opacity < 1} />
                                {vg.positions.map((pos, i) => <Instance key={i} position={pos} />)}
                            </Instances>
                        )
                    }
                    {trimeshArgs && <TrimeshCollider args={trimeshArgs} />}
                </group>
            </SyncRigidBody>
        );
    }
));
