import { InboxMessage } from '@trycourier/courier-js';
import { CourierInboxFeed, InboxDataSet } from '../types/inbox-data-set';
import { CourierInboxDataStoreListener } from './datastore-listener';
/**
 * Shared datastore for Inbox components.
 *
 * CourierInboxDatastore is a singleton. Use `CourierInboxDatastore.shared`
 * to access the shared instance.
 *
 * @public
 */
export declare class CourierInboxDatastore {
    private static readonly TAG;
    private static readonly OPEN_BATCH_DELAY_MS;
    private static readonly OPEN_BATCH_MAX_SIZE;
    private static instance;
    private _datasets;
    private _listeners;
    private _removeMessageEventListener?;
    private _pendingOpenMessageIds;
    private _openBatchTimer;
    /**
     * Global message store is a map of Message ID to Message for all messages
     * that have been loaded.
     *
     * This acts as the source of truth to apply messages mutations to a message
     * given its ID and propagate those mutations to individual datasets.
     */
    private _globalMessages;
    /** Access CourierInboxDatastore through {@link CourierInboxDatastore.shared} */
    private constructor();
    /**
     * Instantiate the datastore with the feeds specified.
     *
     * Feeds are added to the datastore as datasets. Each feed has a respective
     * dataset. Existing datasets will be cleared before the feeds specified are added.
     *
     * @param feeds - The feeds with which to instantiate the datastore
     */
    registerFeeds(feeds: CourierInboxFeed[]): void;
    private createDatasetsFromFilters;
    /**
     * Add a message to the datastore.
     *
     * The message will be added to any datasets for which it qualifies.
     *
     * @param message - The message to add
     */
    addMessage(message: InboxMessage): void;
    private updateDatasetsWithMessageChange;
    /**
     * Listen for real-time message updates from the Courier backend.
     *
     * If an existing WebSocket connection is open, it will be re-used. If not,
     * a new connection will be opened.
     */
    listenForUpdates(): Promise<void>;
    /**
     * Load unread counts for multiple tabs in a single GraphQL query.
     * This populates tab badges without loading messages.
     * @param tabIds - Array of tab IDs to load counts for
     */
    loadUnreadCountsForTabs(tabIds: string[]): Promise<void>;
    /**
     * Add a datastore listener, whose callbacks will be called in response to various message events.
     * @param listener - The listener instance to add
     */
    addDataStoreListener(listener: CourierInboxDataStoreListener): void;
    /**
     * Remove a datastore listener.
     * @param listener - The listener instance to remove
     */
    removeDataStoreListener(listener: CourierInboxDataStoreListener): void;
    /**
     * Mark a message as read.
     * @param message - The message to mark as read
     */
    readMessage({ message }: {
        message: InboxMessage;
    }): Promise<void>;
    /**
     * Mark a message as unread.
     * @param message - The message to mark as unread
     */
    unreadMessage({ message }: {
        message: InboxMessage;
    }): Promise<void>;
    /**
     * Mark a message as opened.
     *
     * The local state is updated optimistically and the server call is
     * batched: multiple opens arriving within a short window
     * are collected and flushed as a single GraphQL request.
     *
     * @param message - The message to mark as opened
     */
    openMessage({ message }: {
        message: InboxMessage;
    }): void;
    private scheduleBatchOpen;
    private flushBatchOpen;
    /**
     * Unarchive a message.
     * @param message - The message to unarchive
     */
    unarchiveMessage({ message }: {
        message: InboxMessage;
    }): Promise<void>;
    /**
     * Archive a message.
     * @param message - The message to archive
     */
    archiveMessage({ message }: {
        message: InboxMessage;
    }): Promise<void>;
    /**
     * Track a click event for a message.
     * @param message - The message that was clicked
     */
    clickMessage({ message }: {
        message: InboxMessage;
    }): Promise<void>;
    /**
     * Archive all messages for the specified dataset.
     */
    archiveAllMessages(): Promise<void>;
    /**
     * Mark all messages read across all datasets.
     */
    readAllMessages(): Promise<void>;
    /**
     * Archive all read messages for the specified dataset.
     */
    archiveReadMessages(): Promise<void>;
    /**
     * Load datasets from the backend.
     *
     * Props:
     *  - canUseCache: If true and the dataset has already been loaded once, this will return the dataset from memory.
     *  - datasetIds: Optional: The set of dataset IDs to load. If unset, all known datasets will be loaded.
     *
     * @param props - Options to load datasets, see method documentation
     */
    load(props?: {
        canUseCache: boolean;
        datasetIds?: string[];
    }): Promise<void>;
    private loadDatasets;
    /**
     * Sync messages from a dataset to the global message store.
     * This is called after datasets load messages to ensure the global store has all messages.
     */
    private syncDatasetMessagesToGlobalStore;
    /**
     * Fetch the next page of messages for the specified feed or datasetId.
     *
     * feedType is deprecated and will be removed in the next major release.
     * Please migrate to pass the same identifier as datasetId.
     * While both options are present, exactly one is required.
     *
     * @param props - Options to fetch the next page of messages, see method documetation
     */
    fetchNextPageOfMessages(props: {
        feedType?: string;
        datasetId?: string;
    }): Promise<InboxDataSet | null>;
    /**
     * Get the {@link InboxDataSet} representation of the dataset ID specified.
     * @param datasetId - The dataset ID to get
     */
    getDatasetById(datasetId: string): InboxDataSet | undefined;
    /**
     * Get datasets currently in the datastore.
     * @returns A record mapping dataset IDs to their InboxDataSet representations
     */
    getDatasets(): Record<string, InboxDataSet>;
    /**
     * Get the total unread count across all datasets.
     */
    get totalUnreadCount(): number;
    private fetchNextPageForDataset;
    private handleMessageEvent;
    /**
     * Update all messages across all datasets from an InboxMessageEvent.
     * This only handles InboxMessageEvents that do not specify a messageId
     * and mutate all messages.
     *
     * Related: {@link CourierInboxDatastore.updateMessage}
     */
    private updateAllMessages;
    /**
     * Update a single message across all datasets from an InboxMessageEvent.
     * This only handles InboxMessageEvents that specify a messageId.
     *
     * Related: {@link CourierInboxDatastore.updateAllMessages}
     */
    private updateMessage;
    private clearDatasets;
    private static getISONow;
    /**
     * Create a snapshot of all datasets and global messages for rollback purposes.
     * This captures the current state of all messages and metadata.
     */
    private createDatastoreSnapshot;
    /**
     * Restore all datasets and global messages from a snapshot, reverting any mutations.
     * This is used for rollback when API calls or updates to downstream datasets fail.
     */
    private restoreDatastoreSnapshot;
    /**
     * Execute an operation with automatic rollback on failure.
     * Snapshots all datasets before the operation and restores them if the operation throws.
     *
     * Note: Errors are caught and logged, but not re-thrown to match the behavior
     * for backwards compatibility with the legacy (inbox/archive) datastore implementation.
     *
     * Note: This method exists at the datastore level (rather than dataset) to handle
     * errors from API calls.
     */
    private executeWithRollback;
    /**
     * Get the shared instance of CourierInboxDatastore.
     *
     * CourierInboxDatastore is a singleton. Instance methods should be accessed
     * through this `shared` static accessor.
     */
    static get shared(): CourierInboxDatastore;
}
