import type { ReactElement } from 'react';
import type { SerializedStyles } from '@emotion/react';
import type { BatchAttrsStep, OverrideDocumentStepJSON as OverrideDocumentStep } from '@atlaskit/adf-schema/steps';
import type { JSONDocNode } from '@atlaskit/editor-json-transformer';
import type { Node as PMNode, Slice } from '@atlaskit/editor-prosemirror/model';
import type { EditorState, ReadonlyTransaction, Transaction } from '@atlaskit/editor-prosemirror/state';
import type { Step } from '@atlaskit/editor-prosemirror/transform';
import { token } from '@atlaskit/tokens';
import type { Providers } from '../provider-factory';
import type { GetResolvedEditorStateReason } from '../types';
export type NewCollabSyncUpErrorAttributes = {
    clientId?: number | string;
    lengthOfUnconfirmedSteps?: number;
    maxRetries: number;
    tries: number;
    version: number;
};
export type ResolvedEditorState<T = any> = {
    content: JSONDocNode | T;
    stepVersion: number;
    title: string | null;
};
export declare enum PROVIDER_ERROR_CODE {
    NO_PERMISSION_ERROR = "NO_PERMISSION_ERROR",
    INVALID_USER_TOKEN = "INVALID_USER_TOKEN",
    DOCUMENT_NOT_FOUND = "DOCUMENT_NOT_FOUND",
    LOCKED = "LOCKED",
    FAIL_TO_SAVE = "FAIL_TO_SAVE",
    DOCUMENT_RESTORE_ERROR = "DOCUMENT_RESTORE_ERROR",
    INITIALISATION_ERROR = "INITIALISATION_ERROR",
    NETWORK_ISSUE = "NETWORK_ISSUE",
    INVALID_PROVIDER_CONFIGURATION = "INVALID_PROVIDER_CONFIGURATION",
    INTERNAL_SERVICE_ERROR = "INTERNAL_SERVICE_ERROR",
    DOCUMENT_UPDATE_ERROR = "DOCUMENT_UPDATE_ERROR"
}
/**
 * This occurs when the provided user token is considered invalid for the given document ARI.
 * It happens during initialisation of the provider.
 * It could mean the document has been deleted (hence not found).
 * @message Message returned to editor, i.e User does not have permissions to access this document or document is not found
 * @recoverable It is recoverable, as we will try to refresh the token.
 */
type InsufficientEditingPermission = {
    code: PROVIDER_ERROR_CODE.NO_PERMISSION_ERROR;
    message: string;
    reason?: string;
    recoverable: boolean;
    /**
     * @deprecated switch to using either the error code or the recoverable flag
     */
    status?: number;
};
/**
 * Similar to InsufficientEditingPermission, but the user token is invalid because it has expired or been revoked.
 * It may also be an invalid token format.
 * This error is given to the provider by NCS.
 * @message Message returned to editor, i.e. The user token was invalid
 * @recoverable It is recoverable, as we will try to refresh the token.
 */
type InvalidUserToken = {
    code: PROVIDER_ERROR_CODE.INVALID_USER_TOKEN;
    message: string;
    recoverable: boolean;
    /**
     * @deprecated switch to using either the error code or the recoverable flag
     */
    status?: number;
};
/**
 * Document not found error, thrown when the provider is unable to find a document with the given ARI and user token.
 * It occurs during fetchCatchup, a function that fetches the latest document state during catchup.
 * We need to recieve a 404 from the document service to throw this error.
 * @message Message returned to editor, i.e. The requested document is not found
 * @recoverable It is recoverable, as the provider can try again later.
 */
type DocumentNotFound = {
    code: PROVIDER_ERROR_CODE.DOCUMENT_NOT_FOUND;
    message: string;
    recoverable: boolean;
    /**
     * @deprecated switch to using either the error code or the recoverable flag
     */
    status?: number;
};
/**
 * This error is thrown when the document is locked by another user.
 * The error is passed to us by NCS.
 * @message Message returned to editor, i.e. The document is currently not available, please try again later
 * @recoverable It is recoverable, as the provider can try again later.
 */
