import { OpaqueRoom, YjsSyncStatus, IYjsProvider } from '@liveblocks/core';
import { Observable } from 'lib0/observable';
import * as Y from 'yjs';
import { PermanentUserData, Doc } from 'yjs';
import { User, JsonObject, BaseUserMeta } from '@liveblocks/client';

type MetaClientState = {
    clock: number;
    lastUpdated: number;
};
/**
 * This class will store Yjs awareness in Liveblock's presence under the __yjs key
 * IMPORTANT: The Yjs awareness protocol uses ydoc.clientId to reference users
 * to their respective documents. To avoid mapping Yjs clientIds to liveblock's connectionId,
 * we simply set the clientId of the doc to the connectionId. Then no further mapping is required
 */
declare class Awareness extends Observable<unknown> {
    private room;
    doc: Y.Doc;
    states: Map<number, unknown>;
    actorToClientMap: Map<number, number>;
    meta: Map<number, MetaClientState>;
    _checkInterval: number;
    private othersUnsub;
    constructor(doc: Y.Doc, room: OpaqueRoom);
    rebuildActorToClientMap(others: readonly User<JsonObject, BaseUserMeta>[]): void;
    destroy(): void;
    getLocalState(): JsonObject | null;
    setLocalState(state: Partial<JsonObject> | null): void;
    setLocalStateField(field: string, value: JsonObject | null): void;
    getStates(): Map<number, unknown>;
}

declare class yDocHandler extends Observable<unknown> {
    private unsubscribers;
    private _synced;
    private doc;
    private updateRoomDoc;
    private fetchRoomDoc;
    private useV2Encoding;
    private localSnapshotHashΣ;
    private remoteSnapshotHashΣ;
    private hasEverSyncedΣ;
    private debounceTimer;
    private static readonly DEBOUNCE_INTERVAL_MS;
    private isLocalAndRemoteSnapshotEqualΣ;
    constructor({ doc, isRoot, updateDoc, fetchDoc, useV2Encoding, }: {
        doc: Y.Doc;
        isRoot: boolean;
        updateDoc: (update: Uint8Array, guid?: string) => void;
        fetchDoc: (vector: string, guid?: string) => void;
        useV2Encoding: boolean;
    });
    handleServerUpdate: ({ update, stateVector, readOnly, v2, remoteSnapshotHash, }: {
        update: Uint8Array;
        stateVector: string | null;
        readOnly: boolean;
        v2?: boolean;
        remoteSnapshotHash: string;
    }) => void;
    syncDoc: () => void;
    get synced(): boolean;
    set synced(state: boolean);
    private debounced_updateLocalSnapshot;
    private updateHandler;
    experimental_getSyncStatus(): YjsSyncStatus;
    destroy(): void;
}

type ProviderOptions = {
    enablePermanentUserData?: boolean;
    autoloadSubdocs?: boolean;
    offlineSupport_experimental?: boolean;
    useV2Encoding_experimental?: boolean;
};
declare class LiveblocksYjsProvider extends Observable<unknown> implements IYjsProvider {
    private readonly room;
    private readonly rootDoc;
    private readonly options;
    private indexeddbProvider;
    private isPaused;
    private readonly unsubscribers;
    readonly awareness: Awareness;
    readonly rootDocHandler: yDocHandler;
    private readonly subdocHandlersΣ;
    private readonly syncStatusΣ;
    readonly permanentUserData?: PermanentUserData;
    constructor(room: OpaqueRoom, doc: Doc, options?: ProviderOptions);
    private setupOfflineSupport;
    private handleSubdocs;
    private updateDoc;
    private fetchDoc;
    private createSubdocHandler;
    loadSubdoc: (guid: string) => boolean;
    private syncDoc;
    get useV2Encoding(): boolean;
    get synced(): boolean;
    pause(): Promise<void>;
    unpause(): void;
    getStatus(): YjsSyncStatus;
    destroy(): void;
    clearOfflineData(): Promise<void>;
    getYDoc(): Doc;
    disconnect(): void;
    connect(): void;
    get subdocHandlers(): Map<string, yDocHandler>;
    set subdocHandlers(value: Map<string, yDocHandler>);
}

/**
 * Get a LiveblocksYjsProvider for a room.
 * @param room - The room to get the provider for.
 * @param options - The options for the provider.
 * @returns A LiveblocksYjsProvider for the room.
 */
declare const getYjsProviderForRoom: (room: OpaqueRoom, options?: ProviderOptions, forceNewProvider?: boolean) => LiveblocksYjsProvider;

export { LiveblocksYjsProvider, type ProviderOptions, getYjsProviderForRoom };
