import { AsyncOptionalCreatable } from '@salesforce/kit';
import { JsonMap, Optional } from '@salesforce/ts-types';
import { Crypto } from '../crypto/crypto';
import { LWWMap } from './lwwMap';
import { ConfigContents, ConfigEntry, ConfigValue, Key } from './configStackTypes';
/**
 * An interface for a config object with a persistent store.
 */
export type ConfigStore<P extends ConfigContents = ConfigContents> = {
    entries(): ConfigEntry[];
    get<K extends Key<P>>(key: K, decrypt: boolean): P[K];
    get<T extends ConfigValue>(key: string, decrypt: boolean): T;
    getKeysByValue(value: ConfigValue): Array<Key<P>>;
    has(key: string): boolean;
    keys(): Array<Key<P>>;
    set<K extends Key<P>>(key: K, value: P[K]): void;
    set<T extends ConfigValue>(key: string, value: T): void;
    update<K extends Key<P>>(key: K, value: Partial<P[K]>): void;
    update<T extends ConfigValue>(key: string, value: Partial<T>): void;
    unset(key: string): boolean;
    unsetAll(keys: string[]): boolean;
    clear(): void;
    values(): ConfigValue[];
    forEach(actionFn: (key: string, value: ConfigValue) => void): void;
    getContents(): P;
};
/**
 * An abstract class that implements all the config management functions but
 * none of the storage functions.
 *
 * **Note:** To see the interface, look in typescripts autocomplete help or the npm package's ConfigStore.d.ts file.
 */
