import { useThrelte } from '@threlte/core';
import { getContext, setContext, untrack } from 'svelte';
import { Object3D } from 'three';
import { traits, useWorld } from '../ecs';
import { useEnvironment } from './useEnvironment.svelte';
const selectedKey = Symbol('selected-frame-context');
const focusedKey = Symbol('focused-frame-context');
const focusedObject3dKey = Symbol('focused-object-3d-context');
export const provideSelection = () => {
    const world = useWorld();
    const { scene } = useThrelte();
    const environment = useEnvironment();
    let selected = $state.raw();
    let selectedInstance = $state();
    let focused = $state.raw();
    let focusedInstance = $state();
    $effect(() => {
        return world.onRemove(traits.Name, (entity) => {
            if (entity === selected)
                selected = undefined;
            if (entity === focused)
                focused = undefined;
        });
    });
    const selectedEntityContext = {
        get current() {
            return selected;
        },
        get instance() {
            return selectedInstance;
        },
        set(entity, instance) {
            selected = entity;
            selectedInstance = instance;
        },
    };
    setContext(selectedKey, selectedEntityContext);
    const focusedEntityContext = {
        get current() {
            return focused;
        },
        get instance() {
            return focusedInstance;
        },
        set(entity, instance) {
            focused = entity;
            focusedInstance = instance;
        },
    };
    setContext(focusedKey, focusedEntityContext);
    const focusedObject3d = $derived(focused ? scene.getObjectByName(focused)?.clone() : undefined);
    $effect(() => {
        const previousMode = untrack(() => environment.current.viewerMode);
        if (focusedObject3d) {
            environment.current.viewerMode = 'focus';
            return () => {
                environment.current.viewerMode = previousMode;
            };
        }
    });
    setContext(focusedObject3dKey, {
        get current() {
            return focusedObject3d;
        },
    });
    return {
        selection: selectedEntityContext,
        focus: focusedEntityContext,
    };
};
export const useFocusedEntity = () => {
    return getContext(focusedKey);
};
export const useSelectedEntity = () => {
    return getContext(selectedKey);
};
export const useFocusedObject3d = () => {
    return getContext(focusedObject3dKey);
};
export const useSelectedObject3d = () => {
    const selectedEntity = useSelectedEntity();
    const { scene } = useThrelte();
    const object = $derived.by(() => {
        if (!selectedEntity.current) {
            return;
        }
        return scene.getObjectByName(selectedEntity.current);
    });
    return {
        get current() {
            return object;
        },
    };
};