type Locked = {
    code: PROVIDER_ERROR_CODE.LOCKED;
    message: string;
    recoverable: boolean;
    status?: number;
};
/**
 * This error is thrown when the provider is unable to save the document.
 * This can happen when the connection to dynamoDB is lost, or when we do not have sufficient permissions (DYNAMO ERROR).
 * This error is given to us by NCS.
 * @message Message returned to editor, i.e. Collab service is not able to save changes
 * @recoverable It is not recoverable, as we don't want the user to continue editing a document that is not being saved.
 */
type FailToSave = {
    code: PROVIDER_ERROR_CODE.FAIL_TO_SAVE;
    message: string;
    recoverable: boolean;
    /**
     * @deprecated switch to using either the error code or the recoverable flag
     */
    status?: number;
};
/**
 * This error is thrown when the provider is unable to restore the document.
 * It occurs during onRestore, a function that restores the document to a previous version and reapplies unconfirmed steps.
 * onRestore is called when page recovery has emitted an 'init' event on a page client is currently connected to.
 * It could mean we failed to update the page metadata, or we failed to reapply unconfirmed steps.
 * @message Message returned to editor, i.e. Collab service unable to restore document
 * @recoverable It is not recoverable, as the provider has no further options after this.
 * The user will need to refresh the page to try again.
 */
type DocumentNotRestore = {
    code: PROVIDER_ERROR_CODE.DOCUMENT_RESTORE_ERROR;
    message: string;
    recoverable: boolean;
    /**
     * @deprecated switch to using either the error code or the recoverable flag
     */
    status?: number;
};
/**
 * The initial document couldn't be loaded from the collab service.
 * This error is given to us by NCS.
 * It could indicate either a network issue, or an internal service error in NCS.
 * @message Message returned to editor, i.e. The initial document couldn't be loaded from the collab service
 * @recoverable It is not recoverable, as the provider cannot do anything to fix it.
 * The user will need to refresh the page to try again.
 */
type InitialisationError = {
    code: PROVIDER_ERROR_CODE.INITIALISATION_ERROR;
    message: string;
    recoverable: boolean;
    /**
     * @deprecated switch to using either the error code or the recoverable flag
     */
    status?: number;
};
/**
 * Couldn't reconnect to the collab service (NCS) due to network issues.
 * NCS could be down, or the user could be offline. It's also possible the url is incorrect, or the user is behind a proxy blocking the connection.
 * Fired upon a reconnection attempt error (from Socket.IO Manager)
 * @message Message returned to editor, i.e. Couldn't reconnect to the collab service due to network issues
 * @recoverable It is recoverable, as the provider will try to reconnect.
 */
type NetworkIssue = {
    code: PROVIDER_ERROR_CODE.NETWORK_ISSUE;
    message: string;
    recoverable: boolean;
    /**
     * @deprecated switch to using either the error code or the recoverable flag
     */
    status?: number;
};
/**
 * This error is thrown when the provider has an invalid configuration.
 * It could happen due to these errors from NCS:
 *  NAMESPACE_INVALID
    INVALID_ACTIVATION_ID
    INVALID_DOCUMENT_ARI
    INVALID_CLOUD_ID
 * @message Message returned to editor, i.e. Invalid provider configuration
 * @recoverable It is not recoverable, as the provider cannot do anything to fix it.
 * The service using the provider will need to fix the configuration.
 */
type InvalidProviderConfiguration = {
    code: PROVIDER_ERROR_CODE.INVALID_PROVIDER_CONFIGURATION;
    message: string;
    reason: string;
    recoverable: boolean;
    /**
     * @deprecated switch to using either the error code or the recoverable flag
     */
    status?: number;
};
/**
 * This error is thrown when the provider encounters an internal service error, not otherwise accounted for.
 * @message Message returned to editor, i.e. Collab Provider experienced an unrecoverable error
 * @recoverable It is not recoverable, as the provider cannot do anything to fix it.
 */
