/**
 * 小程序工具库。
 *
 * @packageDocumentation
 */

/// <reference types="wechat-miniprogram" />

import { default as React_2 } from 'react';

declare let $mp: ReturnType<typeof inMiniProgram> | undefined;

/**
 * 任意对象。
 *
 * @public
 */
declare type AnyObject_2 = Record<any, any>;

declare const brands: readonly ["微信", "QQ", "支付宝", "京东", "百度", "字节跳动", "钉钉"];

declare type CreateSubmitResult<T = string> = (<TResult>(action: (payload: SubmitActionPayload<T>) => Promise<TResult>) => Promise<TResult>) & Pick<SubmitActionPayload<T>, 'fail' | 'success'>;

/** @private */
export declare const currentPageListeners: (keyof MiniProgramBusListeners)[];

/**
 * 去除类型 T 中的 undefined。
 *
 * @public
 * @example
 * ```typescript
 * type X = string | undefined
 * type Y = Defined<X> // => string
 * ```
 */
declare type Defined<T> = Exclude<T, undefined>;

/**
 * 确保当前在小程序环境并执行回调。
 *
 * @param cb 要执行的回调，第一个参数为小程序 API 挂载的全局变量
 * @returns 返回回调的执行结果
 */
export declare function ensureInMiniProgram<T>(cb: (mp: Exclude<typeof $mp, false | undefined>) => T): T;

/**
 * 事件巴士，管理事件的发布与订阅。
 *
 * @template TListeners 事件名称及其对应的回调描述
 * @example
 * ```typescript
 * const bus = new EventBus<{
 *   success: (payload: { message: string }) => any
 * }>()
 * bus.on('success', ({ message }) => console.log(message))
 * bus.emit('success', { message: '提交成功' })
 * // => 控制台输出: 提交成功
 * ```
 */
declare class EventBus<TListeners extends EventBusListeners> {
    private options?;
    /**
     * 构造函数。
     */
    constructor(options?: EventBusOptions<TListeners> | undefined);
    /**
     * 回调列表。
     */
    private callbacks;
    /**
     * 订阅多个事件。
     *
     * @param eventNames 事件名称
     * @param callback 事件触发回调
     * @returns 返回取消订阅的函数
     */
    on<TListenerName extends keyof TListeners>(eventNames: TListenerName[], callback: (firstPayload: {
        [K in TListenerName]: Parameters<TListeners[K]>[0];
    }, payload: {
        [K in TListenerName]: Parameters<TListeners[K]>;
    }) => any): EventBusOffListener;
    /**
     * 订阅单个事件。
     *
     * @param eventName 事件名称
     * @param callback 事件触发回调
     * @returns 返回取消订阅的函数
     */
    on<TListenerName extends keyof TListeners>(eventName: TListenerName, callback: TListeners[TListenerName]): EventBusOffListener;
    /**
     * 订阅事件，但只订阅一次即取消订阅。
     *
     * @param eventName 事件名称
     * @param callback 事件触发回调
     * @returns 返回取消订阅的函数
     */
    once<TListenerName extends keyof TListeners>(eventName: TListenerName, callback: TListeners[TListenerName]): EventBusOffListener;
    /**
     * 取消订阅事件，若没有指定回调，则取消所有回调。
     *
     * @param eventName 事件名称
     * @param callback 事件触发回调
     */
    off<TListenerName extends keyof TListeners>(eventName: TListenerName, callbackOrTag?: TListeners[TListenerName] | string | number): void;
    /**
     * 发布事件。
     *
     * @param eventNameAndContext 事件名称和上下文
     * @param args 传给事件回调的参数
     * @returns 返回各事件回调的返回结果组成的数组
     */
    emit<TListenerName extends keyof TListeners>(eventName: TListenerName | EventBusListenerDescriptor<TListenerName>, ...args: Parameters<TListeners[TListenerName]>): Array<ReturnType<TListeners[TListenerName]>>;
    /**
     * 局部执行。
     *
     * @param fn 执行函数
     * @returns 可以返回一个或多个取消订阅的函数
     */
    run(fn: (bus: this) => void | EventBusOffListener | EventBusOffListener[]): EventBusOffListener;
    /**
     * 清空事件订阅。
     */
    clear(): void;
    /**
     * 销毁。
     */
    destroy(): void;
}

