import { IParseOptions, IStringifyOptions } from "qs";
import { Optionality } from "./helpers";
import PathParamDescription from "./PathParamDescription";
import QueryParamDescription from "./QueryParamDescription";
import RouteDescription from "./RouteDescription";
declare type MapToRoute<TRouteDescription extends RouteDescription<any, any, any>> = {
    (...params: [...args: PathPatternArgs<TRouteDescription>, stringifyOptions?: IStringifyOptions]): string;
    parseQuery: (query: string, parseOptions?: IParseOptions) => GetParsedQuery<TRouteDescription>;
    pattern: string;
} & {
    [TKey in keyof RouteChildren<TRouteDescription>]: MapToRoute<AddParams<RouteChildren<TRouteDescription>[TKey], TRouteDescription>>;
};
declare type RouteChildren<TRouteDescription extends RouteDescription<any, any, any>> = TRouteDescription extends RouteDescription<any, any, infer TChildren> ? TChildren : never;
declare type AddParams<TDestRoute extends RouteDescription<any, any, any>, TSourceRoute extends RouteDescription<any, any, any>> = TDestRoute extends RouteDescription<infer TDestPathParamsDescription, infer TDestQueryParamsDesrciption, infer TChildren> ? TSourceRoute extends RouteDescription<infer TSourcePathParamsDescription, infer TSourceQueryParamsDescription, any> ? RouteDescription<[
    ...TSourcePathParamsDescription,
    ...TDestPathParamsDescription
], TSourceQueryParamsDescription & TDestQueryParamsDesrciption, TChildren> : never : never;
declare type MakeOptional<T> = {} extends T ? [T?] : [T];
declare type PathPatternArgs<TRouteDescription extends RouteDescription<any, any, any>> = [
    ...pathParams: MakeOptional<MapPathParams<GetPathParams<TRouteDescription>>>,
    ...queryParams: MakeOptional<MapQueryParams<GetQueryParams<TRouteDescription>>>
];
declare type GetPathParams<TRouteDescription extends RouteDescription<any, any, any>> = TRouteDescription extends RouteDescription<infer TPathParams, any, any> ? TPathParams : never;
declare type GetQueryParams<TRouteDescription extends RouteDescription<any, any, any>> = TRouteDescription extends RouteDescription<any, infer TQueryParams, any> ? TQueryParams : never;
declare type UnionToIntersection<T> = (T extends any ? (x: T) => any : never) extends (x: infer R) => any ? R : never;
declare type MapPathParams<TPathParams extends PathParamDescription<string, Optionality>[]> = UnionToIntersection<{
    [T in keyof TPathParams]: GetParam<TPathParams[T]>;
}[number]>;
declare type SingleOrArray<T> = T | T[];
declare type MapQueryParams<TQueryParams extends Record<string, QueryParamDescription<any, Optionality>>> = {
    [TName in keyof TQueryParams as TQueryParams[TName] extends QueryParamDescription<any, "optional"> ? TName : never]?: SingleOrArray<GetQueryResultType<TQueryParams[TName]>>;
} & {
    [TName in keyof TQueryParams as TQueryParams[TName] extends QueryParamDescription<any, "required"> ? TName : never]: SingleOrArray<GetQueryResultType<TQueryParams[TName]>>;
};
declare type GetQueryResultType<TQueryParam extends QueryParamDescription<any, Optionality>> = TQueryParam extends QueryParamDescription<infer TReturnType, Optionality> ? TReturnType : never;
declare type GetParam<TPathParam> = TPathParam extends PathParamDescription<infer TName, infer TOptional> ? TOptional extends "optional" ? {
    [T in TName]?: string;
} : {
    [T in TName]: string;
} : never;
declare type GetParsedQuery<TRouteDescription extends RouteDescription<any, any, any>> = MapQueryParams<GetQueryParams<TRouteDescription>>;
export default function createRouting<TRoutes extends {
    readonly [name: string]: RouteDescription<any, any, any>;
}>(routes: TRoutes, options?: IStringifyOptions & IParseOptions): {
    readonly [TKey in keyof TRoutes]: MapToRoute<TRoutes[TKey]>;
};
export {};
