import { EventEmitter } from 'events';
import { RaftEngine, RaftEngineConfig } from './raft/RaftEngine';
import { HamokMessage } from './messages/HamokMessage';
import { LogEntry } from './raft/LogEntry';
import { RaftStateName } from './raft/RaftState';
import { HamokMap } from './collections/HamokMap';
import { HamokConnectionConfig } from './collections/HamokConnection';
import { HamokCodec } from './common/HamokCodec';
import { BaseMap } from './collections/BaseMap';
import { HamokGrid } from './HamokGrid';
import { HamokQueue } from './collections/HamokQueue';
import { HamokEmitter, HamokEmitterEventMap } from './collections/HamokEmitter';
import { RaftLogs } from './raft/RaftLogs';
import { HamokRecord, HamokRecordObject } from './collections/HamokRecord';
import { RemoteMap } from './collections/RemoteMap';
import { HamokRemoteMap } from './collections/HamokRemoteMap';
export type HamokJoinProcessParams = {
    /**
     * Timeout in milliseconds for fetching the remote peers.
     *
     * DEFAULT: 5000
     */
    fetchRemotePeerTimeoutInMs?: number;
    /**
     * The maximum number of retries for fetching the remote peers.
     * -1 - means infinite retries
     * 0 - means no retries
     *
     * DEFAULT: 3
     */
    maxRetry?: number;
};
export type HamokObjectConfig<AppData extends Record<string, unknown> = Record<string, unknown>> = {
    /**
     * Indicate if the Hamok should stop automatically when there are no remote peers.
     */
    /**
     * The timeout in milliseconds for waiting for the remote storage state.
     *
     * DEFAULT: 1000
     */
    remoteStorageStateWaitingTimeoutInMs: number;
    /**
     * A custom appData object to be used by the application utilizes Hamok.
     */
    appData?: AppData;
};
/**
 * Configuration settings for the Hamok constructor, extending RaftEngineConfig and HamokConfig.
 */
export type HamokConfig<AppData extends Record<string, unknown> = Record<string, unknown>> = RaftEngineConfig & Partial<HamokObjectConfig<AppData>> & {
    /**
     * Optional. The expiration time in milliseconds for log entries.
     * Log entries older than this duration may be purged.
     * Only applicable when a custom RaftLogs is NOT provided.
     *
     * DEFAULT: 300000 (5 minutes)
     */
    logEntriesExpirationTimeInMs?: number;
    /**
     * Optional. A map of initial log entries to be used by the system.
     * The key is the log index, and the value is the LogEntry.
     */
    initialLogEntries?: Map<number, LogEntry>;
    /**
     * The period in milliseconds to send notifications to the source(s) about ongoing requests
     * to prevent timeouts. This is applicable when a requestId is explicitly added to the ongoing
     * requests set by calling addOngoingRequestId(). Notifications stop when removeOngoingRequestId
     * is called. It is crucial to call this explicitly in any case as comlink does not handle
     * automatically stopping notifications for explicitly postponed requests.
     */
    ongoingRequestsSendingPeriodInMs: number;
    /**
     * Optional. A custom implementation of RaftLogs to store log entries.
     */
    raftLogs?: RaftLogs;
};
export type HamokConnectionBuilderBaseConfig = Pick<HamokConnectionConfig, 'requestTimeoutInMs' | 'remoteStorageStateWaitingTimeoutInMs'> & {
    maxOutboundMessageKeys: number;
    maxOutboundMessageValues: number;
};
/**
 * Configuration settings for building a Hamok record.
 */
export type HamokRecordBuilderConfig<T extends HamokRecordObject> = Partial<HamokConnectionBuilderBaseConfig> & {
    /**
     * The unique identifier for the record.
     */
    recordId: string;
    /**
     * Optional. A map of payload codecs for encoding and decoding record properties.
     * The key is a property of the record, and the value is a codec for that property.
     */
    payloadCodecs?: Map<keyof T, HamokCodec<T[keyof T], string>>;
    /**
     * Optional. An initial object to be used as the base state of the record.
     */
    initialObject?: Partial<T>;
    /**
     * Optional. A function to determine equality between two values.
     * Used for custom equality checking.
     */
    equalValues?: (a: T[keyof T], b: T[keyof T]) => boolean;
};
/**
 * Configuration settings for building a Hamok map.
 */
