import { Awaitable, MaybeFn, WithChildren } from '@rhao/types-base';
import { ToTreeArrayOptions } from 'nice-fns';
import { AppSDKInternalInstance, Plugin, PluginID } from '../..';
import { RouteComponent, RouteLocationNormalizedLoaded, RouteMeta, RouteRecordNormalized, RouteRecordRaw } from 'vue-router';
import { PageMetadata, PageMetadataWithChildren, RoleList } from './interface';
import { MaybeRefOrGetter } from 'vue';
export interface PageOptions {
    /**
     * 是否为移动端应用，设为 `true` 时在调用 `handleMenuClick` 时将禁用动画插件（若存在）的导航动画并使用 `router.replace` 跳转
     */
    isMobile?: MaybeRefOrGetter<boolean>;
    /**
     * 跳转外链时若存在已打开的外链窗口是否重复使用进行跳转
     * @default false
     */
    linkSingleWindow?: boolean;
    /**
     * 调用 `handleMenuClick` 时是否允许跳转外链，返回假值时走正常页面跳转
     * @default (menu) => menu.link
     */
    allowLink?: (menu: PageMetadata) => boolean;
    /**
     * 根据 `page.file` 获取真实组件
     * @example
     * ```ts
     * const page = createPage({ resolveComponent: (file) => () => import(`src/${file}.vue`) })
     *
     * const route = page.pageToRoute({ file: 'home/index' })
     * route.component // () => import('src/home/index.vue')
     */
    resolveComponent: (file: string, page: PageMetadata) => MaybeFn<Awaitable<RouteComponent>, []>;
    /**
     * 校准不符合 `PageMetadata` 的元数据
     * @param data 不符合的元数据
     * @returns 符合的元数据
     *
     * @example
     * ```ts
     * // ❌ 不符合 PageMetadata 的元数据
     * { id: 1, routeName: 'home', routePath: '/home', sort: 0, ... }
     *
     * // 校准后 ↓
     *
     * // ✔️ 符合 PageMetadata 的元数据
     * { id: 1, name: 'home', path: '/home', index: 0, ... }
     * ```
     */
    calibrateMetadata?: (data: any) => PageMetadata;
}
/**
 * Page Plugin ID
 */
export declare const PAGE_ID: PluginID<Page>;
/**
 * 应用页面管理插件
 */
