import { StorageOptions } from '../types';
import { NoopFn, SetRequired, Simplify } from '@rhao/types-base';
import { RouteLocationNormalized } from 'vue-router';
import { Plugin, PluginID } from './Plugin';
import { AppSDKInternalInstance } from './SDK';
/**
 * 路由导航方向
 */
export declare enum NavigationDirection {
    /**
     * 前进
     */
    forward = "forward",
    /**
     * 后退
     */
    backward = "backward",
    /**
     * 刷新
     */
    unchanged = "unchanged"
}
/**
 * 路由配置项
 */
export interface RouterOptions extends Omit<StorageOptions<true>, 'persistent'> {
    /**
     * 是否持久化详情记录，开启后会将 `detailsRecord` 存储在 `storage` 中，防止刷新丢失
     *
     * ***注意：持久化后会缓存每次导航的详情信息，默认只在导航后退时清理旧导航信息，也可手动执行 `router.clearDetails()` 清理全部缓存。***
     * @default true
     */
    persistentDetails?: boolean;
    /**
     * 自定义识别导航方向
     * @param to 目标路由
     * @param from 来源路由
     */
    identifyDirection?: (ctx: {
        to: RouteLocationNormalized;
        from: RouteLocationNormalized;
        latestPosition: number | null;
        currentPosition: number | null;
    }) => NavigationDirection;
}
/**
 * Router Plugin ID
 */
export declare const ROUTER_ID: PluginID<Router>;
/**
 * 路由详情
 */
export interface RouteDetails<T = unknown> {
    /**
     * 来源路由信息
     */
    from: Simplify<Readonly<Pick<RouteLocationNormalized, 'path' | 'name' | 'fullPath' | 'hash'>>> | undefined;
    /**
     * 详情数据
     */
    data: T | undefined;
}
/**
 * 路由详情记录
 */
export type RouteDetailsRecord = Record<string, RouteDetails>;
/**
 * 获取路由详情（只读）
 *
 * @example
 * ```ts
 * // a.vue
 * router.pushWithData('/b', { msg: 'from a' })
 *
 * // b.vue
 * import { useRouteDetails } from 'vue-app-sdk'
 *
 * const details = useRouteDetails()
 * details.data.msg // => 'from a'
 *
 * // 持续监听
 * watch(() => details.data, (data) => {
 *   console.log(data)
 * })
 * ```
 */
export declare function useRouteDetails<T = unknown>(): Readonly<import('vue').ShallowReactive<RouteDetails<T>>>;
export type WatchDetailsFromKey = RouteLocationNormalized['path'] | RouteLocationNormalized['fullPath'] | RouteLocationNormalized['name'];
export type WatchDetailsCallback<T = any> = (data: T | undefined, details: SetRequired<RouteDetails<T>, 'from'>) => void;
/**
 * 精确监听路由详情，必须在组件 setup() 作用域内使用，将会在组件卸载前自动取消监听，支持手动取消
 * @param fromKey 来源标识，支持路由的 `path`、`fullPath`、`name`
 * @param callback 监听回调
 * @returns 取消监听回调
 *
 * @example
 * ```ts
 * // a.vue
 * import { watchDetails } from 'vue-app-sdk'
 *
 * // 精确监听路由 `/b` 传递的消息
 * watchDetails('/b', (data) => {
 *   console.log(data.msg) // => 'from b'
 * })
 *
 * router.pushWithData('/b', { msg: 'from a' })
 *
 * // b.vue
 * import { useRouteDetails } from 'vue-app-sdk'
 *
 * const details = useRouteDetails()
 * details.data.msg // => 'from a'
 *
 * router.backWithData({ msg: 'from b' })
 * ```
 */
export declare function watchDetails<T = unknown>(fromKey: WatchDetailsFromKey, callback: WatchDetailsCallback<T>): () => void;
/**
 * 路由插件
 */