export type HamokMapBuilderConfig<K, V> = Partial<HamokConnectionBuilderBaseConfig> & {
    /**
     * The unique identifier for the map.
     */
    mapId: string;
    /**
     * Optional. A codec for encoding and decoding keys in the map.
     */
    keyCodec?: HamokCodec<K, Uint8Array>;
    /**
     * Optional. A codec for encoding and decoding values in the map.
     */
    valueCodec?: HamokCodec<V, Uint8Array>;
    /**
     * Optional. A base map to be used as the initial state of the map.
     */
    baseMap?: BaseMap<K, V>;
    /**
     * Optional. A function to determine equality between two values.
     * Used for custom equality checking.
     */
    equalValues?: (a: V, b: V) => boolean;
};
/**
 * Configuration settings for building a Hamok remote map.
 */
export type HamokRemoteMapBuilderConfig<K, V> = Omit<HamokMapBuilderConfig<K, V>, 'baseMap'> & {
    /**
     * The remote map to be used to store the data.
     */
    remoteMap: RemoteMap<K, V>;
    /**
     * Flag indicate if the events should be emitted by the event emitter or not.
     * It also reduces the communication overhead if not needed, as for emitting events
     * the leader should send a message to all followers to emit an event.
     * In such case when it's not necessary (like cache maintenance) it can be disabled.
     */
    noEvents?: boolean;
};
/**
 * Configuration settings for building a Hamok queue.
 */
export type HamokQueueBuilderConfig<T> = Partial<HamokConnectionBuilderBaseConfig> & {
    /**
     * The unique identifier for the queue.
     */
    queueId: string;
    /**
     * Optional. A codec for encoding and decoding items in the queue.
     */
    codec?: HamokCodec<T, Uint8Array>;
    /**
     * Optional. A base map to be used as the initial state of the queue.
     */
    baseMap?: BaseMap<number, T>;
};
/**
 * Configuration settings for building a Hamok emitter.
 */
