import { type IEventsManager } from "../../common/events/IEventsManager";
import { type IClientInternalEvents } from "../../common/events/types";
import { type IClientToServerEvents, type IServerToClientEvents } from "../../../../shared/net/common/events/types";
/**
 * Реализация `IEventsManager` поверх нативного CCMP клиента.
 *
 * Важные особенности CCMP, продиктовавшие дизайн:
 *
 * 1. У `ccmp.on(name, cb)` **нет** парного `ccmp.off`. Поэтому unsubscribe
 *    реализован через собственный реестр: на каждое имя регистрируется ровно
 *    один диспетчер в `ccmp`, который проходит по нашему `Set` подписчиков.
 *    `off` лишь удаляет колбэк из `Set`, диспетчер на стороне CCMP остаётся
 *    висеть (становится no-op).
 *
 * 2. `ccmp.emitServer(event, data)` принимает **одно** значение `data`. Наш
 *    контракт `emitServer(name, ...args)` — variadic. Чтобы не терять
 *    позиционные аргументы, всегда отправляем `args` массивом, а на приёме
 *    разворачиваем обратно. Это совпадает с тем, как сервер уже шлёт клиенту
 *    (`ccmpPlayer.emit(name, args)` в `CCMPEventsManager` на сервере).
 *
 * 3. Локальной in-process шины событий (аналог `mp.events.call`) у CCMP нет —
 *    под `emitInternal` подкладываем `CCMPInProcessEmitter`. Однако `onInternal`
 *    дополнительно подписывает handler ещё и на нативный `ccmp.on(name, ...)`,
 *    потому что геймод использует `events.onInternal` как канал для UI-ingress
 *    (см. `rock-mod-event-emitter.adapter.ts:61-66` в геймоде: `registerUI()`
 *    делегирует в `events.onInternal`). Под RageMP такого дубля не нужно,
 *    потому что `mp.events.add` естественно ловит и `mp.events.call`, и
 *    CEF-выпуски `mp.trigger`. Побочный эффект: server/system события с тем
 *    же именем тоже долетят до internal-handler'а — на практике конфликтов
 *    нет, потому что namespace'ы геймода различаются (`rm::*` server,
 *    `api:*` UI, `player:*`/`vehicle:*`/etc. internal).
 *
 * 4. `IClientEvents` (для `onRaw`/`offRaw`) — RageMP-specific глобальный
 *    тип. Под CCMP осмысленно регистрировать `ccmp.on('playerConnected', ...)`
 *    и другие билтины, но строго типизировать их через `IClientEvents` нельзя
 *    — используем `@ts-expect-error` по аналогии с серверным `CCMPEventsManager`.
 */
export declare class CCMPEventsManager implements IEventsManager {
    /** Реестр всех серверных/raw/generic подписчиков. */
    private readonly _externalListeners;
    /** Имена, для которых уже зарегистрирован диспетчер в нативном `ccmp`. */
    private readonly _dispatched;
    /** Локальная in-process шина — питает `onInternal`/`emitInternal`. */
    private readonly _internalEmitter;
    onRaw(events: Partial<IClientEvents>): void;
    offRaw<K extends keyof IClientEvents>(eventName: K, listener?: IClientEvents[K]): void;
    onInternal(events: Partial<IClientInternalEvents>): void;
    offInternal<K extends keyof IClientInternalEvents>(eventName: K, listener?: IClientInternalEvents[K]): void;
    emitInternal<K extends keyof IClientInternalEvents>(eventName: K, ...args: Parameters<IClientInternalEvents[K]>): void;
    /**
     * Sticky-вариант `emitInternal`. Кэширует последнее значение, чтобы поздние
     * подписчики (`onInternal`) получили его сразу при подписке. Использовать
     * для one-shot lifecycle-событий (`rm::playerReady` и т.п.), где гонка между
     * "событие случилось" и "подписчик зарегистрирован" критична.
     *
     * См. `CCMPInProcessEmitter.emitSticky` для подробностей семантики.
     */
    emitInternalSticky<K extends keyof IClientInternalEvents>(eventName: K, ...args: Parameters<IClientInternalEvents[K]>): void;
    /**
     * Очищает sticky-кэш для конкретного internal-события. Использовать на
     * disconnect/reset чтобы новые подписчики не получали устаревший local-
     * player-stub после реконнекта.
     */
    clearInternalSticky<K extends keyof IClientInternalEvents>(eventName: K): void;
    onServer(events: Partial<IServerToClientEvents>): void;
    offServer<K extends keyof IServerToClientEvents>(eventName: K, listener?: IServerToClientEvents[K]): void;
    emitServer<K extends keyof IClientToServerEvents>(eventName: K, ...args: Parameters<IClientToServerEvents[K]>): void;
    register(event: string, listener: (...args: unknown[]) => void): void;
    unregister(event: string): void;
    private _registerExternal;
    private _unregisterExternal;
}
