import { ModelHubSubscription, ModelServiceSubscription } from '@eclipse-emfcloud/model-service';
import { Deferred } from '@theia/core/lib/common/promise-util';
import { Operation } from 'fast-json-patch';
import { ModelHubClient, ModelHubProtocol } from '../common';
import { ModelHubTracker, ModelHubTrackingSubscription } from '../common/model-hub-tracker';
export declare const FrontendModelHubSubscriber: unique symbol;
/**
 * An injectable service for creation of subscriptions to receive
 * notifications of changes in model state in the {@link ModelHubProtocol}.
 * Most clients will not need to use this directly because it is more
 * convenient to use the {@link _FrontendModelHub | FrontendModelHub} API, instead.
 */
export interface FrontendModelHubSubscriber<K = string> {
    /**
     * Subscribe to model hub notifications.
     *
     * @template M the type of model object that is expected to send notifications
     *
     * @param context the model hub context in which to subscribe to models
     */
    subscribe<M extends object = object>(context: string): Promise<ModelHubSubscription<K, M>>;
    /**
     * Subscribe to model notifications.
     *
     * @param context the model hub context in which to subscribe to models
     * @param modelIds the models to which to subscribe, or none to subscribe to all
     */
    subscribe<M extends object = object>(context: string, ...modelIds: K[]): Promise<ModelServiceSubscription<K, M>>;
    /**
     * Get the given model from the local (frontend) cache.
     * If it is not yet cached, it is retrieved from the backend.
     *
     * @param context the model hub context in which to retrieve a model
     * @param modelId the model to retrieve
     */
    getModel<M extends object>(context: string, modelId: K): Promise<M>;
}
/**
 * A subscription registered on the subscriber is augmented by the model IDs that it
 * watches (if any).
 */
type SubscriberSubscription<K, M extends object = object> = ModelHubSubscription<K, M> & {
    context: unknown;
    modelIds: K[];
};
/** Utility type requiring some subset of keys in a type. */
type With<T, K extends keyof T> = T & Required<Pick<T, K>>;
export declare class FrontendModelHubSubscriberImpl<K = string> implements FrontendModelHubSubscriber<K>, ModelHubTracker {
    readonly client: ModelHubClient<K>;
    protected readonly subscriptions: SubscriberSubscription<K>[];
    protected readonly trackingSubs: ModelHubTrackingSubscription[];
    protected readonly modelCaches: Map<string, Map<K, object>>;
    protected readonly modelHub: Deferred<ModelHubProtocol<K>>;
    private readonly knownModelHubs;
    /**
     * My own subscription to the model hub that implements
     * the pipeline of incremental model caching and client
     * subscription multiplexing.
     */
    private subscriptionPipelines;
    setModelHub(modelHub: ModelHubProtocol<K>): void;
    /**
     * Look up a subscription and the model that will have to be passed along
     * to any of its call-backs that are subsequently invoked.
     *
     * @param subscriptionId the subscription to look up
     * @param modelId a model to resolve to pass on to the subscription
     * @returns resolved subscription and model, as long as both are resolved
     */
    protected lookupSubs<M extends object>(subscriptionId: number, modelId: K): Promise<{
        subs: ModelServiceSubscription<K>[];
        model: M;
    }> | undefined;
    /**
     * Look up a subscription for the purpose of invoking hub lifecycle call-backs.
     * As for now the only call-back is `onModelHubDisposed`, we return only subs
     * that have this call-back.
     *
     * @param subscriptionId the subscription to look up
     * @returns resolved hub subscriptions
     */
    protected lookupHubSubs(subscriptionId: number): Promise<With<ModelHubSubscription<K>, 'onModelHubDisposed'>[]> | undefined;
    private getSubscriptionContext;
    /**
     * React to the notification from the backend that a subscription
     * was closed on that end by closing the corresponding frontend
     * subscriptions.
     *
     * @param subscriptionId a backend subscription that was closed
     */
    protected closeSub(subscriptionId: number): void;
    protected closeContext(context: string): void;
    protected updateModelCache(subscriptionId: number, modelId: K, delta?: Operation[]): void;
    protected removeModelCache(subscriptionId: number, modelId: K): void;
    getModel<M extends object>(context: string, modelId: K): Promise<M>;
    protected getModelCache(context: string): Map<K, object>;
    subscribe<M extends object = object>(context: string, ...modelIds: K[]): Promise<ModelHubSubscription<K, M>>;
    /**
     * Ensure that I am myself subscribed to the model hub to maintain my model cache
     * and multiplex my clients' subscriptions.
     */
    private ensureSubscriptionPipeline;
    trackModelHubs(): ModelHubTrackingSubscription;
    isModelHubAvailable(context: string): boolean;
}
export {};
//# sourceMappingURL=frontend-model-hub-subscriber.d.ts.map