export declare class Router implements Plugin {
    /**
     * 配置项
     */
    options: RouterOptions;
    constructor(
    /**
     * 配置项
     */
    options?: RouterOptions);
    id: PluginID<Router>;
    /**
     * 最近记录的位置
     */
    latestPosition: number | null;
    /**
     * 识别导航方向
     * @readonly
     */
    get identifyDirection(): (ctx: {
        to: RouteLocationNormalized;
        from: RouteLocationNormalized;
        latestPosition: number | null;
        currentPosition: number | null;
    }) => NavigationDirection;
    /**
     * 路由详情记录
     */
    private _detailsRecord;
    /**
     * 是否正在导航
     */
    private _isNavigating;
    /**
     * 锁定 `beforeOnce`
     */
    private _onceLocked;
    /**
     * 详情数据
     */
    private _detailsData;
    /**
     * 设置详情数据
     * @param data 详情数据
     */
    private _setDetailsData;
    /**
     * 消费详情数据
     */
    private _consumeDetailsData;
    /**
     * 更新详情记录
     * @param value 详情记录
     */
    private _updateDetailsRecord;
    /**
     * 获取路由详情
     * @param fullPath 完整路径
     * @returns 路由详情
     */
    getDetails: (fullPath: string) => RouteDetails<unknown>;
    /**
     * 清理所有详情记录
     */
    clearDetailsRecord: () => void;
    /**
     * 创建路由详情
     * @param details 需要合并的路由详情
     * @param increment 需要自增路由详情变更次数
     */
    makeDetails: (details?: Partial<RouteDetails>, increment?: boolean) => RouteDetails;
    /**
     * 获取当前导航位置
     * @returns 当前导航位置
     */
    getCurrentPosition: () => number | null;
    install: (sdk: AppSDKInternalInstance) => () => void;
}
declare module 'vue-app-sdk' {
    interface AppSDKHooks {
        /**
         * 路由前进后触发
         */
        'sdk:router:forward'(to: RouteLocationNormalized, from: RouteLocationNormalized): void;
        /**
         * 路由后退后触发
         */
        'sdk:router:backward'(to: RouteLocationNormalized, from: RouteLocationNormalized): void;
        /**
         * 路由替换后触发
         */
        'sdk:router:replace'(to: RouteLocationNormalized, from: RouteLocationNormalized): void;
        /**
         * 路由导航成功后触发
         */
        'sdk:router:navigate'(direction: NavigationDirection, to: RouteLocationNormalized, from: RouteLocationNormalized): void;
        /**
         * 路由详情记录变更后触发
         */
        'sdk:router:detailsRecordChange'(record: RouteDetailsRecord): void;
    }
}
declare module 'vue-router' {
    interface Router {
        /**
         * 是否正在导航
         */
        readonly isNavigating: boolean;
        /**
         * 同 `router.beforeEach`，区别在于仅单次触发，直到 `afterEach` 被执行后可下次触发，常用于避免在 `beforeEach` 内重定向再次触发 `beforeEach` 钩子的回调处理
         */
        beforeOnce(guard: NavigationGuard): NoopFn;
        /**
         * 携带跨页面数据，类似于 `params`
         * @example
         * ```ts
         * // a.vue
         * router.pushWithData('/b', { msg: 'from a' })
         *
         * // b.vue
         * import { useRouteDetails } from 'vue-app-sdk'
         *
         * const details = useRouteDetails()
         * details.data.msg // => 'from a'
         *
         * // 持续监听
         * watch(() => details.data, (data) => {
         *   console.log(data.msg)
         * })
         * ```
         */
        pushWithData(to: RouteLocationRaw, data?: unknown): ReturnType<Router['push']>;
        /**
         * 携带跨页面数据，类似于 `params`，参考 `router.pushWithData`
         */
        replaceWithData(to: RouteLocationRaw, data?: unknown): ReturnType<Router['replace']>;
        /**
         * 携带跨页面数据，类似于 `params`，参考 `router.pushWithData`
         */
        forwardWithData(data?: unknown): ReturnType<Router['forward']>;
        /**
         * 携带跨页面数据，类似于 `params`，参考 `router.pushWithData`
         */
        backWithData(data?: unknown): ReturnType<Router['back']>;
        /**
         * 携带跨页面数据，类似于 `params`，参考 `router.pushWithData`
         */
        goWithData(delta: number, data?: unknown): ReturnType<Router['go']>;
        /**
         * 清理所有详情记录
         */
        clearDetailsRecord(): void;
    }
}