declare type EventBusBeforeEmit<TListeners extends EventBusListeners> = {
    [TListenerName in keyof TListeners]?: (this: EventBus<TListeners>, context: any) => any;
};

declare type EventBusBeforeOn<TListeners extends EventBusListeners> = {
    [TListenerName in keyof TListeners]?: (this: EventBus<TListeners>, callback: EventBusListener<TListeners[TListenerName]>) => TListeners[TListenerName];
};

declare type EventBusListener<TCallback extends (...args: any[]) => any = (...args: any[]) => any> = TCallback & {
    __EVENT_BUS_TAG__?: EventBusListenerTag;
};

declare interface EventBusListenerDescriptor<TListenerName extends keyof EventBusListeners> {
    name: TListenerName;
    context?: any;
    tag?: EventBusListenerTag;
    filter?: (callback: EventBusListener, index: number, callbacks: EventBusListener[]) => boolean;
}

declare type EventBusListeners = Record<string, EventBusListener>;

declare type EventBusListenerTag = string | number;

declare type EventBusOffListener = () => any;

declare interface EventBusOptions<TListeners extends EventBusListeners> {
    beforeOn?: EventBusBeforeOn<TListeners>;
    beforeEmit?: EventBusBeforeEmit<TListeners>;
}

/**
 * 获取当前页面的路径（不含查询参数），始终以 `/` 开头。
 *
 * @param pageInstance 页面实例，默认当前页面
 * @returns 返回当前页面的路径
 */
export declare function getCurrentPagePath(pageInstance?: WechatMiniprogram.Page.Instance<AnyObject_2, AnyObject_2>): string;

/**
 * 获取当前页面的查询参数，已经对每个值执行了 decodeURIComponent。
 *
 * @param pageInstance 页面实例，默认当前页面
 * @returns 返回当前页面的查询参数
 */
export declare function getCurrentPageQuery<T extends Record<string, string | undefined>>(pageInstance?: WechatMiniprogram.Page.Instance<AnyObject_2, AnyObject_2>): T;

/**
 * 获取当前页面的地址（包含查询参数）。
 *
 * @param pageInstance 页面实例，默认当前页面
 * @returns 返回当前页面的地址
 */
export declare function getCurrentPageUrl(pageInstance?: WechatMiniprogram.Page.Instance<AnyObject_2, AnyObject_2>): string;

export declare function getMiniProgramConfig(): Readonly<MiniProgramConfig>;

/**
 * 获取场景参数。
 *
 * @param parser 解析器
 */
export declare function getSceneParams<T extends Record<any, any> = Record<any, any>>(parser?: GetSceneParamsParser<T>): T;

export declare type GetSceneParamsParser<T> = 'searchParams' | 'json' | ((data: string) => T);

/**
 * 获取顶栏信息。
 *
 * @returns 返回获取到的顶栏信息
 */
export declare function getTopBarInfo(): GetTopBarInfoResult;

export declare interface GetTopBarInfoResult {
    /**
     * 状态栏高度。
     */
    statusBarHeight: number;
    /**
     * 菜单按钮宽度。
     */
    menuButtonWidth: number;
    /**
     * 菜单按钮高度。
     */
    menuButtonHeight: number;
    /**
     * 菜单按钮垂直外边距。
     */
    menuButtonVerticalMargin: number;
    /**
     * 菜单按钮水平外边距。
     *
     * **注意: QQ 小程序下该项为 0，请自行选取默认值**
     */
    menuButtonHorizontalMargin: number;
    /**
     * 导航栏高度。
     */
    navigationBarHeight: number;
    /**
     * 顶栏高度。
     */
    topBarHeight: number;
}