export declare abstract class BaseConfigStore<T extends BaseConfigStore.Options = BaseConfigStore.Options, P extends ConfigContents = ConfigContents> extends AsyncOptionalCreatable<T> implements ConfigStore<P> {
    protected static encryptedKeys: Array<string | RegExp>;
    protected options: T;
    protected crypto?: Crypto;
    protected contents: LWWMap<P>;
    private statics;
    /**
     * Constructor.
     *
     * @param options The options for the class instance.
     * @ignore
     */
    constructor(options?: T);
    /**
     * Returns an array of {@link ConfigEntry} for each element in the config.
     */
    entries(): ConfigEntry[];
    /**
     * Returns the value associated to the key, or undefined if there is none.
     *
     * @param key The key (object property)
     * @param decrypt If it is an encrypted key, decrypt the value.
     * If the value is an object, a clone will be returned.
     */
    get<K extends Key<P>>(key: K, decrypt?: boolean): P[K];
    get<V = ConfigValue>(key: string, decrypt?: boolean): V;
    /**
     * Returns the list of keys that contain a value.
     *
     * @param value The value to filter keys on.
     */
    getKeysByValue(value: ConfigValue): Array<Key<P>>;
    /**
     * Returns a boolean asserting whether a value has been associated to the key in the config object or not.
     *
     */
    has(key: string): boolean;
    /**
     * Returns an array that contains the keys for each element in the config object.
     */
    keys(): Array<Key<P>>;
    /**
     * Sets the value for the key in the config object. This will override the existing value.
     * To do a partial update, use {@link BaseConfigStore.update}.
     *
     * @param key The key.
     * @param value The value.
     */
    set<K extends Key<P>>(key: K, value: P[K]): void;
    /**
     * Updates the value for the key in the config object. If the value is an object, it
     * will be merged with the existing object.
     *
     * @param key The key.
     * @param value The value.
     */
    update<K extends Key<P>>(key: K, value: Partial<P[K]>): void;
    /**
     * Returns `true` if an element in the config object existed and has been removed, or `false` if the element does not
     * exist. {@link BaseConfigStore.has} will return false afterwards.
     *
     * @param key The key
     */
    unset<K extends Key<P>>(key: K): boolean;
    /**
     * Returns `true` if all elements in the config object existed and have been removed, or `false` if all the elements
     * do not exist (some may have been removed). {@link BaseConfigStore.has(key)} will return false afterwards.
     *
     * @param keys The keys
     */
    unsetAll(keys: Array<Key<P>>): boolean;
    /**
     * Removes all key/value pairs from the config object.
     */
    clear(): void;
    /**
     * Returns an array that contains the values for each element in the config object.
     */
    values(): ConfigValue[];
    /**
     * Returns the entire config contents.
     *
     * *NOTE:* Data will still be encrypted unless decrypt is passed in. A clone of
     * the data will be returned to prevent storing un-encrypted data in memory and
     * potentially saving to the file system.
     *
     * @param decrypt: decrypt all data in the config. A clone of the data will be returned.
     *
     */
    getContents(decrypt?: boolean): Readonly<P>;
    /**
     * Invokes `actionFn` once for each key-value pair present in the config object.
     *
     * @param {function} actionFn The function `(key: string, value: ConfigValue) => void` to be called for each element.
     */
    forEach(actionFn: (key: string, value: ConfigValue) => void): void;
    /**
     * Convert the config object to a JSON object. Returns the config contents.
     * Same as calling {@link ConfigStore.getContents}
     */
    toObject(): JsonMap;
    /**
     * Convert an object to a {@link ConfigContents} and set it as the config contents.
     *
     * @param obj The object.
     */
    setContentsFromObject(obj: P): void;
    /**
     * Keep ConfigFile concurrency-friendly.
     * Avoid using this unless you're reading the file for the first time
     * and guaranteed to no be cross-saving existing contents
     * */
    protected setContentsFromFileContents(contents: P, timestamp?: bigint): void;
    /**
     * Sets the entire config contents.
     *
     * @param contents The contents.
     */
    protected setContents(contents?: P): void;
    protected getEncryptedKeys(): Array<string | RegExp>;
    /**
     * This config file has encrypted keys and it should attempt to encrypt them.
     *
     * @returns Has encrypted keys
     */
    protected hasEncryption(): boolean;
    protected initialContents(): P;
    /**
     * Used to initialize asynchronous components.
     */
    protected init(): Promise<void>;
    /**
     * Initialize the crypto dependency.
     */
    protected initCrypto(): Promise<void>;
    /**
     * Closes the crypto dependency. Crypto should be close after it's used and no longer needed.
     */
    protected clearCrypto(): Promise<void>;
    /**
     * Should the given key be encrypted on set methods and decrypted on get methods.
     *
     * @param key The key. Supports query key like `a.b[0]`.
     * @returns Should encrypt/decrypt
     */
    protected isCryptoKey(key: string): string | RegExp | undefined;
    protected encrypt(value: unknown): Optional<string>;
    protected decrypt(value: unknown): string | undefined;
    /**
     * Encrypt all values in a nested JsonMap.
     *
     * @param keyPaths: The complete path of the (nested) data
     * @param data: The current (nested) data being worked on.
     */
    protected recursiveEncrypt<J extends JsonMap>(data: J, parentKey?: string): J;
    /**
     * Decrypt all values in a nested JsonMap.
     *
     * @param keyPaths: The complete path of the (nested) data
     * @param data: The current (nested) data being worked on.
     */
    protected recursiveDecrypt(data: JsonMap, parentKey?: string): JsonMap;
    /**
     * Encrypt/Decrypt all values in a nested JsonMap.
     *
     * @param keyPaths: The complete path of the (nested) data
     * @param data: The current (nested) data being worked on.
     */
    private recursiveCrypto;
}
/**
 * @ignore
 */
export declare namespace BaseConfigStore {
    /**
     * Options for the config store.
     */
    type Options = {
        /**
         * Keys to encrypt.
         *
         * The preferred way to set encrypted keys is to use {@link BaseConfigStore.encryptedKeys}
         * so they are constant for all instances of a Config class. However, this is useful for
         * instantiating subclasses of ConfigStore on the fly (like {@link ConfigFile}) without
         * defining a new class.
         */
        encryptedKeys?: Array<string | RegExp>;
    };
}
