import type * as symbols from '../internals/symbols.cjs';
import { Primitives } from './helpers.cjs';
import { None, Some, SelectionType } from './FindSelected.cjs';
export type MatcherType = 'not' | 'optional' | 'or' | 'and' | 'array' | 'select' | 'default';
export type MatcherProtocol<input, narrowed, matcherType extends MatcherType, selections extends SelectionType, excluded> = {
    match: <I>(value: I | input) => MatchResult;
    getSelectionKeys?: () => string[];
    matcherType?: matcherType;
};
export type MatchResult = {
    matched: boolean;
    selections?: Record<string, any>;
};
/**
 * A `Matcher` is an object implementing the match
 * protocol. It must define a `symbols.matcher` property
 * which returns an object with a `match()` method, taking
 * the input value and returning whether the pattern matches
 * or not, along with optional selections.
 */
export interface Matcher<input, narrowed, matcherType extends MatcherType = 'default', selections extends SelectionType = None, excluded = narrowed> {
    [symbols.matcher](): MatcherProtocol<input, narrowed, matcherType, selections, excluded>;
}
type UnknownMatcher = Matcher<unknown, unknown, any, any>;
export type OptionalP<input, p> = Matcher<input, p, 'optional'>;
export type ArrayP<input, p> = Matcher<input, p, 'array'>;
export type AndP<input, ps> = Matcher<input, ps, 'and'>;
export type OrP<input, ps> = Matcher<input, ps, 'or'>;
export type NotP<input, p> = Matcher<input, p, 'not'>;
export type GuardP<input, narrowed> = Matcher<input, narrowed>;
export type GuardExcludeP<input, narrowed, excluded> = Matcher<input, narrowed, 'default', None, excluded>;
export type SelectP<key extends string, input = unknown, p = Matcher<unknown, unknown>> = Matcher<input, p, 'select', Some<key>>;
export type AnonymousSelectP = SelectP<symbols.anonymousSelectKey>;
export interface ToExclude<a> {
    [symbols.toExclude]: a;
}
export type UnknownPattern = readonly [] | readonly [UnknownPattern, ...UnknownPattern[]] | {
    readonly [k: string]: UnknownPattern;
} | Set<UnknownPattern> | Map<unknown, UnknownPattern> | Primitives | UnknownMatcher;
/**
 * `Pattern<a>` is the generic type for patterns matching a value of type `a`. A pattern can be any (nested) javascript value.
 *
 * They can also be wildcards, like `P._`, `P.string`, `P.number`,
 * or other matchers, like `P.when(predicate)`, `P.not(pattern)`, etc.
 *
 * [Read documentation for `P.Pattern` on GitHub](https://github.com/gvergnaud/ts-pattern#patterns)
 *
 * @example
 * const pattern: P.Pattern<User> = { name: P.string }
 */
export type Pattern<a> = Matcher<a, unknown, any, any> | (a extends Primitives ? a : unknown extends a ? UnknownPattern : a extends readonly (infer i)[] ? a extends readonly [any, ...any] ? {
    readonly [index in keyof a]: Pattern<a[index]>;
} : readonly [] | readonly [Pattern<i>, ...Pattern<i>[]] : a extends Map<infer k, infer v> ? Map<k, Pattern<v>> : a extends Set<infer v> ? Set<Pattern<v>> : a extends object ? {
    readonly [k in keyof a]?: Pattern<Exclude<a[k], undefined>>;
} : a);
export {};