/**
 * 检查是否在指定品牌的小程序中，若在，返回承载其 API 的全局对象，若不在，返回 false。
 *
 * @param brand 指定的小程序品牌，若未指定，则表示所有小程序品牌
 * @returns 返回检查结果
 */
declare function inMiniProgram(brand?: MiniProgramBrand | MiniProgramBrand[]): MiniProgramApi | false;

declare type MiniProgramApi = WechatMiniprogram.Wx & {
    /** 小程序品牌 */
    readonly $brand: MiniProgramBrand;
};

declare type MiniProgramBrand = typeof brands[number];

export declare const miniProgramBus: EventBus<MiniProgramBusListeners>;

export declare interface MiniProgramBusListeners {
    appLaunch: Defined<WechatMiniprogram.App.Options<{}>['onLaunch']>;
    appShow: Defined<WechatMiniprogram.App.Options<{}>['onShow']>;
    appHide: Defined<WechatMiniprogram.App.Options<{}>['onHide']>;
    appError: Defined<WechatMiniprogram.App.Options<{}>['onError']>;
    appThemeChange: Defined<WechatMiniprogram.App.Options<{}>['onThemeChange']>;
    appUnhandledRejectionThrow: Defined<WechatMiniprogram.App.Options<{}>['onUnhandledRejection']>;
    pageNotFound: Defined<WechatMiniprogram.App.Options<{}>['onPageNotFound']>;
    pageLoad: Defined<WechatMiniprogram.Page.Options<{}, {}>['onLoad']>;
    pageShow: Defined<WechatMiniprogram.Page.Options<{}, {}>['onShow']>;
    pageHide: Defined<WechatMiniprogram.Page.Options<{}, {}>['onHide']>;
    pageReady: Defined<WechatMiniprogram.Page.Options<{}, {}>['onReady']>;
    pageUnload: Defined<WechatMiniprogram.Page.Options<{}, {}>['onUnload']>;
    pagePullDownRefresh: Defined<WechatMiniprogram.Page.Options<{}, {}>['onPullDownRefresh']>;
    pageReachBottom: Defined<WechatMiniprogram.Page.Options<{}, {}>['onReachBottom']>;
    pageShareAppMessage: Defined<WechatMiniprogram.Page.Options<{}, {}>['onShareAppMessage']>;
    pageShareTimeline: Defined<WechatMiniprogram.Page.Options<{}, {}>['onShareTimeline']>;
    pageAddToFavorites: Defined<WechatMiniprogram.Page.Options<{}, {}>['onAddToFavorites']>;
    pageResize: Defined<WechatMiniprogram.Page.Options<{}, {}>['onResize']>;
    pageTabItemTap: Defined<WechatMiniprogram.Page.Options<{}, {}>['onTabItemTap']>;
    currentPageShow: Defined<WechatMiniprogram.Page.Options<{}, {}>['onShow']>;
    currentPageHide: Defined<WechatMiniprogram.Page.Options<{}, {}>['onHide']>;
    currentPageReady: Defined<WechatMiniprogram.Page.Options<{}, {}>['onReady']>;
    currentPageUnload: Defined<WechatMiniprogram.Page.Options<{}, {}>['onUnload']>;
    currentPagePullDownRefresh: Defined<WechatMiniprogram.Page.Options<{}, {}>['onPullDownRefresh']>;
    currentPageReachBottom: Defined<WechatMiniprogram.Page.Options<{}, {}>['onReachBottom']>;
    currentPageShareAppMessage: Defined<WechatMiniprogram.Page.Options<{}, {}>['onShareAppMessage']>;
    currentPageShareTimeline: Defined<WechatMiniprogram.Page.Options<{}, {}>['onShareTimeline']>;
    currentPageAddToFavorites: Defined<WechatMiniprogram.Page.Options<{}, {}>['onAddToFavorites']>;
    currentPageResize: Defined<WechatMiniprogram.Page.Options<{}, {}>['onResize']>;
    currentPageTabItemTap: Defined<WechatMiniprogram.Page.Options<{}, {}>['onTabItemTap']>;
    routeChange: (payload: MiniProgramBusRouteChangePayload) => any;
}

