import { Awareness } from "y-protocols/awareness";
import * as Y from "yjs";
import * as lib0_encoding0 from "lib0/encoding";
import { Encoder } from "lib0/encoding";
import { CloseEvent } from "@hocuspocus/common";
import { Decoder } from "lib0/decoding";

//#region packages/provider/src/EventEmitter.d.ts
declare class EventEmitter {
  callbacks: {
    [key: string]: Function[];
  };
  on(event: string, fn: Function): this;
  protected emit(event: string, ...args: any): this;
  off(event: string, fn?: Function): this;
  removeAllListeners(): void;
}
//#endregion
//#region packages/provider/src/IncomingMessage.d.ts
declare class IncomingMessage {
  data: any;
  encoder: Encoder;
  decoder: Decoder;
  constructor(data: any);
  peekVarString(): string;
  readVarUint(): MessageType;
  readVarString(): string;
  readVarUint8Array(): Uint8Array<ArrayBufferLike>;
  writeVarUint(type: MessageType): void;
  writeVarString(string: string): void;
  writeVarUint8Array(data: Uint8Array): void;
  length(): number;
}
//#endregion
//#region packages/provider/src/OutgoingMessage.d.ts
declare class OutgoingMessage implements OutgoingMessageInterface {
  encoder: Encoder;
  type?: MessageType;
  constructor();
  get(args: Partial<OutgoingMessageArguments>): Encoder | undefined;
  toUint8Array(): Uint8Array<ArrayBuffer>;
}
//#endregion
//#region packages/provider/src/OutgoingMessages/AuthenticationMessage.d.ts
declare class AuthenticationMessage extends OutgoingMessage {
  type: MessageType;
  description: string;
  get(args: Partial<OutgoingMessageArguments>): lib0_encoding0.Encoder;
}
//#endregion
//#region packages/provider/src/OutgoingMessages/AwarenessMessage.d.ts
declare class AwarenessMessage extends OutgoingMessage {
  type: MessageType;
  description: string;
  get(args: Partial<OutgoingMessageArguments>): lib0_encoding0.Encoder;
}
//#endregion
//#region packages/provider/src/OutgoingMessages/QueryAwarenessMessage.d.ts
declare class QueryAwarenessMessage extends OutgoingMessage {
  type: MessageType;
  description: string;
  get(args: Partial<OutgoingMessageArguments>): lib0_encoding0.Encoder;
}
//#endregion
//#region packages/provider/src/OutgoingMessages/SyncStepOneMessage.d.ts
declare class SyncStepOneMessage extends OutgoingMessage {
  type: MessageType;
  description: string;
  get(args: Partial<OutgoingMessageArguments>): lib0_encoding0.Encoder;
}
//#endregion
//#region packages/provider/src/OutgoingMessages/SyncStepTwoMessage.d.ts
declare class SyncStepTwoMessage extends OutgoingMessage {
  type: MessageType;
  description: string;
  get(args: Partial<OutgoingMessageArguments>): lib0_encoding0.Encoder;
}
//#endregion
//#region packages/provider/src/OutgoingMessages/UpdateMessage.d.ts
declare class UpdateMessage extends OutgoingMessage {
  type: MessageType;
  description: string;
  get(args: Partial<OutgoingMessageArguments>): lib0_encoding0.Encoder;
}
//#endregion
//#region packages/provider/src/types.d.ts
declare enum MessageType {
  Sync = 0,
  Awareness = 1,
  Auth = 2,
  QueryAwareness = 3,
  Stateless = 5,
  CLOSE = 7,
  SyncStatus = 8,
  Ping = 9,
  Pong = 10
}
declare enum WebSocketStatus {
  Connecting = "connecting",
  Connected = "connected",
  Disconnected = "disconnected"
}
type AuthorizedScope = "read-write" | "readonly";
interface OutgoingMessageInterface {
  encoder: Encoder;
  type?: MessageType;
}
interface OutgoingMessageArguments {
  documentName: string;
  token: string;
  document: Y.Doc;
  awareness: Awareness;
  clients: number[];
  states: Map<number, {
    [key: string]: any;
  }>;
  update: any;
  payload: string;
  encoder: Encoder;
}
interface Constructable<T> {
  new (...args: any): T;
}
type ConstructableOutgoingMessage = Constructable<AuthenticationMessage> | Constructable<AwarenessMessage> | Constructable<QueryAwarenessMessage> | Constructable<SyncStepOneMessage> | Constructable<SyncStepTwoMessage> | Constructable<UpdateMessage>;
type onAuthenticationFailedParameters = {
  reason: string;
};
type onAuthenticatedParameters = {
  scope: AuthorizedScope;
};
type onOpenParameters = {
  event: Event;
};
type onMessageParameters = {
  event: MessageEvent;
  message: IncomingMessage;
};
type onOutgoingMessageParameters = {
  message: OutgoingMessage;
};
type onStatusParameters = {
  status: WebSocketStatus;
};
type onSyncedParameters = {
  state: boolean;
};
type onUnsyncedChangesParameters = {
  number: number;
};
type onDisconnectParameters = {
  event: CloseEvent;
};
type onCloseParameters = {
  event: CloseEvent;
};
type onAwarenessUpdateParameters = {
  states: StatesArray;
};
type onAwarenessChangeParameters = {
  states: StatesArray;
};
type onStatelessParameters = {
  payload: string;
};
type StatesArray = {
  clientId: number;
  [key: string | number]: any;
}[];
//#endregion
//#region packages/provider/src/HocuspocusProviderWebsocket.d.ts
type HocuspocusWebSocket = WebSocket & {
  identifier: string;
};
type HocusPocusWebSocket = HocuspocusWebSocket;
type HocuspocusProviderWebsocketConfiguration = Required<Pick<CompleteHocuspocusProviderWebsocketConfiguration, "url">> & Partial<CompleteHocuspocusProviderWebsocketConfiguration>;
interface CompleteHocuspocusProviderWebsocketConfiguration {
  /**
   * Whether to connect automatically when creating the provider instance. Default=true
   */
  autoConnect: boolean;
  /**
   * URL of your @hocuspocus/server instance
   */
  url: string;
  /**
   * By default, trailing slashes are removed from the URL. Set this to true
   * to preserve trailing slashes if your server configuration requires them.
   */
  preserveTrailingSlash: boolean;
  /**
   * An optional WebSocket polyfill, for example for Node.js
   */
  WebSocketPolyfill: any;
  /**
   * Disconnect when no message is received for the defined amount of milliseconds.
   */
  messageReconnectTimeout: number;
  /**
   * The delay between each attempt in milliseconds. You can provide a factor to have the delay grow exponentially.
   */
  delay: number;
  /**
   * The initialDelay is the amount of time to wait before making the first attempt. This option should typically be 0 since you typically want the first attempt to happen immediately.
   */
  initialDelay: number;
  /**
   * The factor option is used to grow the delay exponentially.
   */
  factor: number;
  /**
   * The maximum number of attempts or 0 if there is no limit on number of attempts.
   */
  maxAttempts: number;
  /**
   * minDelay is used to set a lower bound of delay when jitter is enabled. This property has no effect if jitter is disabled.
   */
  minDelay: number;
  /**
   * The maxDelay option is used to set an upper bound for the delay when factor is enabled. A value of 0 can be provided if there should be no upper bound when calculating delay.
   */
  maxDelay: number;
  /**
   * If jitter is true then the calculated delay will be a random integer value between minDelay and the calculated delay for the current iteration.
   */
  jitter: boolean;
  /**
   * A timeout in milliseconds. If timeout is non-zero then a timer is set using setTimeout. If the timeout is triggered then future attempts will be aborted.
   */
  timeout: number;
  handleTimeout: (() => Promise<unknown>) | null;
  onOpen: (data: onOpenParameters) => void;
  onConnect: () => void;
  onMessage: (data: onMessageParameters) => void;
  onOutgoingMessage: (data: onOutgoingMessageParameters) => void;
  onStatus: (data: onStatusParameters) => void;
  onDisconnect: (data: onDisconnectParameters) => void;
  onClose: (data: onCloseParameters) => void;
  onDestroy: () => void;
  onAwarenessUpdate: (data: onAwarenessUpdateParameters) => void;
  onAwarenessChange: (data: onAwarenessChangeParameters) => void;
  /**
   * Map of attached providers keyed by documentName.
   */
  providerMap: Map<string, HocuspocusProvider>;
}
declare class HocuspocusProviderWebsocket extends EventEmitter {
  private static readonly DEDUPLICATABLE_TYPES;
  private messageQueue;
  configuration: CompleteHocuspocusProviderWebsocketConfiguration;
  webSocket: HocusPocusWebSocket | null;
  webSocketHandlers: {
    [key: string]: any;
  };
  shouldConnect: boolean;
  status: WebSocketStatus;
  lastMessageReceived: number;
  identifier: number;
  intervals: any;
  connectionAttempt: {
    resolve: (value?: any) => void;
    reject: (reason?: any) => void;
  } | null;
  constructor(configuration: HocuspocusProviderWebsocketConfiguration);
  receivedOnOpenPayload?: Event | undefined;
  onOpen(event: Event): Promise<void>;
  attach(provider: HocuspocusProvider): void;
  detach(provider: HocuspocusProvider): void;
  setConfiguration(configuration?: Partial<HocuspocusProviderWebsocketConfiguration>): void;
  cancelWebsocketRetry?: () => void;
  connect(): Promise<unknown>;
  attachWebSocketListeners(ws: HocusPocusWebSocket, reject: Function): void;
  cleanupWebSocket(): void;
  createWebSocketConnection(): Promise<unknown>;
  onMessage(event: MessageEvent): void;
  /**
   * Send application-level Pong response to server Ping
   */
  private sendPong;
  resolveConnectionAttempt(): void;
  stopConnectionAttempt(): void;
  rejectConnectionAttempt(): void;
  closeTries: number;
  checkConnection(): void;
  get serverUrl(): string;
  get url(): string;
  disconnect(): void;
  private parseQueuedMessage;
  private addToQueue;
  send(message: any): void;
  onClose({
    event
  }: onCloseParameters): void;
  destroy(): void;
}
//#endregion
//#region packages/provider/src/HocuspocusProvider.d.ts
type HocuspocusProviderConfiguration = Required<Pick<CompleteHocuspocusProviderConfiguration, "name">> & Partial<CompleteHocuspocusProviderConfiguration> & ((Required<Pick<CompleteHocuspocusProviderWebsocketConfiguration, "url">> & Partial<Pick<CompleteHocuspocusProviderWebsocketConfiguration, "preserveTrailingSlash">>) | Required<Pick<CompleteHocuspocusProviderConfiguration, "websocketProvider">>);
interface CompleteHocuspocusProviderConfiguration {
  /**
   * The identifier/name of your document
   */
  name: string;
  /**
   * The actual Y.js document
   */
  document: Y.Doc;
  /**
   * An Awareness instance to keep the presence state of all clients.
   *
   * You can disable sharing awareness information by passing `null`.
   * Note that having no awareness information shared across all connections will break our ping checks
   * and thus trigger reconnects. You should always have at least one Provider with enabled awareness per
   * socket connection, or ensure that the Provider receives messages before running into `HocuspocusProviderWebsocket.messageReconnectTimeout`.
   */
  awareness: Awareness | null;
  /**
   * A token that’s sent to the backend for authentication purposes.
   */
  token: string | (() => string) | (() => Promise<string>) | null;
  /**
   * Hocuspocus websocket provider
   */
  websocketProvider: HocuspocusProviderWebsocket;
  /**
   * Enable session-aware multiplexing. When true, the provider embeds a unique
   * sessionId in the documentName field of every message, allowing multiple
   * providers with the same document name on a single WebSocket connection.
   *
   * Only set this to `true` when connecting to a v4 server that does
   * support session awareness.
   *
   * Default: false
   */
  sessionAwareness: boolean;
  /**
   * Force syncing the document in the defined interval.
   */
  forceSyncInterval: false | number;
  /**
   * Batch outgoing document and awareness updates over a short window (in
   * milliseconds) instead of sending one message per change. During heavy
   * editing this drastically reduces the number of websocket messages: Yjs
   * updates collected in the window are merged with `Y.mergeUpdates` into a
   * single message, and awareness collapses to the latest state of each
   * changed client.
   *
   * The window is a fixed batch, not a resetting debounce, so the added
   * latency is capped at `flushDelay` even while the user keeps typing. Keep
   * it small (e.g. 500) to avoid delaying what other clients see.
   *
   * Set to `false` (the default) to send every change immediately.
   */
  flushDelay: false | number;
  onAuthenticated: (data: onAuthenticatedParameters) => void;
  onAuthenticationFailed: (data: onAuthenticationFailedParameters) => void;
  onOpen: (data: onOpenParameters) => void;
  onConnect: () => void;
  onStatus: (data: onStatusParameters) => void;
  onMessage: (data: onMessageParameters) => void;
  onOutgoingMessage: (data: onOutgoingMessageParameters) => void;
  onSynced: (data: onSyncedParameters) => void;
  onDisconnect: (data: onDisconnectParameters) => void;
  onClose: (data: onCloseParameters) => void;
  onDestroy: () => void;
  onAwarenessUpdate: (data: onAwarenessUpdateParameters) => void;
  onAwarenessChange: (data: onAwarenessChangeParameters) => void;
  onStateless: (data: onStatelessParameters) => void;
  onUnsyncedChanges: (data: onUnsyncedChangesParameters) => void;
}
declare class AwarenessError extends Error {
  code: number;
}
declare class HocuspocusProvider extends EventEmitter {
  configuration: CompleteHocuspocusProviderConfiguration;
  isSynced: boolean;
  unsyncedChanges: number;
  isAuthenticated: boolean;
  authorizedScope: AuthorizedScope | undefined;
  manageSocket: boolean;
  private _isAttached;
  /**
   * Outgoing document updates buffered for the current `flushDelay` window.
   */
  private pendingUpdates;
  /**
   * Awareness client ids whose latest state should be sent on the next flush.
   */
  private pendingAwarenessClients;
  private flushTimeout;
  /**
   * Unique session identifier for this provider instance.
   * Used for multiplexing multiple providers with the same document name on a single WebSocket.
   */
  sessionId: string;
  /**
   * The effective name used as the first VarString in messages.
   * When `sessionAwareness` is enabled, returns a composite key (documentName\0sessionId).
   * Otherwise, returns the plain document name.
   */
  get effectiveName(): string;
  intervals: any;
  constructor(configuration: HocuspocusProviderConfiguration);
  boundDocumentUpdateHandler: (update: Uint8Array, origin: any) => void;
  boundAwarenessUpdateHandler: ({
    added,
    updated,
    removed
  }: any, origin: any) => void;
  boundPageHide: () => void;
  boundOnOpen: (event: Event) => Promise<void>;
  boundOnClose: () => void;
  forwardConnect: () => this;
  forwardStatus: (e: onStatusParameters) => this;
  forwardClose: (e: onCloseParameters) => this;
  forwardDisconnect: (e: onDisconnectParameters) => this;
  forwardDestroy: () => this;
  setConfiguration(configuration?: Partial<HocuspocusProviderConfiguration>): void;
  get document(): Y.Doc;
  get isAttached(): boolean;
  get awareness(): Awareness | null;
  get hasUnsyncedChanges(): boolean;
  private resetUnsyncedChanges;
  incrementUnsyncedChanges(): void;
  decrementUnsyncedChanges(): void;
  forceSync(): void;
  pageHide(): void;
  registerEventListeners(): void;
  sendStateless(payload: string): void;
  sendToken(): Promise<void>;
  private get batchingEnabled();
  documentUpdateHandler(update: Uint8Array, origin: any): void;
  awarenessUpdateHandler({
    added,
    updated,
    removed
  }: any, origin: any): void;
  private scheduleFlush;
  /**
   * Send everything buffered for the current `flushDelay` window right away.
   * Buffered document updates are merged into a single message and awareness
   * collapses to the latest state of each changed client. Safe to call when
   * nothing is pending.
   */
  flushPendingUpdates(): void;
  /**
   * Indicates whether a first handshake with the server has been established
   *
   * Note: this does not mean all updates from the client have been persisted to the backend. For this,
   * use `hasUnsyncedChanges`.
   */
  get synced(): boolean;
  set synced(state: boolean);
  receiveStateless(payload: string): void;
  connect(): Promise<unknown>;
  disconnect(): void;
  onOpen(event: Event): Promise<void>;
  getToken(): Promise<string | null>;
  startSync(): void;
  send(message: ConstructableOutgoingMessage, args: any): void;
  onMessage(event: MessageEvent): void;
  onClose(): void;
  destroy(): void;
  detach(): void;
  attach(): void;
  permissionDeniedHandler(reason: string): void;
  authenticatedHandler(scope: string): void;
  setAwarenessField(key: string, value: any): void;
}
//#endregion
export { AuthorizedScope, AwarenessError, CompleteHocuspocusProviderConfiguration, CompleteHocuspocusProviderWebsocketConfiguration, Constructable, ConstructableOutgoingMessage, HocusPocusWebSocket, HocuspocusProvider, HocuspocusProviderConfiguration, HocuspocusProviderWebsocket, HocuspocusProviderWebsocketConfiguration, HocuspocusWebSocket, MessageType, OutgoingMessageArguments, OutgoingMessageInterface, StatesArray, WebSocketStatus, onAuthenticatedParameters, onAuthenticationFailedParameters, onAwarenessChangeParameters, onAwarenessUpdateParameters, onCloseParameters, onDisconnectParameters, onMessageParameters, onOpenParameters, onOutgoingMessageParameters, onStatelessParameters, onStatusParameters, onSyncedParameters, onUnsyncedChangesParameters };