import { jsx as _jsx } from "@emotion/react/jsx-runtime";
import React, { useEffect, useContext, useState, useRef, } from 'react';
import { EngineContext } from '../engine-provider';
import { useStore, useConfig } from '../../hooks';
import { includesArray } from '../../../utils/includes-array';
import { getSavedSelectedSceneId } from '../../../utils/get-saved-selected-scene-id';
import { getSavedInspectedEntity } from '../../../utils/get-saved-inspected-entity';
import { getSavedEntitySelection } from '../../../utils/get-saved-entity-selection';
import { EventType } from '../../../events';
import { persistentStorage } from '../../../persistent-storage';
import { getEntityType } from './get-entity-type';
import { getSceneId } from './get-scene-id';
export const InspectedEntityContext = React.createContext({});
export const EntitySelectionContext = React.createContext({ paths: [] });
// Provider to store selected entity details and sync selection update to avoid issues
// when entity was deleted but state has not updated yet
export const EntityExplorerProvider = ({ children, }) => {
    var _a;
    const { world } = (_a = useContext(EngineContext)) !== null && _a !== void 0 ? _a : {};
    const store = useStore();
    const [entityData, setEntityData] = useState(() => ({
        path: getSavedInspectedEntity(store),
        type: getEntityType(getSavedInspectedEntity(store)),
    }));
    const selectedSceneRef = useRef(getSavedSelectedSceneId(store));
    const [entitySelection, setEntitySelection] = useState(() => ({
        paths: getSavedEntitySelection(store),
    }));
    const scenes = useConfig('scenes');
    useEffect(() => {
        if (world === undefined || scenes === undefined) {
            return;
        }
        const isDeleted = scenes.every((scene) => scene.id !== selectedSceneRef.current);
        if (isDeleted) {
            world.dispatchEvent(EventType.SelectScene, { sceneId: undefined });
            selectedSceneRef.current = undefined;
            persistentStorage.set('selectedScene', undefined);
        }
    }, [world, scenes]);
    useEffect(() => {
        if (!world) {
            return () => { };
        }
        const handleInspectEntity = (event) => {
            const { path } = event;
            const sceneId = getSceneId(path);
            if (sceneId !== undefined && sceneId !== selectedSceneRef.current) {
                world.dispatchEvent(EventType.SelectScene, { sceneId });
                selectedSceneRef.current = sceneId;
                persistentStorage.set('selectedScene', sceneId);
            }
            setEntityData({ path, type: getEntityType(path) });
            world.dispatchEvent(EventType.InspectedEntityChange, { path });
            persistentStorage.set('inspectedEntity', path);
        };
        world.addEventListener(EventType.InspectEntity, handleInspectEntity);
        return () => {
            world.removeEventListener(EventType.InspectEntity, handleInspectEntity);
        };
    }, [world]);
    useEffect(() => {
        if (!world) {
            return () => { };
        }
        const handleSelectEntities = (event) => {
            setEntitySelection({ paths: event.paths });
            persistentStorage.set('entitySelection', event.paths);
            world.dispatchEvent(EventType.SelectEntitiesChange, { paths: event.paths });
        };
        world.addEventListener(EventType.SelectEntities, handleSelectEntities);
        return () => {
            world.removeEventListener(EventType.SelectEntities, handleSelectEntities);
        };
    }, [world]);
    useEffect(() => {
        if (world === undefined) {
            return () => { };
        }
        const unsubscribe = store.subscribe((updatedPath) => {
            const newSelection = entitySelection.paths.filter((path) => {
                if (!includesArray(path, updatedPath)) {
                    return true;
                }
                return store.get(path) !== undefined;
            });
            if (entitySelection.paths.length !== newSelection.length) {
                setEntitySelection({ paths: newSelection });
                world.dispatchEvent(EventType.SelectEntitiesChange, { paths: newSelection });
                persistentStorage.set('entitySelection', newSelection);
            }
            const { path } = entityData;
            if (!path || !includesArray(path, updatedPath)) {
                return;
            }
            if (store.get(path) === undefined) {
                const newPath = newSelection.at(-1);
                setEntityData({ path: newPath, type: getEntityType(newPath) });
                world.dispatchEvent(EventType.InspectedEntityChange, { path: newPath });
                persistentStorage.set('inspectedEntity', newPath);
            }
        });
        return () => {
            unsubscribe();
        };
    }, [world, store, entitySelection, entityData.path]);
    return (_jsx(EntitySelectionContext.Provider, { value: entitySelection, children: _jsx(InspectedEntityContext.Provider, { value: entityData, children: children }) }));
};
