// Type definitions for config-sets v3.0.0
// Project: https://github.com/manuel-lohmus/config-sets

type Primitive = string | number | boolean | null | '';
type ArgValue = Primitive;
type ArgList = ArgValue[];

export interface ArgOptions {
    [key: string]: ArgValue | ArgList;
}

export interface DataEvent<T = any> {
    key?: string;
    value?: any;
    oldValue?: any;
    path?: string;
    target?: T;
}

export type DataListener<T = any> = (ev: DataEvent<T>) => boolean | void;

export interface DataEvents<T = any> {
    on(key: string, listener: DataListener<T>): this;
    once?(key: string, listener: DataListener<T>): this;
    off?(key: string, listener?: DataListener<T>): this;
    emit?(key: string, ev?: DataEvent<T>): boolean;
    resetChanges(): void;
}

export type ConfigContext<T extends object = any> = T & DataEvents<T> & {
    [k: string]: any;
};

/**
 * Create or access configuration contexts.
 * - If first arg is an object, it is treated as defaultConfigSettings.
 * - If first arg is a string, it is treated as a module name bucket.
 */
declare function configSets<T extends object = any>(
    defaultConfigSettings: T,
    watchFile?: boolean
): ConfigContext<T>;

declare function configSets<K extends string, T extends object = any>(
    configModuleName: K,
    defaultConfigSettings?: T,
    watchFile?: boolean
): ConfigContext<T>;

declare namespace configSets {
    /**
     * Deep-merge source into target. Respects "-metadata*" keys.
     * When overwriteChanges is true, values in target are overwritten.
     */
    function assign<T extends object, S extends object>(
        target: T,
        source: S,
        overwriteChanges?: boolean
    ): T & S;

    /**
     * Parse CLI args:
     * --key, --key=value, --key=1, --key=true, --key=, --key=a --key=b
     * Returns strings, numbers, booleans, null, '' or arrays of those.
     */
    function arg_options(): ArgOptions;

    /** Print built-in help to stdout. */
    function print_help(): void;

    /** Use production or development settings. */
    var isProduction: boolean;

    /** Production configuration context (read-only property reference). */
    const production: ConfigContext<any>;

    /** Development configuration context (read-only property reference). */
    const development: ConfigContext<any>;

    /**
     * Toggle file read/write via data-context.
     * When true, changes are persisted to config-sets.json.
     */
    var enableFileReadWrite: boolean;
}

export = configSets