export declare type MiniProgramBusRouteChangeAction = 'replace' | 'pop' | 'push';

export declare interface MiniProgramBusRouteChangePageInfo {
    url: string;
    path: string;
    query: AnyObject_2;
}

export declare interface MiniProgramBusRouteChangePayload {
    from: MiniProgramBusRouteChangePageInfo | undefined;
    to: MiniProgramBusRouteChangePageInfo;
    action: MiniProgramBusRouteChangeAction;
}

export declare interface MiniProgramConfig {
    webUrlToMiniProgramUrl?: (url: string) => string;
}

/**
 * 关闭当前页面，返回上一页面或多级页面。
 *
 * @param delta 返回的页面数，如果 delta 大于现有页面数，则返回到首页
 */
export declare function navigatePageBack(delta?: number): Promise<any>;

/**
 * 跳转至某个页面，跳转失败时会尝试切换到 Tab 页。
 *
 * **注意：在页面真正切换后 Promise 才会被 resolve，因而此时的页面上下文已经是新页面。**
 *
 * @param url 要跳转去的页面地址
 * @param query 查询参数
 * @param redirect 是否关闭当前页面后跳转
 */
export declare function navigatePageTo(url: string, query?: AnyObject_2, redirect?: boolean): Promise<any>;

/** @private */
export declare const pageListeners: (keyof MiniProgramBusListeners)[];

/** @private */
export declare const pageListenerToCurrentPageListener: Partial<Record<keyof MiniProgramBusListeners, keyof MiniProgramBusListeners>>;

/**
 * 打补丁。
 */
export declare function patchMiniProgram(): void;

export declare namespace patchMiniProgram {
    var __CURRENT_PAGE_ID__: number;
}

/**
 * 关闭当前页面，跳转至某个页面，跳转失败时会尝试切换到 Tab 页。
 *
 * @param url 要跳转去的页面地址
 * @param query 查询参数
 */
export declare function redirectPageTo(url: string, query?: AnyObject_2): Promise<any>;

export declare function setMiniProgramConfig(config: Partial<MiniProgramConfig>): Readonly<MiniProgramConfig>;

/**
 * 对提交类行为的封装。
 */
export declare const submit: CreateSubmitResult;

declare interface SubmitActionPayload<T = string> {
    /**
     * 开始提示。
     *
     * @param message 提示信息
     */
    start(message?: T): Promise<any>;
    /**
     * 失败提示。
     *
     * @param message 提示信息
     * @param duration 持续时间（毫秒），默认 1500
     */
    fail(message: T, duration?: number): Promise<any>;
    /**
     * 成功提示。
     *
     * @param message 提示信息
     * @param duration 持续时间（毫秒），默认 1500
     */
    success(message: T, duration?: number): Promise<any>;
}

export declare function usePullDownRefresh(callback: () => any): void;

/**
 * 获取场景参数。
 *
 * @param parser 解析器
 */
export declare function useSceneParams<T extends Record<any, any> = Record<any, any>>(parser?: GetSceneParamsParser<T>): T;

export declare function useShareAppMessage(callback: Defined<WechatMiniprogram.Page.Options<{}, {}>['onShareAppMessage']>): void;

/**
 * 对提交类行为的封装。
 */
export declare function useSubmit<TResult>(action: (payload: SubmitActionPayload) => Promise<TResult>, deps: React_2.DependencyList): () => Promise<TResult>;

/**
 * 获取顶栏信息。
 *
 * @returns 返回获取到的顶栏信息
 */
export declare function useTopBarInfo(): GetTopBarInfoResult;

export { }
