import { Workspace } from '@blockeditor/store';
import { ElementModel } from './base.js';
import { BrushElementModel } from './brush.js';
import { ConnectorElementModel } from './connector.js';
import { setCreateState } from './decorators.js';
import { GroupElementModel } from './group.js';
import { ShapeElementModel } from './shape.js';
import { TextElementModel } from './text.js';
const elementsCtorMap = {
    group: GroupElementModel,
    connector: ConnectorElementModel,
    shape: ShapeElementModel,
    brush: BrushElementModel,
    text: TextElementModel,
};
export function createElementModel(type, id, yMap, model, options) {
    const stashed = new Map();
    const Ctor = elementsCtorMap[type];
    if (!Ctor) {
        throw new Error(`Invalid element type: ${yMap.get('type')}`);
    }
    setCreateState(true, options.skipFieldInit ?? false);
    const elementModel = new Ctor({
        yMap,
        model,
        stashedStore: stashed,
        onChange: props => options.onChange({ id, props }),
    });
    setCreateState(false, false);
    const dispose = onElementChange(yMap, props => {
        options.onChange({
            id,
            props,
        });
    });
    return {
        model: elementModel,
        dispose,
    };
}
function onElementChange(yMap, callback) {
    const observer = (events) => {
        const props = {};
        const event = events[0];
        event.keysChanged.forEach(key => {
            const type = event.changes.keys.get(key);
            const oldValue = event.changes.keys.get(key)?.oldValue;
            if (!type) {
                return;
            }
            if (type.action === 'update' || type.action === 'add') {
                props[key] = { oldValue };
            }
        });
        callback(props);
    };
    yMap.observeDeep(observer);
    return () => {
        yMap.observeDeep(observer);
    };
}
export function propsToY(type, props) {
    const ctor = elementsCtorMap[type];
    if (!ctor) {
        throw new Error(`Invalid element type: ${type}`);
    }
    // @ts-ignore
    return (ctor.propsToY ?? ElementModel.propsToY)(props);
}
export function createModelFromProps(props, model, options) {
    const { type, id, ...rest } = props;
    if (!id) {
        throw new Error('Cannot find id in props');
    }
    const yMap = new Workspace.Y.Map();
    const elementModel = createElementModel(type, id, yMap, model, options);
    props = propsToY(type, props);
    yMap.set('type', type);
    yMap.set('id', id);
    Object.keys(rest).forEach(key => {
        // @ts-ignore
        elementModel.model[key] = props[key];
    });
    // @ts-ignore
    elementModel.model._preserved.clear();
    return elementModel;
}
//# sourceMappingURL=index.js.map