import React from 'react';
import { ShowModalWindowParams, UpdateModalWindowParams, ShowNotificationParams } from '@open-condo/bridge';
import { z } from 'zod';

type FrameId = string;
type FrameType = HTMLIFrameElement;
type WorkerType = ServiceWorker;
type EventType = string;
type EventName = string;
type EventParams = Record<string, unknown>;
type SourceMetadata = Record<string, unknown>;
type EventTypeStorage = Pick<Map<string, unknown>, 'set' | 'get' | 'has' | 'delete'>;
type ValidationResult<T> = {
    success: true;
    data: T;
    error?: never;
} | {
    success: false;
    data?: never;
    error: string;
};
type FrameSource = {
    ref: FrameType;
    id: FrameId;
    type: 'frame';
    metadata?: SourceMetadata;
};
type WindowSource = {
    ref: Window;
    id: 'parent';
    type: 'window';
};
type WorkerSource = {
    ref: WorkerType;
    id: 'worker';
    type: 'worker';
};
type MessageSource = FrameSource | WindowSource | WorkerSource;
type ParamsValidator<Params extends EventParams> = (params: unknown) => ValidationResult<Params>;
type HandlerResult = Record<string, unknown>;
type HandlerArgs<Params extends EventParams> = {
    source: MessageSource;
    storage: {
        events: EventTypeStorage;
    };
    params: Params;
    eventName: EventName;
    eventType: EventType;
};
type Handler<Params extends EventParams, Result extends HandlerResult> = (args: HandlerArgs<Params>) => Result | Promise<Result>;
type HandlerScope = MessageSource['id'] | '*';
type AddHandlerType = <Params extends EventParams, Result extends HandlerResult>(eventType: EventType, eventName: EventName, handlerScope: HandlerScope, validator: ParamsValidator<Params>, handler: Handler<Params, Result>) => void;
type MiddlewareNextFn<Params extends EventParams, Result extends HandlerResult> = (args?: Partial<Pick<HandlerArgs<Params>, 'params'>>) => Result | Promise<Result>;
type MiddlewareArgs<Params extends EventParams, Result extends HandlerResult> = HandlerArgs<Params> & {
    next: MiddlewareNextFn<Params, Result>;
};
type MiddlewareFn<Params extends EventParams, Result extends HandlerResult> = (args: MiddlewareArgs<Params, Result>) => Result | Promise<Result>;
type MiddlewareId = string;
type RegisteredMiddleware<Params extends EventParams, Result extends HandlerResult> = {
    id: MiddlewareId;
    eventType?: EventType;
    eventName?: EventName;
    scope: HandlerScope;
    order?: number;
    fn: MiddlewareFn<Params, Result>;
};
type Middleware<Params extends EventParams, Result extends HandlerResult> = Omit<RegisteredMiddleware<Params, Result>, 'id'>;
type ControllerState = {
    isBridgeReady: boolean;
};

type SimpleRouter = {
    push(url: string): unknown;
};
type NotificationsApi = (params: ShowNotificationParams) => void;
type ExtraShowModalParams = {
    onCancel?: () => void;
    metadata?: SourceMetadata;
};
type ModalsApi = (params: ShowModalWindowParams & ExtraShowModalParams) => {
    update(params: UpdateModalWindowParams['data']): void;
    destroy(): void;
};
type RegisterBridgeEventsOptions = {
    addHandler: AddHandlerType;
    router?: SimpleRouter;
    notificationsApi?: NotificationsApi;
    modalsApi?: ModalsApi;
};

declare class PostMessageController extends EventTarget {
    #private;
    state: ControllerState;
    constructor();
    private updateState;
    private getWrappedHandler;
    private getMessageSource;
    addFrame(frame: FrameType, metadata?: SourceMetadata): FrameId;
    removeFrame(frameId: FrameId): void;
    addHandler<Params extends EventParams, Result extends HandlerResult>(eventType: EventType, eventName: EventName, handlerScope: HandlerScope, validator: ParamsValidator<Params>, handler: Handler<Params, Result>): void;
    addMiddleware<Params extends EventParams, Result extends HandlerResult>(mw: Middleware<Params, Result>): MiddlewareId;
    removeMiddleware(id: MiddlewareId): void;
    eventListener(event: MessageEvent): Promise<void>;
    registerBridgeEvents(options: Omit<RegisterBridgeEventsOptions, 'addHandler'>): void;
}

type PostMessageContextType = Pick<PostMessageController, 'addFrame' | 'removeFrame' | 'addHandler' | 'addMiddleware' | 'removeMiddleware'> & ControllerState;
type PostMessageProviderProps = Partial<Omit<RegisterBridgeEventsOptions, 'addHandler'>>;
declare const PostMessageProvider: React.FC<React.PropsWithChildren<PostMessageProviderProps>>;
declare function usePostMessageContext(): PostMessageContextType;

type TypeChecker<T extends EventParams> = (params: unknown) => params is T;
declare function typeCheckerToValidator<T extends EventParams>(typeChecker: TypeChecker<T>): ParamsValidator<T>;
declare function zodSchemaToValidator<T extends EventParams>(schema: z.ZodSchema<T>): ParamsValidator<T>;

export { type Middleware, type ModalsApi, type NotificationsApi, PostMessageController, PostMessageProvider, typeCheckerToValidator, usePostMessageContext, zodSchemaToValidator };
