import { Prettify } from './typescript.model.js';
import '../utils/navigator.utils.js';

interface ParamTypeMap {
    string: string;
    number: number;
    boolean: boolean;
}
type ParamValue<Map extends Partial<ParamTypeMap> = ParamTypeMap> = Map[keyof Map];
type ExtractSegmentParams<Segment extends string, Types extends Partial<ParamTypeMap> = ParamTypeMap> = Segment extends `:{${infer Type}}:${infer Name}:${infer Optional}` ? Optional extends '?' ? {
    [K in Name]?: Type extends keyof Types ? Types[Type] : ParamValue<Types>;
} : {
    [K in Name]: Type extends keyof Types ? Types[Type] : ParamValue<Types>;
} : Segment extends `:{${infer Type}}:${infer Name}` ? {
    [K in Name]: Type extends keyof Types ? Types[Type] : ParamValue<Types>;
} : Segment extends `:${infer Name}:?` ? {
    [K in Name]?: ParamValue<Types>;
} : Segment extends `:${infer Name}` ? {
    [K in Name]: ParamValue<Types>;
} : {};
type ExtractRecursiveParams<Path extends string, Types extends Partial<ParamTypeMap> = ParamTypeMap, Result extends object = {}> = Path extends `${infer Head}/${infer Tail}` ? ExtractRecursiveParams<Tail, Types, Result & ExtractSegmentParams<Head>> : Result & ExtractSegmentParams<Path, Types>;
/**
 * Extracts the parameters from a path template.
 * If the template does not contain any parameters, Record<string, ParamValue<Types> | undefined>
 */
type ExtractPathParams<Path extends string, Types extends Partial<ParamTypeMap> = ParamTypeMap> = Prettify<Path extends `${infer _Start}/:${infer _End}` ? ExtractRecursiveParams<Path, Types> : Record<string, ParamValue<Types> | undefined>>;
/**
 * Extracts the parameters from a strict path template.
 * If the template does not contain any parameters, Record<string, never> is returned.
 */
type ExtractStrictPathParams<Path extends string, Types extends Partial<ParamTypeMap> = ParamTypeMap> = Prettify<Path extends `${infer _Start}/:${infer _End}` ? ExtractRecursiveParams<Path, Types> : Record<string, never>>;

export type { ExtractPathParams, ExtractStrictPathParams, ParamValue };