type InternalServiceError = {
    code: PROVIDER_ERROR_CODE.INTERNAL_SERVICE_ERROR;
    message: string;
    reason: string;
    recoverable: boolean;
    /**
     * @deprecated switch to using either the error code or the recoverable flag
     */
    status?: number;
};
type ProviderDocumentUpdateError = {
    code: PROVIDER_ERROR_CODE.DOCUMENT_UPDATE_ERROR;
    message: 'The provider failed to apply changes to the editor';
    recoverable: boolean;
    /**
     * @deprecated switch to using either the error code or the recoverable flag
     */
    status?: number;
};
/**
 * A union of all possible provider errors that can be emitted back to the editor.
 */
export type ProviderError = InsufficientEditingPermission | InvalidUserToken | DocumentNotFound | Locked | FailToSave | DocumentNotRestore | InitialisationError | NetworkIssue | InvalidProviderConfiguration | InternalServiceError | ProviderDocumentUpdateError;
export interface Metadata {
    [key: string]: string | number | boolean;
}
export type CollabMetadataPayload = Metadata;
export interface CollabEventInitData {
    doc?: any;
    json?: any;
    reserveCursor?: boolean;
    sid?: string;
    version?: number;
}
export interface CollabInitPayload extends CollabEventInitData {
    caller?: string;
    doc: any;
    metadata?: Metadata;
    reserveCursor?: boolean;
    targetClientId?: string;
    version: number;
}
export interface CollabEventConnectionData {
    initial: boolean;
    sid: string;
}
export type CollabConnectedPayload = CollabEventConnectionData;
export declare enum DisconnectReason {
    CLIENT_DISCONNECT = "CLIENT_DISCONNECT",
    SERVER_DISCONNECT = "SERVER_DISCONNECT",
    SOCKET_CLOSED = "SOCKET_CLOSED",
    SOCKET_ERROR = "SOCKET_ERROR",
    SOCKET_TIMEOUT = "SOCKET_TIMEOUT",
    UNKNOWN_DISCONNECT = "UNKNOWN_DISCONNECT"
}
export interface CollabDisconnectedPayload {
    reason: DisconnectReason;
    sid: string;
}
export interface CollabNamespaceLockCheckPayload {
    isLocked: boolean;
}
export interface CollabEventRemoteData {
    json?: any;
    newState?: EditorState;
    userIds?: (number | string)[];
}
type MarkJson = {
    attrs: {
        [key: string]: any;
    };
    type: string;
};
export type NodeJson = {
    attrs: {
        [key: string]: any;
    };
    content: NodeJson[];
    marks: MarkJson[];
    text?: string;
    type: string;
};
type SliceJson = {
    content: NodeJson[];
    openEnd: number;
    openStart: number;
};
export interface StepMetadata {
    metadata?: {
        createdOffline?: boolean;
        prevStepId?: string;
        rebased?: boolean;
        reqId?: string;
        schemaVersion?: string;
        source?: string;
        stepId?: string;
        traceId?: string;
        unconfirmedStepAfterRecovery?: boolean;
    };
}
export interface BaseStepPM extends StepMetadata {
    clientId: number | string;
    from?: number;
    slice?: SliceJson;
    stepType: string;
    to?: number;
    userId: string;
}
export interface ReplaceStepPM extends BaseStepPM {
    from: number;
    slice: SliceJson;
    structure?: boolean;
    to: number;
}
export interface ReplaceAroundStepPM extends BaseStepPM {
    from: number;
    gapFrom: number;
    gapTo: number;
    insert: number;
    slice: SliceJson;
    structure?: boolean;
    to: number;
}
export type InlineCommentStepPM = InlineCommentAddMarkStepPM | InlineCommentAddNodeMarkStepPM;
interface InlineCommentAddMarkStepPM extends BaseStepPM {
    from: number;
    mark?: {
        attrs?: {
            annotationType?: 'inlineComment';
            id?: string;
        };
        type?: 'annotation';
    };
    stepType: 'addMark';
    to: number;
}
export interface InlineCommentAddNodeMarkStepPM extends BaseStepPM {
    mark?: {
        attrs?: {
            annotationType?: 'inlineComment';
            id?: string;
        };
        type?: 'annotation';
    };
    pos: number;
    stepType: 'addNodeMark';
}
export interface SetAttrsStepPM extends BaseStepPM {
    attrs: Record<string, unknown>;
    pos: number;
    stepType: 'setAttrs';
}
export type BatchAttrsStepPM = BaseStepPM & BatchAttrsStep;
export type OverrideDocumentStepPM = BaseStepPM & OverrideDocumentStep;
export type StepJson = OverrideDocumentStepPM | ReplaceAroundStepPM | ReplaceStepPM | InlineCommentStepPM | SetAttrsStepPM;
export interface CollabDataPayload extends CollabEventRemoteData {
    json: StepJson[];
    userIds: (number | string)[];
    version: number;
}
export interface CollabSendableSelection {
    anchor?: number | string;
    head?: number | string;
    type: 'textSelection' | 'nodeSelection';
}
export type PresenceActivity = 'viewer' | 'editor';
export type CollabActivityAIProviderChangedPayload = {
    action: 'add' | 'remove';
    providerId?: string;
    type: 'ai-provider:change';
};
export type CollabPresenceActivityChangePayload = {
    activity?: PresenceActivity;
    type: 'participant:activity';
};
export interface CollabEventTelepointerData {
    selection: CollabSendableSelection;
    sessionId: string;
    type: 'telepointer';
}
export type CollabTelepointerPayload = CollabEventTelepointerData;
type ProviderParticipantPermitLevel = {
    isPermittedToComment?: boolean;
    isPermittedToEdit?: boolean;
    isPermittedToView?: boolean;
};
export interface CollabParticipant {
    avatar: string;
    cursorPos?: number;
    isGuest?: boolean;
    isHydrated?: boolean;
    lastActive: number;
    name: string;
    permit?: ProviderParticipantPermitLevel;
    presenceActivity?: PresenceActivity;
    presenceId?: string;
    sessionId: string;
}
export type ProviderParticipant = CollabParticipant & {
    clientId: number | string;
    email: string;
    userId: string;
};
export interface CollabEventPresenceData {
    joined?: ProviderParticipant[];
    left?: {
        sessionId: string;
    }[];
}
export type CollabPresencePayload = CollabEventPresenceData;
export type CollabLocalStepsPayload = {
    steps: readonly Step[];
};
export interface CollabEventConnectingData {
    initial: boolean;
}
export type CollabConnectingPayload = CollabEventConnectingData;
export type CollabCommitStatusEventPayload = {
    status: 'attempt' | 'success' | 'failure';
    version: number;
};
export type UserPermitType = {
    isPermittedToComment: boolean;
    isPermittedToEdit: boolean;
    isPermittedToView: boolean;
};
export type CollabPermissionEventPayload = UserPermitType;
export type ConflictChange = {
    from: number;
    local: Slice;
    remote: Slice;
    to: number;
};
export type ConflictChanges = {
    deleted: ConflictChange[];
    inserted: ConflictChange[];
};
export interface CollabEventConflictPayload extends ConflictChanges {
    offlineDoc: PMNode;
}
export interface CollabEvents {
    'commit-status': CollabCommitStatusEventPayload;
    connected: CollabConnectedPayload;
    connecting: CollabConnectingPayload;
    data: CollabDataPayload;
    'data:conflict': CollabEventConflictPayload;
    disconnected: CollabDisconnectedPayload;
    entity: any;
    error: ProviderError;
    init: CollabInitPayload;
    'local-steps': CollabLocalStepsPayload;
    'metadata:changed': Metadata;
    'namespace-lock:check': CollabNamespaceLockCheckPayload;
    permission: CollabPermissionEventPayload;
    presence: CollabPresencePayload;
    'presence:changed': CollabPresenceActivityChangePayload;
    telepointer: CollabTelepointerPayload;
}
export type SyncUpErrorFunction = (attributes: NewCollabSyncUpErrorAttributes) => void;
export interface CollabEditProvider<Events extends CollabEvents = CollabEvents> {
    getFinalAcknowledgedState: (reason: GetResolvedEditorStateReason) => Promise<ResolvedEditorState>;
    /**
     * Returns the cached `init` payload if the provider has already initialised the
     * document with NCS, otherwise `undefined`.
     *
     * Used by the collab plugin to seed a freshly-attached plugin view (e.g. after
     * an editor preset reconfigure or a full EditorView recreation) with the same
     * `init` data the original subscribers received. Without this, late subscribers
     * never receive `init` (it is fired once at session start) and the editor
     * gets stuck in the `!isReady` state, silently dropping doc-changing
     * transactions via `filterTransaction`.
     *
     * Optional for backwards compatibility with custom provider implementations
     * (e.g. test mocks). When undefined, the rebind path is skipped.
     */
    getInitPayload?: () => CollabEventInitData | undefined;
    getIsNamespaceLocked: () => boolean;
    initialize: (getState: () => any, createStep: (json: object) => Step) => this;
    off: (evt: keyof Events, handler: (...args: any) => void) => this;
    on: (evt: keyof Events, handler: (...args: any) => void) => this;
    send: (tr: Transaction, oldState: EditorState, newState: EditorState) => void;
    sendMessage: <K extends keyof Events>(data: {
        type: K;
    } & Events[K]) => void;
    setup: (props: {
        editorApi?: any;
        getState?: () => EditorState;
        onSyncUpError?: SyncUpErrorFunction;
    }) => this;
    unsubscribeAll: (evt: keyof Events) => this;
}
export type CollabEditOptions = {
    provider?: Providers['collabEditProvider'];
    useNativePlugin?: boolean;
    userId?: string;
} & CollabInviteToEditProps & CollabAnalyticsProps;
export type InviteToEditButtonProps = {
    onClick: (event: React.MouseEvent<HTMLElement>) => void;
    selected: boolean;
};
export type InviteToEditComponentProps = {
    children: ReactElement<InviteToEditButtonProps>;
};
export interface CollabInviteToEditProps {
    inviteToEditComponent?: React.ComponentType<React.PropsWithChildren<InviteToEditComponentProps>>;
    inviteToEditHandler?: (event: React.MouseEvent<HTMLElement>) => void;
    isInviteToEditButtonSelected?: boolean;
}
export interface CollabAnalyticsProps {
    /**
     * @description Control whether Synchrony entity error events are tracked
     */
    EXPERIMENTAL_allowInternalErrorAnalytics?: boolean;
}
export interface CollabEventLocalStepData {
    steps: Array<Step>;
}
export type Color = ReturnType<typeof token>;
export declare const TELEPOINTER_DIM_CLASS = "telepointer-dim";
export declare const TELEPOINTER_PULSE_CLASS = "telepointer-pulse-animate";
export declare const TELEPOINTER_PULSE_DURING_TR_CLASS = "telepointer-pulse-during-tr";
export declare const TELEPOINTER_PULSE_DURING_TR_DURATION_MS = 7500;
export declare const TELEPOINTER_DATA_SESSION_ID_ATTR = "data-telepointer-sessionid";
export declare const telepointerStyle: SerializedStyles;
export declare const isDirtyTransaction: (tr: Transaction | ReadonlyTransaction) => boolean;
export declare const tintDirtyTransaction: (tr: Transaction) => void;
export {};