export declare class Page implements Plugin {
    /**
     * 配置项
     */
    options: PageOptions;
    constructor(
    /**
     * 配置项
     */
    options: PageOptions);
    id: PluginID<Page>;
    /**
     * AppSDK 实例
     */
    private _sdk;
    /**
     * 移除路由函数列表
     */
    private _removeRouteFns;
    /**
     * 已打开的窗口实例
     */
    private openedWindow;
    /**
     * 校准页面元数据
     * @readonly
     */
    get calibrateMetadata(): (data: any) => PageMetadata;
    /**
     * 是否允许跳转外链
     * @readonly
     */
    get allowLink(): (menu: PageMetadata) => boolean;
    /**
     * 重置路由列表为初始创建路由器时传入的列表
     */
    resetRoutes: () => void;
    /**
     * 获取路由上的页面元数据（浅拷贝）
     * @param data `route` 或 `route.meta`
     */
    getPageMetadata: (data: Pick<RouteRecordNormalized, "meta"> | RouteMeta) => Partial<PageMetadata>;
    /**
     * 将树形元数据列表扁平化为符合 `PageMetadata` 的页面元数据列表
     * @param data 树形元数据列表
     * @param options 配置项
     * @returns 扁平化的页面元数据列表
     */
    toFlattenPages: <T extends {}, Calibrate extends boolean = false>(data: T[], options?: Pick<ToTreeArrayOptions, "childrenKey"> & {
        /**
         * 是否克隆源数据，避免转换时影响到源数据
         * @default false
         */
        clone?: boolean;
        /**
         * 是否校准元数据，数据格式不符合 `PageMetadata` 时可以设为 `true`
         * @default false
         */
        calibrate?: Calibrate;
        /**
         * 是否补全路径，设为 `true` 后会对 `path` 进行拼接补全，可以在 `addRoute()` 时不受父子级限制
         * @default false
         */
        completePath?: boolean;
    }) => Calibrate extends true ? PageMetadata[] : T[];
    /**
     * 将元数据列表转为符合 `PageMetaWithChildren` 的树形页面元数据列表
     * @param data 元数据列表
     * @param options 配置项
     * @param options.strict 严格模式，开启后将移除父子关联不存在的数据
     * @param options.clone 是否克隆源数据，避免转换时影响到源数据
     * @param options.calibrate 是否校准元数据，数据格式不符合 `PageMetadata` 时可以设为 `true`
     * @param options.completePath 是否补全路径，设为 `true` 后会对 `path` 进行拼接补全，可以在 `addRoute()` 时不受父子级限制
     * @returns 树形页面元数据列表
     */
    toTreePages: <T extends {}, Calibrate extends boolean = false>(data: T[], options?: {
        /**
         * 严格模式，开启后将移除父子关联不存在的数据
         */
        strict?: boolean;
        /**
         * 是否克隆源数据，避免转换时影响到源数据
         * @default false
         */
        clone?: boolean;
        /**
         * 是否校准元数据，数据格式不符合 `PageMetadata` 时可以设为 `true`
         * @default false
         */
        calibrate?: Calibrate;
        /**
         * 是否补全路径，设为 `true` 后会对 `path` 进行拼接补全，可以在 `addRoute()` 时不受父子级限制
         * @default false
         */
        completePath?: boolean;
    }) => Calibrate extends true ? PageMetadataWithChildren[] : WithChildren<T, "children", false>[];
    /**
     * 父子关联页面元数据列表转为树形菜单列表，返回深克隆数据，与源数据不共用内存引用
     * @param pages 页面元数据列表
     * @param strict 严格模式
     * @returns 树形菜单元数据列表
     */
    toMenus: (pages: PageMetadata[], strict: boolean) => WithChildren<PageMetadata, "children", false>[];
    /**
     * 指定角色列表是否可以访问页面
     * @param page 页面元数据
     * @param roleList 角色列表
     * @param strict 严格模式
     * @returns 是否可以访问页面
     */
    canVisitPage: (page: PageMetadata, roleList: RoleList, strict: boolean) => boolean;
    /**
     * 过滤指定角色可以访问的页面元数据列表
     * @param pages 页面元数据列表
     * @param roleList 角色列表
     * @param strict 严格模式
     * @returns 可以访问的页面元数据列表
     */
    filterVisitPages: (pages: PageMetadata[], roleList: RoleList, strict: boolean) => PageMetadata[];
    /**
     * 创建不同场景下的页面元数据状态
     * @param pages 页面元数据列表
     * @param options 配置项
     */
    createStates: <T extends {}, ActiveMenu = string>(pages: MaybeRefOrGetter<T[]>, options: Pick<ToTreeArrayOptions, "childrenKey"> & {
        /**
         * `pages` 格式
         */
        format: MaybeRefOrGetter<"list" | "tree">;
        /**
         * 严格模式，开启后扁平化列表转为树形列表时将移除父子关联不存在的数据
         */
        strict?: MaybeRefOrGetter<boolean>;
        /**
         * 角色列表，用于过滤页面
         * @default []
         */
        roleList?: MaybeRefOrGetter<RoleList>;
        /**
         * 严格访问模式，开启时若指定角色列表或页面角色列表为空时则不能访问页面
         * @default true
         */
        strictVisit?: MaybeRefOrGetter<boolean>;
        /**
         * 角色过滤页面时是否子级优先
         * - `true`: 子级存在权限时父级必定存在
         * - `false`: 父级无权限时子级必定不存在
         * @default true
         */
        childrenFirst?: MaybeRefOrGetter<boolean>;
        /**
         * 是否补全路径，设为 `true` 后会对 `path` 进行拼接补全，可以在 `addRoute()` 时不受父子级限制
         * @default true
         */
        completePath?: MaybeRefOrGetter<boolean>;
        /**
         * 根据当前路由获取激活菜单标识
         * @default
         * ```ts
         * (route) => this.getPageMetadata(route).activeMenu || this.getPageMetadata(route).name || ''
         * ```
         */
        resolveActiveMenu?: (route: RouteLocationNormalizedLoaded, states: {
            flattenPages: PageMetadata[];
            treePages: PageMetadataWithChildren[];
            visitablePages: PageMetadata[];
            visitableTreePages: PageMetadataWithChildren[];
            visitableMenus: PageMetadataWithChildren[];
            visitablePageMap: Record<PageMetadata["id"], PageMetadata>;
            visitableTreeLinkMap: Record<PageMetadata["id"], PageMetadataWithChildren[]>;
        }) => ActiveMenu;
    }) => {
        /**
         * 扁平化的页面元数据列表
         */
        flattenPages: import('vue').ShallowRef<PageMetadata[]>;
        /**
         * 树形页面元数据列表
         */
        treePages: import('vue').ShallowRef<PageMetadataWithChildren[]>;
        /**
         * 可访问的树形页面元数据列表
         */
        visitableTreePages: import('vue').ShallowRef<PageMetadataWithChildren[]>;
        /**
         * 可访问的页面元数据列表
         */
        visitablePages: import('vue').ShallowRef<PageMetadata[]>;
        /**
         * 可访问的页面元数据映射
         */
        visitablePageMap: import('vue').ShallowRef<Record<string | number, PageMetadata>>;
        /**
         * 可访问的树形页面元数据链路映射
         */
        visitableTreeLinkMap: import('vue').ShallowRef<Record<string | number, PageMetadataWithChildren[]>>;
        /**
         * 可访问的菜单页面元数据列表
         */
        visitableMenus: import('vue').ShallowRef<PageMetadataWithChildren[]>;
        /**
         * 激活的菜单页面标识
         */
        activeMenu: import('vue').ComputedRef<ActiveMenu>;
    };
    /**
     * 页面元数据转为路由配置
     * @param page 页面元数据
     * @param extraProps 路由额外参数
     * @param syncName 同步组件 `name` 为路由 `name`，可以更好的配合 `KeepAlive` 组件缓存
     * @returns 路由配置
     */
    pageToRoute: (page: PageMetadata, extraProps?: Omit<RouteRecordRaw, "path" | "name" | "redirect" | "component">, syncName?: boolean | ((name: string, page: PageMetadata) => string)) => RouteRecordRaw;
    /**
     * 获取页面元数据设置的外链地址
     * @param page 页面元数据
     * @param selfLink 获取自身的外链地址（等同于 `page.link=true`）
     * @returns 外链地址
     *
     * @example
     * ```ts
     * resolveLink({ path: '/test', name: 'test', link: true })
     * // => '/test'
     *
     * resolveLink({ path: '/test', name: 'test', link: '//www.test.com' })
     * // => '//www.test.com'
     *
     * resolveLink({ path: '/test', name: 'test' })
     * // => ''
     *
     * resolveLink({ path: '/test/:id', name: 'test', routeParams: { id: 1 } }, true)
     * // => '/test/1'
     * ```
     */
    resolveLink: (page: PageMetadata, selfLink?: boolean) => string;
    /**
     * 处理菜单点击，设置 `link` 时将会在客户端新标签页打开指定路由页或网站，
     * 在 `options.isMobile` 设为 `true` 时将禁用动画插件（若存在）的导航动画并使用 `router.replace` 跳转
     * @param menu 页面元数据
     * @param singleWindow 跳转外链时若存在已打开的外链窗口是否重复使用进行跳转
     */
    handleMenuClick: (menu: PageMetadata, singleWindow?: boolean | undefined) => void;
    install(sdk: AppSDKInternalInstance): () => void;
}
declare module 'vue-router' {
    interface RouteMeta {
        /**
         * 页面元数据
         */
        _metadata?: PageMetadata;
    }
}