export type HamokEmitterBuilderConfig<T extends HamokEmitterEventMap> = Partial<HamokConnectionBuilderBaseConfig> & {
    /**
     * The unique identifier for the emitter.
     */
    emitterId: string;
    /**
     * Optional. A map of payload codecs for encoding and decoding event payloads.
     * The key is an event type, and the value is a codec for that event type.
     */
    payloadsCodec?: Map<keyof T, {
        encode: (...args: unknown[]) => string;
        decode: (data: string) => unknown[];
    }>;
    /**
     * Optional.Indicate if the emitter automatically cleans up and unssubscribes from events
     * remote peers gone offline. Only leader endpoint does this.
     */
    autoClean?: boolean;
};
export type HamokFetchRemotePeersResponse = {
    remotePeers: string[];
    minNumberOfLogs?: number;
    smallestCommitIndex?: number;
};
export type HamokEventMap = {
    follower: [];
    candidate: [];
    leader: [];
    message: [message: HamokMessage];
    'remote-peer-joined': [peerId: string];
    'remote-peer-left': [peerId: string];
    'leader-changed': [leaderId: string | undefined, prevLeader: string | undefined];
    'state-changed': [newState: RaftStateName, prevState: RaftStateName];
    commit: [commitIndex: number, message: HamokMessage];
    heartbeat: [];
    error: [error: Error];
    'no-heartbeat-from': [remotePeerId: string];
    'unsynced-peer': [remotePeerId: string];
    joined: [];
    rejoining: [];
    left: [];
    close: [];
};
export type HamokStorageType = 'record' | 'map' | 'remoteMap' | 'emitter' | 'queue';
export type HamokSharedStorageMap = HamokMap<string, {
    type: HamokStorageType;
    count: number;
}>;
export declare interface Hamok {
    on<U extends keyof HamokEventMap>(event: U, listener: (...args: HamokEventMap[U]) => void): this;
    once<U extends keyof HamokEventMap>(event: U, listener: (...args: HamokEventMap[U]) => void): this;
    emit<U extends keyof HamokEventMap>(event: U, ...args: HamokEventMap[U]): boolean;
}
export declare class Hamok<AppData extends Record<string, unknown> = Record<string, unknown>> extends EventEmitter {
    readonly config: HamokObjectConfig<AppData>;
    readonly raft: RaftEngine;
    readonly storages: Map<string, HamokRecord<any> | HamokMap<any, any> | HamokQueue<any> | HamokRemoteMap<any, any> | HamokEmitter<any, Record<string, unknown>>>;
    private _closed;
    private _run;
    private _raftTimer?;
    private readonly _remoteHeartbeats;
    private readonly _codec;
    readonly grid: HamokGrid;
    private _joining?;
    constructor(providedConfig?: Partial<HamokConfig<AppData>>);
    get appData(): AppData;
    get localPeerId(): string;
    get remotePeerIds(): ReadonlySet<string>;
    get leader(): boolean;
    get ready(): Promise<this>;
    get state(): RaftStateName;
    get run(): boolean;
    get activeRemoteHeartbeats(): IterableIterator<string>;
    get closed(): boolean;
    close(): void;
    get stats(): {
        /**
         * Number of requests sent out from the grid, but waiting for response from remote peer
         */
        numberOfPendingRequests: number;
        /**
         * Number of requests received by this peer and queued for processing (for example requests to be waited to be committed by the leader)
         */
        numberOfOngoingRequests: number;
        /**
         * Number of responses received by this peer and queued for processing as the response were chunked
         */
        numberOfPendingResponses: number;
        /**
         * Number of remote peers this peer is connected to
         */
        numberOfRemotePeers: number;
        /**
         * Number of bytes used by the raft logs in memory
         */
        raftLogsBytesInMemory: number;
    };
    private _acceptCommit;
    addRemotePeerId(remoteEndpointId: string): void;
    removeRemotePeerId(remotePeerId: string): void;
    private _acceptLeaderChanged;
    /**
     * Wait until the commit head (the most recent spread commit by the leader) is reached
     * @returns
     */
    waitUntilCommitHead(): Promise<void>;
    waitUntilLeader(timeoutInMs?: number): Promise<void>;
    createMap<K, V>(options: HamokMapBuilderConfig<K, V>): HamokMap<K, V>;
    getOrCreateMap<K, V>(options: HamokMapBuilderConfig<K, V>, callback?: (alreadyExisted: boolean) => void): HamokMap<K, V>;
    createRemoteMap<K, V>(options: HamokRemoteMapBuilderConfig<K, V>): HamokRemoteMap<K, V>;
    getOrCreateRemoteMap(options: HamokRemoteMapBuilderConfig<unknown, unknown>, callback?: (alreadyExisted: boolean) => void): HamokRemoteMap<unknown, unknown>;
    createRecord<T extends HamokRecordObject>(options: HamokRecordBuilderConfig<T>): HamokRecord<T>;
    getOrCreateRecord<T extends HamokRecordObject>(options: HamokRecordBuilderConfig<T>, callback?: (alreadyExisted: boolean) => void): HamokRecord<T>;
    createQueue<T>(options: HamokQueueBuilderConfig<T>): HamokQueue<T>;
    getOrCreateQueue<T>(options: HamokQueueBuilderConfig<T>, callback?: (alreadyExisted: boolean) => void): HamokQueue<T>;
    createEmitter<T extends HamokEmitterEventMap, M extends Record<string, unknown> = Record<string, unknown>>(options: HamokEmitterBuilderConfig<T>): HamokEmitter<T, M>;
    getOrCreateEmitter<T extends HamokEmitterEventMap>(options: HamokEmitterBuilderConfig<T>, callback?: (alreadyExisted: boolean) => void): HamokEmitter<T>;
    submit(entry: HamokMessage): Promise<void>;
    accept(message: HamokMessage, commitIndex?: number): void;
    leave(): Promise<void>;
    join(params?: HamokJoinProcessParams): Promise<void>;
    private _join;
    private _startRaftEngine;
    private _stopRaftEngine;
    private _sendEndpointNotification;
    private _acceptGridMessage;
    broadcastEndpointNotification(): void;
    private _emitMessage;
    private _createStorageConnection;
    private _acceptKeepAliveHamokMessage;
    private _checkRemoteHeartbeats;
    private _sendJoinMsg;
}
//# sourceMappingURL=Hamok.d.ts.map