import { type IsAnyFunc, type IsArray, type IsPlainObj, type NotIterable } from '@rimbu/base';
import type { Protected } from './internal.cjs';
import type { Tuple } from './tuple.cjs';
/**
 * The type to determine the allowed input values for the `match` function.
 * @typeparam T - the type of value to match
 * @typeparam C - utility type
 */
export type Match<T, C extends Partial<T> = Partial<T>> = Match.Entry<T, C, T, T>;
export declare namespace Match {
    /**
     * Determines the various allowed match types for given type `T`.
     * @typeparam T - the input value type
     * @typeparam C - utility type
     * @typeparam P - the parent type
     * @typeparam R - the root object type
     */
    type Entry<T, C, P, R> = IsAnyFunc<T> extends true ? T : IsPlainObj<T> extends true ? Match.WithResult<T, P, R, Match.Obj<T, C, P, R>> : IsArray<T> extends true ? Match.Arr<T, C, P, R> | Match.Entry<T[number & keyof T], C[number & keyof C], P, R>[] | Match.Func<T, P, R, Match.Arr<T, C, P, R> | Match.Entry<T[number & keyof T], C[number & keyof C], P, R>[]> : Match.WithResult<T, P, R, {
        [K in keyof C]: C[K & keyof T];
    }>;
    /**
     * The type that determines allowed matchers for objects.
     * @typeparam T - the input value type
     * @typeparam C - utility type
     * @typeparam P - the parent type
     * @typeparam R - the root object type
     */
    type Obj<T, C, P, R> = Match.ObjProps<T, C, R> | Match.CompoundForObj<T, C, P, R>;
    /**
     * The type to determine allowed matchers for object properties.
     * @typeparam T - the input value type
     * @typeparam C - utility type
     * @typeparam R - the root object type
     */
    type ObjProps<T, C, R> = {
        [K in keyof C]?: K extends keyof T ? Match.Entry<T[K], C[K], T, R> : never;
    };
    /**
     * The type that determines allowed matchers for arrays/tuples.
     * @typeparam T - the input value type
     * @typeparam C - utility type
     * @typeparam P - the parent type
     * @typeparam R - the root object type
     */
    type Arr<T, C, P, R> = C | Match.CompoundForArr<T, C, P, R> | Match.TraversalForArr<T, C, R> | (Match.TupIndices<T, C, R> & {
        [K in Match.CompoundType | Match.ArrayTraversalType]?: never;
    });
    /**
     * A type that either directly results in result type `S` or is a function taking the value, parent, and root values, and
     * returns a value of type `S`.
     * @typeparam T - the input value type
     * @typeparam P - the parent type
     * @typeparam R - the root object type
     * @typeparam S - the result type
     */
    type WithResult<T, P, R, S> = S | Match.Func<T, P, R, S>;
    /**
     * Type used to determine the allowed function types. Always includes booleans.
     * @typeparam T - the input value type
     * @typeparam P - the parent type
     * @typeparam R - the root object type
     * @typeparam S - the allowed return value type
     */
    type Func<T, P, R, S> = (current: Protected<T>, parent: Protected<P>, root: Protected<R>) => boolean | S;
    /**
     * Type used to indicate an object containing matches for tuple indices.
     * @typeparam T - the input value type
     * @typeparam C - utility type
     * @typeparam R - the root object type
     */
    type TupIndices<T, C, R> = {
        [K in Tuple.KeysOf<C>]?: Match.Entry<T[K & keyof T], C[K], T, R>;
    } & NotIterable;
    /**
     * Compound keys used to indicate the type of compound.
     */
    type CompoundType = 'every' | 'some' | 'none' | 'single';
    /**
     * Keys used to indicate an array match traversal.
     */
    type ArrayTraversalType = `${CompoundType}Item`;
    /**
     * Compound matcher for objects, represented as an array starting with a compound type keyword.
     * @typeparam T - the input value type
     * @typeparam C - utility type
     * @typeparam P - the parent type
     * @typeparam R - the root object type
     */
    type CompoundForObj<T, C, P, R> = [
        Match.CompoundType,
        ...Match.Entry<T, C, P, R>[]
    ];
    /**
     * Defines an object containing exactly one `CompoundType` key, having an array of matchers.
     * @typeparam T - the input value type
     * @typeparam C - utility type
     * @typeparam P - the parent type
     * @typeparam R - the root object type
     */
    type CompoundForArr<T, C, P, R> = {
        [K in Match.CompoundType]: {
            [K2 in Match.CompoundType]?: K2 extends K ? Match.Entry<T, C, P, R>[] : never;
        };
    }[Match.CompoundType];
    /**
     * Defines an object containing exactly one `TraversalType` key, having a matcher for the array element type.
     * @typeparam T - the input value type
     * @typeparam C - utility type
     * @typeparam R - the root object type
     */
    type TraversalForArr<T, C, R> = {
        [K in Match.ArrayTraversalType]: {
            [K2 in Match.ArrayTraversalType]?: K2 extends K ? Match.Entry<T[number & keyof T], C[number & keyof C], T, R> : never;
        };
    }[Match.ArrayTraversalType];
    /**
     * Utility type for collecting match failure reasons
     */
    type FailureLog = string[];
}
/**
 * Returns true if the given `value` object matches the given `matcher`, false otherwise.
 * @typeparam T - the input value type
 * @typeparam C - utility type
 * @param source - the value to match (should be a plain object)
 * @param matcher - a matcher object or a function taking the matcher API and returning a match object
 * @param failureLog - (optional) a string array that can be passed to collect reasons why the match failed
 * @example
 * ```ts
 * const input = { a: 1, b: { c: true, d: 'a' } }
 * match(input, { a: 1 }) // => true
 * match(input, { a: 2 }) // => false
 * match(input, { a: (v) => v > 10 }) // => false
 * match(input, { b: { c: true }}) // => true
 * match(input, ['every', { a: (v) => v > 0 }, { b: { c: true } }]) // => true
 * match(input, { b: { c: (v, parent, root) => v && parent.d.length > 0 && root.a > 0 } })
 *  // => true
 * ```
 */
export declare function match<T, C extends Partial<T> = Partial<T>>(source: T, matcher: Match<T, C>, failureLog?: Match.FailureLog): boolean;
