/**
 * SocketIOProvider instance configuration. Here you can configure:
 * - autoConnect: (Optional) Will try to connect to the server when the instance is created if true; otherwise you have to call `provider.connect()` manually
 * - awareness: (Optional) Give an existing awareness
 * - resyncInterval: (Optional) Specify the number of milliseconds to set an interval to synchronize the document,
 *   if it is greater than 0 enable the synchronization interval (by default is -1)
 * - disableBc: (Optional) This boolean disable the broadcast channel functionality, by default is false (broadcast channel enabled)
 * - onConnect: (Optional) Set a callback that will triggered immediately when the socket is connected
 * - onDisconnect: (Optional) Set a callback that will triggered immediately when the socket is disconnected
 * - onConnectError: (Optional) Set a callback that will triggered immediately when the occurs a socket connection error
 */
/**
 * The socket io provider class to sync a document
 */
export class SocketIOProvider extends Observable<any> {
    /**
     * SocketIOProvider constructor
     * @constructor
     * @param {string} url The connection url from server
     * @param {string} roomName The document's room name
     * @param {Y.Doc} doc The yjs document
     * @param options Configuration options to the SocketIOProvider
     */
    constructor(url: string, roomName: string, doc: Y.Doc, { autoConnect, awareness, resyncInterval, disableBc, auth, }: {
        autoConnect?: boolean;
        awareness?: AwarenessProtocol.Awareness;
        resyncInterval?: number;
        disableBc?: boolean;
        auth?: {};
    });
    /**
     * The connection url to server. Example: `ws://localhost:3001`
     * @type {string}
     */
    _url: string;
    /**
     * The name of the document room
     * @type {string}
     */
    roomName: string;
    /**
     * The broadcast channel room
     * @type {string}
     * @private
     */
    private _broadcastChannel;
    /**
     * The socket connection
     * @type {Socket}
     */
    socket: Socket;
    /**
     * The yjs document
     * @type {Y.Doc}
     */
    doc: Y.Doc;
    /**
     * The awareness
     * @type {AwarenessProtocol.Awareness}
     */
    awareness: AwarenessProtocol.Awareness;
    /**
     * Disable broadcast channel, by default is false
     * @type {boolean}
     */
    disableBc: boolean;
    /**
     * The broadcast channel connection status indicator
     * @type {boolean}
     */
    bcconnected: boolean;
    /**
     * The document's sync status indicator
     * @type {boolean}
     * @private
     */
    private _synced;
    /**
     * Interval to emit `sync-step-1` to sync changes
     * @type {NodeJS.Timer | null}
     * @private
     */
    private resyncInterval;
    /**
     * Broadcast channel room getter
     * @type {string}
     */
    get broadcastChannel(): string;
    /**
     * URL getter
     * @type {string}
     */
    get url(): string;
    /**
     * Synchronized state flag setter
     */
    set synced(arg: boolean);
    /**
     * Synchronized state flag getter
     * @type {boolean}
     */
    get synced(): boolean;
    /**
     * This function initializes the socket event listeners to synchronize document changes.
     *
     *  The synchronization protocol is as follows:
     *  - A server emits the sync step one event (`sync-step-1`) which sends the document as a state vector
     *    and the sync step two callback as an acknowledgment according to the socket io acknowledgments.
     *  - When the client receives the `sync-step-1` event, it executes the `syncStep2` acknowledgment callback and sends
     *    the difference between the received state vector and the local document (this difference is called an update).
     *  - The second step of the sync is to apply the update sent in the `syncStep2` callback parameters from the client
     *    to the document on the server side.
     *  - There is another event (`sync-update`) that is emitted from the server, which sends an update for the document,
     *    and when the client receives this event, it applies the received update to the local document.
     *  - When an update is applied to a document, it will fire the document's "update" event, which
     *    sends the update to the server.
     * @type {() => void}
     * @private
     */
    private initSyncListeners;
    /**
     * This function initializes socket event listeners to synchronize awareness changes.
     *
     *  The awareness protocol is as follows:
     *  - The server emits the `awareness-update` event by sending the awareness update.
     *  - The client receives that event and applies the received update to the local awareness.
     *  - When an update is applied to awareness, the awareness "update" event will fire, which
     *    sends the update to the server.
     * @type {() => void}
     * @private
     */
    private initAwarenessListeners;
    /**
     * This function initialize the window or process events listener. Specifically set ups the
     * window `beforeunload` and process `exit` events to remove the client from the awareness.
     * @type {() => void}
     */
    initSystemListeners: () => void;
    connect(): void;
    /**
     * This function runs when the socket connects and reconnects and emits the `sync-step-1`
     * and `awareness-update` socket events to start synchronization.
     *
     *  Also starts the resync interval if is enabled.
     * @private
     * @param  onConnect (Optional) A callback that will be triggered every time that socket is connected or reconnected
     * @param  resyncInterval (Optional) A number of milliseconds for interval of synchronize
     */
    private onSocketConnection;
    disconnect(): void;
    /**
     * This function runs when the socket is disconnected and emits the socket event `awareness-update`
     * which removes this client from awareness.
     */
    onSocketDisconnection: (event: any) => void;
    /**
     * This function is executed when the socket connection fails.
     */
    onSocketConnectionError: (error: any) => void;
    /**
     * This function is executed when the document is updated, if the instance that
     * emit the change is not this, it emit the changes by socket and broadcast channel.
     * @private
     * @param {Uint8Array} update Document update
     * @param {SocketIOProvider} origin The SocketIOProvider instance that emits the change.
     * @type {(update: Uint8Array, origin: SocketIOProvider) => void}
     */
    private onUpdateDoc;
    /**
     * This function is called when the server emits the `sync-update` event and applies the received update to the local document.
     * @private
     * @param {Uint8Array}update A document update received by the `sync-update` socket event
     * @type {(update: Uint8Array) => void}
     */
    private onSocketSyncUpdate;
    /**
     * This function is executed when the local awareness changes and this broadcasts the changes per socket and broadcast channel.
     * @private
     * @param {{ added: number[], updated: number[], removed: number[] }} awarenessChanges The clients added, updated and removed
     * @param {SocketIOProvider | null} origin The SocketIOProvider instance that emits the change.
     * @type {({ added, updated, removed }: { added: number[], updated: number[], removed: number[] }, origin: SocketIOProvider | null) => void}
     */
    private awarenessUpdate;
    /**
     * This function is executed when the windows will be unloaded or the process will be closed and this
     * will remove the local client from awareness.
     * @private
     * @type {() => void}
     */
    private beforeUnloadHandler;
    /**
     * This function subscribes the provider to the broadcast channel and initiates synchronization by broadcast channel.
     * @type {() => void}
     */
    connectBc: () => void;
    /**
     * This function unsubscribes the provider from the broadcast channel and before unsubscribing, updates the awareness.
     * @type {() => void}
     */
    disconnectBc: () => void;
    /**
     * This method handles messages received by the broadcast channel and responds to them.
     * @param {{ type: string, data: any }} message The object message received by broadcast channel
     * @param {SocketIOProvider} origin The SocketIOProvider instance that emits the change
     * @type {(message: { type: string, data: any }, origin: SocketIOProvider) => void}
     */
    onBroadcastChannelMessage: (message: {
        type: string;
        data: any;
    }, origin: SocketIOProvider) => void;
}
import { Observable } from "lib0/observable";
import { Socket } from "socket.io-client";
import * as Y from "yjs";
import * as AwarenessProtocol from "y-protocols/awareness";
