/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { TypedEventEmitter, type ILayerCompatDetails, type IProvideLayerCompatDetails } from "@fluid-internal/client-utils";
import { AttachState, type IAudience } from "@fluidframework/container-definitions";
import { type IDeltaManager } from "@fluidframework/container-definitions/internal";
import type { FluidObject, IDisposable, IEvent } from "@fluidframework/core-interfaces";
import type { IFluidHandleContext, IFluidHandleInternal, ITelemetryBaseLogger } from "@fluidframework/core-interfaces/internal";
import type { IClientDetails, IQuorumClients } from "@fluidframework/driver-definitions";
import type { ISnapshot, IDocumentMessage, ISnapshotTree, ITreeEntry, ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal";
import type { IIdCompressor } from "@fluidframework/id-compressor";
import type { FluidDataStoreMessage, ISummaryTreeWithStats, ITelemetryContext, IGarbageCollectionData, CreateChildSummarizerNodeFn, CreateChildSummarizerNodeParam, FluidDataStoreContextInternal, IContainerRuntimeBase, IDataStore, IFluidDataStoreChannel, IFluidDataStoreContextDetached, IFluidDataStoreRegistry, IGarbageCollectionDetailsBase, IProvideFluidDataStoreFactory, ISummarizeResult, ISummarizerNodeWithGC, SummarizeInternalFn, IInboundSignalMessage, IRuntimeMessageCollection, IFluidDataStoreFactory, PackagePath, IRuntimeStorageService, MinimumVersionForCollab, ContainerExtensionId, ContainerExtensionExpectations } from "@fluidframework/runtime-definitions/internal";
import { type MonitoringContext } from "@fluidframework/telemetry-utils/internal";
import type { IFluidParentContextPrivate } from "./channelCollection.js";
export declare function createAttributesBlob(pkg: readonly string[], isRootDataStore: boolean): ITreeEntry;
export interface ISnapshotDetails {
    pkg: readonly string[];
    isRootDataStore: boolean;
    snapshot?: ISnapshotTree;
    sequenceNumber?: number;
}
/**
 * This is interface that every context should implement.
 * This interface is used for context's parent - ChannelCollection.
 * It should not be exposed to any other users of context.
 */
export interface IFluidDataStoreContextPrivate extends FluidDataStoreContextInternal {
    getAttachSummary(telemetryContext?: ITelemetryContext): ISummaryTreeWithStats;
    getAttachGCData(telemetryContext?: ITelemetryContext): IGarbageCollectionData;
    getInitialSnapshotDetails(): Promise<ISnapshotDetails>;
    realize(): Promise<IFluidDataStoreChannel>;
    isRoot(): Promise<boolean>;
}
/**
 * Properties necessary for creating a FluidDataStoreContext
 */
export interface IFluidDataStoreContextProps {
    readonly id: string;
    readonly parentContext: IFluidParentContextPrivate;
    readonly storage: IRuntimeStorageService;
    readonly scope: FluidObject;
    readonly createSummarizerNodeFn: CreateChildSummarizerNodeFn;
    /**
     * See {@link FluidDataStoreContext.pkg}.
     */
    readonly pkg?: PackagePath;
    /**
     * See {@link FluidDataStoreContext.loadingGroupId}.
     */
    readonly loadingGroupId?: string;
}
/**
 * Properties necessary for creating a local FluidDataStoreContext
 */
export interface ILocalFluidDataStoreContextProps extends IFluidDataStoreContextProps {
    readonly pkg: readonly string[] | undefined;
    readonly snapshotTree: ISnapshotTree | undefined;
    readonly makeLocallyVisibleFn: () => void;
}
/**
 * Properties necessary for creating a local FluidDataStoreContext
 */
export interface ILocalDetachedFluidDataStoreContextProps extends ILocalFluidDataStoreContextProps {
    readonly channelToDataStoreFn: (channel: IFluidDataStoreChannel) => IDataStore;
}
/**
 * Properties necessary for creating a remote FluidDataStoreContext
 */
export interface IRemoteFluidDataStoreContextProps extends IFluidDataStoreContextProps {
    readonly snapshot: ISnapshotTree | ISnapshot | undefined;
}
export interface IFluidDataStoreContextEvents extends IEvent {
    (event: "attaching" | "attached", listener: () => void): any;
}
/**
 * {@link IFluidDataStoreContext} for the implementations of {@link IFluidDataStoreChannel} which powers the {@link IDataStore}s.
 */
export declare abstract class FluidDataStoreContext extends TypedEventEmitter<IFluidDataStoreContextEvents> implements IFluidDataStoreContextPrivate, IDisposable, IProvideLayerCompatDetails {
    private readonly existing;
    readonly isLocalDataStore: boolean;
    private readonly makeLocallyVisibleFn;
    get packagePath(): PackagePath;
    get options(): Record<string | number, unknown>;
    get clientId(): string | undefined;
    get clientDetails(): IClientDetails;
    get baseLogger(): ITelemetryBaseLogger;
    private readonly _contextDeltaManagerProxy;
    get deltaManager(): IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>;
    private isStagingMode;
    isReadOnly: () => boolean;
    get connected(): boolean;
    get IFluidHandleContext(): IFluidHandleContext;
    get containerRuntime(): IContainerRuntimeBase;
    get isLoaded(): boolean;
    get baseSnapshot(): ISnapshotTree | undefined;
    get idCompressor(): IIdCompressor | undefined;
    private _disposed;
    get disposed(): boolean;
    /**
     * A Tombstoned object has been unreferenced long enough that GC knows it won't be referenced again.
     * Tombstoned objects are eventually deleted by GC.
     */
    private _tombstoned;
    get tombstoned(): boolean;
    /**
     * If true, throw an error when a tombstone data store is used.
     * @deprecated NOT SUPPORTED - hardcoded to return false since it's deprecated.
     */
    readonly gcThrowOnTombstoneUsage: boolean;
    /**
     * @deprecated NOT SUPPORTED - hardcoded to return false since it's deprecated.
     */
    readonly gcTombstoneEnforcementAllowed: boolean;
    /**
     * If true, this means that this data store context and its children have been removed from the runtime
     */
    protected deleted: boolean;
    get attachState(): AttachState;
    get IFluidDataStoreRegistry(): IFluidDataStoreRegistry | undefined;
    /**
     * The compatibility details of the Runtime layer that is exposed to the DataStore layer
     * for validating DataStore-Runtime compatibility.
     */
    get ILayerCompatDetails(): ILayerCompatDetails;
    /**
     * {@inheritdoc IFluidDataStoreContext.minVersionForCollab}
     */
    readonly minVersionForCollab: MinimumVersionForCollab;
    private baseSnapshotSequenceNumber;
    /**
     * A datastore is considered as root if it
     * 1. is root in memory - see isInMemoryRoot
     * 2. is root as part of the base snapshot that the datastore loaded from
     * @returns whether a datastore is root
     */
    isRoot(aliasedDataStores?: Set<string>): Promise<boolean>;
    /**
     * There are 3 states where isInMemoryRoot needs to be true
     * 1. when a datastore becomes aliased. This can happen for both remote and local datastores
     * 2. when a datastore is created locally as root
     * 3. when a datastore is created locally as root and is rehydrated
     * @returns whether a datastore is root in memory
     */
    protected isInMemoryRoot(): boolean;
    /**
     * Returns the count of pending messages that are stored until the data store is realized.
     */
    get pendingCount(): number;
    protected registry: IFluidDataStoreRegistry | undefined;
    protected detachedRuntimeCreation: boolean;
    protected channel: IFluidDataStoreChannel | undefined;
    private loaded;
    /**
     * Tracks the messages for this data store that are sent while it's not loaded
     */
    private pendingMessagesState;
    protected channelP: Promise<IFluidDataStoreChannel> | undefined;
    protected _baseSnapshot: ISnapshotTree | undefined;
    protected _attachState: AttachState;
    private _isInMemoryRoot;
    protected readonly summarizerNode: ISummarizerNodeWithGC;
    protected readonly mc: MonitoringContext;
    private readonly thresholdOpsCounter;
    private static readonly pendingOpsCountThreshold;
    /**
     * If the summarizer makes local changes, a telemetry event is logged. This has the potential to be very noisy.
     * So, adding a count of how many telemetry events are logged per data store context. This can be
     * controlled via feature flags.
     */
    private localChangesTelemetryCount;
    readonly id: string;
    private readonly _containerRuntime;
    /**
     * Information for this data store from its parent.
     *
     * @remarks
     * The parent which provided this information currently can be the container runtime or a datastore (if the datastore this context is for is nested under another one).
     */
    private readonly parentContext;
    readonly storage: IRuntimeStorageService;
    readonly scope: FluidObject;
    /**
     * The loading group to which the data store belongs to.
     */
    readonly loadingGroupId: string | undefined;
    /**
     * {@link PackagePath} of this data store.
     *
     * This can be undefined when a data store is delay loaded, i.e., the attributes of this data store in the snapshot are not fetched until this data store is actually used.
     * At that time, the attributes blob is fetched and the pkg is updated from it.
     *
     * @see {@link PackagePath}.
     * @see {@link IFluidDataStoreContext.packagePath}.
     * @see {@link factoryFromPackagePath}.
     */
    protected pkg?: PackagePath;
    constructor(props: IFluidDataStoreContextProps, existing: boolean, isLocalDataStore: boolean, makeLocallyVisibleFn: () => void);
    dispose(): void;
    /**
     * When delete is called, that means that the data store is permanently removed from the runtime, and will not show up in future summaries
     * This function is called to prevent ops from being generated from this data store once it has been deleted. Furthermore, this data store
     * should not receive any ops/signals.
     */
    delete(): void;
    setTombstone(tombstone: boolean): void;
    abstract setAttachState(attachState: AttachState.Attaching | AttachState.Attached): void;
    /**
     * Throw a {@link LoggingError} indicating that {@link factoryFromPackagePath} failed.
     */
    private factoryFromPackagePathError;
    realize(): Promise<IFluidDataStoreChannel>;
    /**
     * Gets the factory that would be used to instantiate this data store by calling `instantiateDataStore` based on {@link pkg}.
     * @remarks
     * Also populates {@link registry}.
     *
     * Must be called after {@link pkg} is set, and only called once.
     *
     * @see {@link @fluidframework/container-runtime-definitions#IContainerRuntimeBase.createDataStore}.
     * @see {@link FluidDataStoreContext.pkg}.
     */
    protected factoryFromPackagePath(): Promise<IFluidDataStoreFactory>;
    createChildDataStore<T extends IFluidDataStoreFactory>(childFactory: T): ReturnType<Exclude<T["createDataStore"], undefined>>;
    private realizeCore;
    /**
     * Notifies this object about changes in the connection state.
     * @param value - New connection state.
     * @param clientId - ID of the client. Its old ID when in disconnected state and
     * its new client ID when we are connecting or connected.
     */
    setConnectionState(connected: boolean, clientId?: string): void;
    notifyReadOnlyState(): void;
    /**
     * Updates the readonly state of the data store based on the staging mode.
     *
     * @param staging - A boolean indicating whether the container is in staging mode.
     * If true, the data store is set to readonly unless explicitly allowed by its policies.
     */
    notifyStagingMode(staging: boolean): void;
    /**
     * Process messages for this data store. The messages here are contiguous messages for this data store in a batch.
     * @param messageCollection - The collection of messages to process.
     */
    processMessages(messageCollection: IRuntimeMessageCollection): void;
    processSignal(message: IInboundSignalMessage, local: boolean): void;
    getQuorum(): IQuorumClients;
    getAudience(): IAudience;
    /**
     * Returns a summary at the current sequence number.
     * @param fullTree - true to bypass optimizations and force a full summary tree
     * @param trackState - This tells whether we should track state from this summary.
     * @param telemetryContext - summary data passed through the layers for telemetry purposes
     */
    summarize(fullTree?: boolean, trackState?: boolean, telemetryContext?: ITelemetryContext): Promise<ISummarizeResult>;
    private summarizeInternal;
    /**
     * Returns the data used for garbage collection. This includes a list of GC nodes that represent this data store
     * including any of its child channel contexts. Each node has a set of outbound routes to other GC nodes in the
     * document.
     * If there is no new data in this data store since the last summary, previous GC data is used.
     * If there is new data, the GC data is generated again (by calling getGCDataInternal).
     * @param fullGC - true to bypass optimizations and force full generation of GC data.
     */
    getGCData(fullGC?: boolean): Promise<IGarbageCollectionData>;
    /**
     * Generates data used for garbage collection. This is called when there is new data since last summary. It
     * realizes the data store and calls into each channel context to get its GC data.
     * @param fullGC - true to bypass optimizations and force full generation of GC data.
     */
    private getGCDataInternal;
    /**
     * After GC has run, called to notify the data store of routes used in it. These are used for the following:
     * 1. To identify if this data store is being referenced in the document or not.
     * 2. To determine if it needs to re-summarize in case used routes changed since last summary.
     * 3. To notify child contexts of their used routes. This is done immediately if the data store is loaded.
     * Else, it is done by the data stores's summarizer node when child summarizer nodes are created.
     *
     * @param usedRoutes - The routes that are used in this data store.
     */
    updateUsedRoutes(usedRoutes: string[]): void;
    /**
     * Called when a new outbound reference is added to another node. This is used by garbage collection to identify
     * all references added in the system.
     *
     * @param fromPath - The absolute path of the node that added the reference.
     * @param toPath - The absolute path of the outbound node that is referenced.
     * @param messageTimestampMs - The timestamp of the message that added the reference.
     */
    addedGCOutboundRoute(fromPath: string, toPath: string, messageTimestampMs?: number): void;
    submitMessage(type: string, content: unknown, localOpMetadata: unknown): void;
    /**
     * This is called from a SharedSummaryBlock that does not generate ops but only wants to be part of the summary.
     * It indicates that there is data in the object that needs to be summarized.
     * We will update the latestSequenceNumber of the summary tracker of this
     * store and of the object's channel.
     *
     * @param address - The address of the channel that is dirty.
     *
     */
    setChannelDirty(address: string): void;
    submitSignal(type: string, content: unknown, targetClientId?: string): void;
    /**
     * This is called by the data store channel when it becomes locally visible indicating that it is ready to become
     * globally visible now.
     */
    makeLocallyVisible(): void;
    protected processPendingOps(channel: IFluidDataStoreChannel): void;
    protected completeBindingRuntime(channel: IFluidDataStoreChannel): void;
    protected bindRuntime(channel: IFluidDataStoreChannel, existing: boolean): Promise<void>;
    getAbsoluteUrl(relativeUrl: string): Promise<string | undefined>;
    /**
     * Get the summary required when attaching this context's DataStore.
     * Used for both Container Attach and DataStore Attach.
     */
    abstract getAttachSummary(telemetryContext?: ITelemetryContext): ISummaryTreeWithStats;
    /**
     * Get the GC Data for the initial state being attached so remote clients can learn of this DataStore's
     * outbound routes.
     */
    abstract getAttachGCData(telemetryContext?: ITelemetryContext): IGarbageCollectionData;
    abstract getInitialSnapshotDetails(): Promise<ISnapshotDetails>;
    /**
     * @deprecated Sets the datastore as root, for aliasing purposes: #7948
     * This method should not be used outside of the aliasing context.
     * It will be removed, as the source of truth for this flag will be the aliasing blob.
     */
    setInMemoryRoot(): void;
    /**
     * @deprecated The functionality to get base GC details has been moved to summarizer node.
     */
    getBaseGCDetails(): Promise<IGarbageCollectionDetailsBase>;
    reSubmit(message: FluidDataStoreMessage, localOpMetadata: unknown, squash: boolean): void;
    rollback(message: FluidDataStoreMessage, localOpMetadata: unknown): void;
    applyStashedOp(contents: unknown): Promise<unknown>;
    private verifyNotClosed;
    /**
     * Readonly client, including summarizer, should not have local changes. These changes can become part of the summary and can break
     * eventual consistency. For example, the next summary (say at ref seq# 100) may contain these changes whereas
     * other clients that are up-to-date till seq# 100 may not have them yet.
     */
    protected identifyLocalChangeIfReadonly(eventName: string, type?: string): void;
    getCreateChildSummarizerNodeFn(id: string, createParam: CreateChildSummarizerNodeParam): (summarizeInternal: SummarizeInternalFn, getGCDataFn: (fullGC?: boolean) => Promise<IGarbageCollectionData>) => ISummarizerNodeWithGC;
    deleteChildSummarizerNode(id: string): void;
    uploadBlob(blob: ArrayBufferLike, signal?: AbortSignal): Promise<IFluidHandleInternal<ArrayBufferLike>>;
    getExtension<TInterface, TUseContext extends unknown[] = []>(id: ContainerExtensionId, requirements: ContainerExtensionExpectations, ...context: TUseContext): TInterface;
}
/**
 * @internal
 */
export declare class RemoteFluidDataStoreContext extends FluidDataStoreContext {
    private snapshotFetchRequired;
    private readonly runtime;
    private readonly blobContents;
    private readonly isSnapshotInISnapshotFormat;
    constructor(props: IRemoteFluidDataStoreContextProps);
    /**
     * This API should not be called for RemoteFluidDataStoreContext. But here is one scenario where it's not the case:
     * The scenario (hit by stashedOps.spec.ts, "resends attach op" UT is the following (as far as I understand):
     *
     * 1. data store is being attached in attached container
     *
     * 2. container state is serialized (stashed ops feature)
     *
     * 3. new container instance is rehydrated (from stashed ops) -
     * As result, we create RemoteFluidDataStoreContext for this data store that is actually in "attaching" state  * (as of # 2).
     * But its state is set to attached when loading container from stashed ops.
     *
     * 4. attach op for this data store is processed - setAttachState() is called.
     */
    setAttachState(attachState: AttachState.Attaching | AttachState.Attached): void;
    private readonly initialSnapshotDetailsP;
    getInitialSnapshotDetails(): Promise<ISnapshotDetails>;
    /**
     * {@inheritDoc FluidDataStoreContext.getAttachSummary}
     */
    getAttachSummary(): ISummaryTreeWithStats;
    /**
     * {@inheritDoc FluidDataStoreContext.getAttachGCData}
     */
    getAttachGCData(telemetryContext?: ITelemetryContext): IGarbageCollectionData;
}
/**
 * Base class for detached & attached context classes
 * @internal
 */
export declare class LocalFluidDataStoreContextBase extends FluidDataStoreContext {
    private readonly snapshotTree;
    constructor(props: ILocalFluidDataStoreContextProps);
    setAttachState(attachState: AttachState.Attaching | AttachState.Attached): void;
    /**
     * {@inheritDoc FluidDataStoreContext.getAttachSummary}
     */
    getAttachSummary(telemetryContext?: ITelemetryContext): ISummaryTreeWithStats;
    /**
     * {@inheritDoc FluidDataStoreContext.getAttachGCData}
     */
    getAttachGCData(telemetryContext?: ITelemetryContext): IGarbageCollectionData;
    private readonly initialSnapshotDetailsP;
    getInitialSnapshotDetails(): Promise<ISnapshotDetails>;
    /**
     * A context should only be marked as deleted when its a remote context.
     * Session Expiry at the runtime level should have closed the container creating the local data store context
     * before delete is even possible. Session Expiry is at 30 days, and sweep is done 36+ days later from the time
     * it was unreferenced. Thus the sweeping container should have loaded from a snapshot and thus creating a remote
     * context.
     */
    delete(): void;
}
/**
 * context implementation for "attached" data store runtime.
 * Various workflows (snapshot creation, requests) result in .realize() being called
 * on context, resulting in instantiation and attachment of runtime.
 * Runtime is created using data store factory that is associated with this context.
 * @internal
 */
export declare class LocalFluidDataStoreContext extends LocalFluidDataStoreContextBase {
    constructor(props: ILocalFluidDataStoreContextProps);
}
/**
 * Detached context. Data Store runtime will be attached to it by attachRuntime() call
 * Before attachment happens, this context is not associated with particular type of runtime
 * or factory, i.e. it's package path is undefined.
 * Attachment process provides all missing parts - package path, data store runtime, and data store factory
 */
export declare class LocalDetachedFluidDataStoreContext extends LocalFluidDataStoreContextBase implements IFluidDataStoreContextDetached {
    constructor(props: ILocalDetachedFluidDataStoreContextProps);
    private readonly channelToDataStoreFn;
    attachRuntime(registry: IProvideFluidDataStoreFactory, dataStoreChannel: IFluidDataStoreChannel): Promise<IDataStore>;
    /**
     * This method provides a synchronous path for binding a runtime to the context.
     *
     * Due to its synchronous nature, it is unable to validate that the runtime
     * represents a datastore which is instantiable by remote clients. This could
     * happen if the runtime's package path does not return a factory when looked up
     * in the container runtime's registry, or if the runtime's entrypoint is not
     * properly initialized. As both of these validation's are asynchronous to preform.
     *
     * If used incorrectly, this function can result in permanent data corruption.
     */
    unsafe_AttachRuntimeSync(channel: IFluidDataStoreChannel): IDataStore;
    getInitialSnapshotDetails(): Promise<ISnapshotDetails>;
}
//# sourceMappingURL=dataStoreContext.d.ts.map