import { IBetterLogger } from "@codiac.io/codiac-common";
import * as dom from "@codiac.io/codiac-domain";
import { AtLeast } from "@codiac.io/codiac-common/contracts";
import { IOutputStyler, IUserInputProvider, ValidationResult } from "../ops";
import { AssetTypesEnum, CabinetClusterRoot, ConfigDef, ConfigDefTypesEnum, EnterpriseRoot, EnvironmentRoot, KvpReference, RootMap, ScopedSetting, ScopeLevel } from "../apis/codiac-api/contracts";
import { Schema } from 'jsonschema';
import { ICabinetTreeEmbellisher, RootMapUiUtils, TextValueParent } from './rootmap-ui-utils';
import { ICodiacClient } from '../apis/codiac-api/i-client';
/** Base for mapping objects to each Special Config Type.
 * Will throw when all Special Config Types are not accounted for in the object.
 *
 * This data structure is known in typescript as a Mapped Type
 * @see [Typescript: Mapped Types](https://www.typescriptlang.org/docs/handbook/2/mapped-types.html)
 */
export type ConfigTypeMap<T> = {
    [key in ConfigDefTypesEnum]: T;
};
export declare enum InteractionModes {
    "echo" = "echo",
    "toscript" = "to-script",
    "silent" = "silent"
}
/** Regular expressions for validating config settings.  */
export declare const RegexBySettingType: ConfigTypeMap<{
    rxForKey?: RegExp;
    rxForValue?: RegExp;
} | undefined>;
export declare class ConfigUiUtils extends RootMapUiUtils {
    private _codiacApi;
    protected logger: IBetterLogger;
    /** The prefix on a setting value indicating that the setting value is actually sourced from a key-value store (such as an Azure key vault or AWS secret store). */
    static SOURCED_VALUE_PREFIX: string;
    /** Converts the source properties of a ScopedSetting into a parseable string so that it can be rendered as a string value.
     *
     * eg: converts this:
     * ```
     * {
     *  "type": "awsKeyVault",
     *  "name": "our-aws-east-dev-secrets",
     *  "key": "mongo-db-user-dev"
     * }
     * ```
     * into this: `#REF|awsKeyVault|our-aws-east-dev-secrets|mongo-db-user-dev`
     *
      */
    serializeSourcedValue(source: KvpReference): any;
    /** Determines if the given setting value is a serialized representation of a sourced setting. */
    isSourced(value: any): boolean;
    /** Mutates the setting object to convert a value that is a serialized source reference into the explicit source property  */
    deserializeSourcedValue(setting: AtLeast<ScopedSetting, "value" | "source">): void;
    buildConfigTree(settings: Pick<ScopedSetting, "setting" | "value">[]): TextValueParent[];
    constructor(ui: IUserInputProvider, styler: IOutputStyler, _codiacApi: ICodiacClient, logger: IBetterLogger);
    promptForTypeAndFile(enterprise: string, asset: string, assetType: AssetTypesEnum | undefined, configType?: dom.SpecialConfigTypesEnum | undefined, targetFile?: string | undefined, existingConfigDefs?: Pick<ConfigDef, "type" | "targetFile">[] | undefined, allowAddNew?: boolean, takeDefaults?: boolean, setEntireFile?: boolean): Promise<[dom.SpecialConfigTypesEnum | undefined, string | undefined, ScopedSetting[] | undefined, boolean]>;
    /** Prompts for a single setting name.
   *
   * TODO: Add ability to select branches of settings (globbed dot-paths)
   * so user can delete entire sections at a time (eg: database-settings.*).
   *
   *
   * Use this inquirer plugin for navigating the object structure:
   *    https://github.com/insightfuls/inquirer-tree-prompt
   *
   * See if this file tree selector could be fashioned to do the same:
   *    https://github.com/anc95/inquirer-file-tree-selection
   *
   * @param existing The list of existing settings to choose from.
   * @param mode Set this to `write` only if you want the user to be able to add new settings.  Indicates whether "Add New" (mode: `write`) or "All" (mode: `read`) options will be provided.
   * @param given A prompt gets invoked in `read` mode only if none match any existing settings, and in `write` mode only if none are given at all.
   */
    promptForOneSetting(configType: ConfigDefTypesEnum, existing: ScopedSetting[], mode?: "read" | "write", predefs?: {
        [dotPath: string]: Schema;
    } | undefined, given?: string | undefined): Promise<[string, ScopedSetting[], boolean, Schema | undefined]>;
    /** Performs regex validation on the given config setting name/key. */
    static settingNameIsValid(settingName: string | undefined, type: ConfigDefTypesEnum | undefined): ValidationResult;
    /** Performs regex validation on the given value for the config setting. */
    static settingValueIsValid(settingValue: string, type: dom.SpecialConfigTypesEnum | undefined): boolean;
    /** Prompts for one or many setting names.  Includes an `ALL` but NOT an `ADDNEW` option.
     *
     * TODO: Add ability to select branches of settings (globbed dot-paths)
     * so user can delete entire sections at a time (eg: database-settings.*).
     *
     *
     * Use this inquirer plugin for navigating the object structure:
     *    https://github.com/insightfuls/inquirer-tree-prompt
     *
     * See if this file tree selector could be fashioned to do the same:
     *    https://github.com/anc95/inquirer-file-tree-selection
     *
     * @param existing
     * @param given A prompt gets invoked only if no givens match any existing settings.
     */
    promptForManySettings(existing: ScopedSetting[], given?: string | string[] | undefined, multi?: boolean): Promise<[string[], ScopedSetting[], boolean]>;
    /** Searches out availables that match ANY of the given specs.
     * @param availables: setting objects to search for.
     * @param matchSpecs: each can be either a distinct setting name (eg `shoe-size`) or a glob (eg `api-settings.*`).
     */
    private static matchMultipleWithGlobbing;
    /** Determines if the two collections have ANY different concrete values,
     * regardless of order or string/array/undefined/empty)
     *
     * ```
     * DIFFERENT IF:
     * any of A not in B
     * AND
     * any of B not in A
     * ```
     * */
    private static areDifferent;
    /** RETURNS Definitive thisMachine flag.
     * Performs a findScopeTarget()
     * and THROWS on invalid. */
    validateScope(rootMap: RootMap, enterprise: string, scope: ScopeLevel | undefined, target: string | undefined): boolean;
    /**
     *
     * @param rootMap
     * @param enterprise
     * @param scope
     * @param target
     * @param existings
     * @param allowEverywhere
     * @returns Array consisting of: [<scope>, <target>, <targetChanged>, <thisMachine>]
     */
    validateAndPromptForScope(rootMap: RootMap, enterprise: string, scope?: ScopeLevel | undefined, target?: string | undefined, existings?: AtLeast<ScopedSetting, "scope" | "target">[], allowEverywhere?: boolean): Promise<[(ScopeLevel | undefined), (string | undefined), boolean, boolean]>;
    /** NOTE: /target output can be undefined ONLY if allowEverywhere is set to true.  If false, you can safely apply an assertion operator (!) to scope and target. */
    promptForScope(enterprise: string, rootMap: RootMap, existings?: AtLeast<ScopedSetting, "scope" | "target">[], allowEverywhere?: boolean, prompt?: string): Promise<Pick<ScopedSetting, "scope" | "target" | "thisMachine"> | undefined>;
    /** Appends the setting (or a count of settings) applied at each scope level */
    createSettingsEmbellisher(existings?: AtLeast<ScopedSetting, "scope" | "target">[]): ICabinetTreeEmbellisher;
    /** Determines the format of the string that was piped in,
   * and parses it into an object in memory.
   *
   * Supports formats:  json, yaml
   */
    parseInputString(input: string): {
        setting: string;
        value: any;
    }[];
}
/** Finds the object in the rootmap (ent, env, or cab) specified by the given scope.
*
* Returns undefined if the scope/target combination does not exist.
*/
export declare function findScopeTarget(rootMap: RootMap, scope: ScopeLevel, target: string): EnterpriseRoot | EnvironmentRoot | CabinetClusterRoot | undefined;
