import { type AnyFunction, type AnyObject, type PartialWithUndefined } from '@augment-vir/common';
import { type RequireExactlyOne } from 'type-fest';
/**
 * Options for creating a new proxy wrapper.
 *
 * @category Internal
 */
export type CreateProxyOptions<ProxyType> = {
    /**
     * Indicates if this proxy is meant to be callable, or, in other words, if this proxy is meant
     * to proxy a function rather than just an object.
     */
    isCallable: boolean;
    /**
     * Indicates if the proxy should not be extensible. By default they are extensible, so set this
     * to true to change that behavior. Read JavaScript docs for "Object.isExtensible()" to
     * understand what being extensible means:
     * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible
     */
    isNotExtensible: boolean;
} & RequireExactlyOne<{
    /** Initial Target to wrap */
    initialTarget: Partial<ProxyType>;
    /** Initial Targets to wrap, in priority order */
    initialTargets: ReadonlyArray<Partial<ProxyType>>;
}>;
/**
 * Base type for a proxy target.
 *
 * @category Internal
 */
export type ProxyTypeBase = AnyObject | AnyFunction;
/**
 * An interface for modifying a proxy after the fact.
 *
 * @category Main
 */
export type MultiTargetProxyModifier<ProxyType extends ProxyTypeBase> = {
    /**
     * Add a target to the internal list of prioritized targets. Since this will be a fallback
     * target, a property from this target will only be used if no previously added target already
     * has the property.
     */
    addFallbackTarget(target: Partial<ProxyType>): void;
    /**
     * Add a target to the internal list of prioritized targets. Since this will be an override
     * target, a property from this target will always be used unless a new override target with the
     * same property is added or if the properties are modified on the proxy itself.
     */
    addOverrideTarget(target: Partial<ProxyType>): void;
    /** Remove the given target from the internal list of prioritized targets. */
    removeTarget(target: Partial<ProxyType>): boolean;
    /**
     * Get a list of all internal targets, in priority order. This is mostly only useful for
     * debugging purposes.
     */
    getAllTargets(): ReadonlyArray<Partial<ProxyType>>;
    /**
     * Add a new proxy handler. Since this will be an override handler, a method from this handler
     * will always be used unless a new override handler with the same method is added or if the
     * methods are modified on the handler object itself.
     */
    addProxyHandlerOverride(handlerOverride: ProxyHandler<ProxyType>): void;
    /**
     * Add a new proxy handler. Since this will be a fallback handler, a method from this handler
     * will only be used if no previously added override already has the method.
     */
    addProxyHandlerFallback(handlerOverride: ProxyHandler<ProxyType>): void;
    /** Remove the given proxy handler override from the internal list of proxy handler overrides. */
    removeProxyOverride(handlerOverride: ProxyHandler<ProxyType>): boolean;
};
/**
 * A proxy wrapper which allows performing multiple operations on the proxy to modify it after the
 * fact (with `.proxyModifier`), such as merging multiple proxies together or adding new proxy
 * handler methods.
 *
 * @category Main
 */
export type WrappedMultiTargetProxy<ProxyType extends ProxyTypeBase> = {
    proxy: ProxyType;
    proxyModifier: MultiTargetProxyModifier<ProxyType>;
};
/**
 * Create an instance of {@link WrappedMultiTargetProxy} which can be used to merge multiple targets
 * together or override proxy handler methods.
 *
 * @category Main
 * @example
 *
 * ```ts
 * import {createWrappedMultiTargetProxy} from 'proxy-vir';
 *
 * // something you imported from a 3rd party library that you want to wrap
 * const importedThing = {
 *     doThingA() {},
 * };
 *
 * const thingWrapper = createWrappedMultiTargetProxy({
 *     initialTarget: importedThing,
 * });
 *
 * // add a new override
 * thingWrapper.proxyModifier.addOverrideTarget({
 *     doThingA() {},
 * });
 * ```
 */
export declare function createWrappedMultiTargetProxy<ProxyType extends ProxyTypeBase>(options?: PartialWithUndefined<CreateProxyOptions<ProxyType>> | undefined): WrappedMultiTargetProxy<ProxyType>;
