import { IConstruct } from 'constructs';
import { IResolvable, ITokenResolver } from './resolvable';
import { TokenizedStringFragments } from './string-fragments';
/**
 * (experimental) An enum-like class that represents the result of comparing two Tokens.
 *
 * The return type of {@link Token.compareStrings}.
 *
 * @experimental
 */
export declare class TokenComparison {
    /**
     * (experimental) This means we're certain the two components are NOT Tokens, and identical.
     *
     * @experimental
     */
    static readonly SAME: TokenComparison;
    /**
     * (experimental) This means we're certain the two components are NOT Tokens, and different.
     *
     * @experimental
     */
    static readonly DIFFERENT: TokenComparison;
    /**
     * (experimental) This means exactly one of the components is a Token.
     *
     * @experimental
     */
    static readonly ONE_UNRESOLVED: TokenComparison;
    /**
     * (experimental) This means both components are Tokens.
     *
     * @experimental
     */
    static readonly BOTH_UNRESOLVED: TokenComparison;
    private constructor();
}
/**
 * (experimental) Represents a special or lazily-evaluated value.
 *
 * Can be used to delay evaluation of a certain value in case, for example,
 * that it requires some context or late-bound data. Can also be used to
 * mark values that need special processing at document rendering time.
 *
 * Tokens can be embedded into strings while retaining their original
 * semantics.
 *
 * @experimental
 */
export declare class Token {
    /**
     * (experimental) Returns true if obj represents an unresolved value.
     *
     * One of these must be true:
     *
     * - `obj` is an IResolvable
     * - `obj` is a string containing at least one encoded `IResolvable`
     * - `obj` is either an encoded number or list
     *
     * This does NOT recurse into lists or objects to see if they
     * containing resolvables.
     *
     * @param obj The object to test.
     * @experimental
     */
    static isUnresolved(obj: any): boolean;
    /**
     * (experimental) Return a reversible string representation of this token.
     *
     * If the Token is initialized with a literal, the stringified value of the
     * literal is returned. Otherwise, a special quoted string representation
     * of the Token is returned that can be embedded into other strings.
     *
     * Strings with quoted Tokens in them can be restored back into
     * complex values with the Tokens restored by calling `resolve()`
     * on the string.
     *
     * @experimental
     */
    static asString(value: any, options?: EncodingOptions): string;
    /**
     * (experimental) Return a reversible number representation of this token.
     *
     * @experimental
     */
    static asNumber(value: any): number;
    /**
     * (experimental) Return a reversible list representation of this token.
     *
     * @experimental
     */
    static asList(value: any, options?: EncodingOptions): string[];
    /**
     * (experimental) Return a resolvable representation of the given value.
     *
     * @experimental
     */
    static asAny(value: any): IResolvable;
    /**
     * (experimental) Compare two strings that might contain Tokens with each other.
     *
     * @experimental
     */
    static compareStrings(possibleToken1: string, possibleToken2: string): TokenComparison;
    private constructor();
}
/**
 * (experimental) Less oft-needed functions to manipulate Tokens.
 *
 * @experimental
 */
export declare class Tokenization {
    /**
     * (experimental) Un-encode a string potentially containing encoded tokens.
     *
     * @experimental
     */
    static reverseString(s: string): TokenizedStringFragments;
    /**
     * (experimental) Un-encode a string which is either a complete encoded token, or doesn't contain tokens at all.
     *
     * It's illegal for the string to be a concatenation of an encoded token and something else.
     *
     * @experimental
     */
    static reverseCompleteString(s: string): IResolvable | undefined;
    /**
     * (experimental) Un-encode a Tokenized value from a number.
     *
     * @experimental
     */
    static reverseNumber(n: number): IResolvable | undefined;
    /**
     * (experimental) Un-encode a Tokenized value from a list.
     *
     * @experimental
     */
    static reverseList(l: string[]): IResolvable | undefined;
    /**
     * (experimental) Reverse any value into a Resolvable, if possible.
     *
     * In case of a string, the string must not be a concatenation.
     *
     * @experimental
     */
    static reverse(x: any, options?: ReverseOptions): IResolvable | undefined;
    /**
     * (experimental) Resolves an object by evaluating all tokens and removing any undefined or empty objects or arrays.
     *
     * Values can only be primitives, arrays or tokens. Other objects (i.e. with methods) will be rejected.
     *
     * @param obj The object to resolve.
     * @param options Prefix key path components for diagnostics.
     * @experimental
     */
    static resolve(obj: any, options: ResolveOptions): any;
    /**
     * (experimental) Return whether the given object is an IResolvable object.
     *
     * This is different from Token.isUnresolved() which will also check for
     * encoded Tokens, whereas this method will only do a type check on the given
     * object.
     *
     * @experimental
     */
    static isResolvable(obj: any): obj is IResolvable;
    /**
     * (experimental) Stringify a number directly or lazily if it's a Token.
     *
     * If it is an object (i.e., { Ref: 'SomeLogicalId' }), return it as-is.
     *
     * @experimental
     */
    static stringifyNumber(x: number): string;
    private constructor();
}
/**
 * (experimental) Options for the 'reverse()' operation.
 *
 * @experimental
 */
export interface ReverseOptions {
    /**
     * (experimental) Fail if the given string is a concatenation.
     *
     * If `false`, just return `undefined`.
     *
     * @default true
     * @experimental
     */
    readonly failConcat?: boolean;
}
/**
 * (experimental) Options to the resolve() operation.
 *
 * NOT the same as the ResolveContext; ResolveContext is exposed to Token
 * implementors and resolution hooks, whereas this struct is just to bundle
 * a number of things that would otherwise be arguments to resolve() in a
 * readable way.
 *
 * @experimental
 */
export interface ResolveOptions {
    /**
     * (experimental) The scope from which resolution is performed.
     *
     * @experimental
     */
    readonly scope: IConstruct;
    /**
     * (experimental) The resolver to apply to any resolvable tokens found.
     *
     * @experimental
     */
    readonly resolver: ITokenResolver;
    /**
     * (experimental) Whether the resolution is being executed during the prepare phase or not.
     *
     * @default false
     * @experimental
     */
    readonly preparing?: boolean;
    /**
     * (experimental) Whether to remove undefined elements from arrays and objects when resolving.
     *
     * @default true
     * @experimental
     */
    readonly removeEmpty?: boolean;
}
/**
 * (experimental) Properties to string encodings.
 *
 * @experimental
 */
export interface EncodingOptions {
    /**
     * (experimental) A hint for the Token's purpose when stringifying it.
     *
     * @experimental
     */
    readonly displayHint?: string;
}
export declare function isResolvableObject(x: any): x is IResolvable;
/**
 * Call the given function only if all given values are resolved
 *
 * Exported as a function since it will be used by TypeScript modules, but
 * can't be exposed via JSII because of the generics.
 */
export declare function withResolved<A>(a: A, fn: (a: A) => void): void;
export declare function withResolved<A, B>(a: A, b: B, fn: (a: A, b: B) => void): void;
export declare function withResolved<A, B, C>(a: A, b: B, c: C, fn: (a: A, b: B, c: C) => void): void;
