/**
 * A programming config for lintstaged.
 *
 * @packageDocumentation
 */

/**
 * Action type, every action should implement this type.
 *
 * @public
 */
export declare type BaseActionFn<O extends IBaseActionOptions> = (options?: O) => string;

/**
 * Config builder. This class should not be created manually.
 * Use {@link Config.builder} or {@link Config.default} instead.
 *
 * @public
 */
export declare class Builder<K extends string> implements IConfigBuilder {
    private _result;
    private _settings;
    /**
     * Do not use this constructor directly.
     * Use {@link Config.builder} or {@link Config.default} instead.
     */
    constructor();
    /**
     * enable debug mode when loading configuration
     *
     * @returns this object
     *
     * @public
     */
    debugMode(): this;
    /**
     * append default actions to current builder
     *
     * @returns this object
     *
     * @public
     */
    default(custom?: CustomDefaultConfig): Builder<K | DefaultKey>;
    /**
     * append value to list of regex or actions if needed.
     * If input key never created yet,
     * it will create with input value
     *
     * @param key - group key
     * @param value - config value associate with input key
     * @returns this object
     *
     * @public
     */
    append<EK extends string>(key: EK, value: Partial<Exclude<IConfigValue, "actionFn">>): Builder<K | EK>;
    /**
     * add new config group to current configuration
     *
     * @param key - group key
     * @param value - config value associate with input key
     * @returns this object
     *
     * @public
     */
    set<EK extends string>(key: EK, value: Partial<IConfigValue>): Builder<K | EK>;
    /**
     * build Config with current builder
     *
     * @returns this object
     *
     * @public
     */
    build(): Config<K>;
    /**
     * delete group by key
     *
     * @param key - group key
     * @returns this object
     *
     * @public
     */
    delete<EK extends K>(key: EK): Builder<Exclude<K, EK>>;
    private _fillValue;
    private _mergeValue;
}

/**
 * All possible command type on lintstaged configuration.
 *
 * @public
 */
export declare type CommandType = string | Array<string> | Promise<string | Array<string>> | Array<Promise<string | Array<string>>>;

/**
 * Configuration object to generate list of command
 * needed for specify values on {@link ConfigCondition}
 *
 * @public
 */
export declare class Config<K extends string> implements IConfigBuilder, IConfig {
    /**
     * create config builder with empty value.
     *
     * @returns config builder
     *
     * @public
     */
    static builder<K extends string = "">(): Builder<K>;
    /**
     * create config builder with default group predefined.
     *
     * @returns config builder
     */
    static default(): Builder<DefaultKey>;
    private _config;
    private _settings;
    constructor(config: Map<K, IConfigValue>, settings: Map<string, string>);
    /**
     * length of configuration.
     *
     * @remarks
     * This can be check to ensure
     * we setting config object correctly
     *
     * @public
     */
    get length(): number;
    /**
     * is debug mode enabled?
     */
    private get _isDebug();
    /**
     * {@inheritDoc IConfig.getCommands}
     * @override
     */
    getCommands(condition: ConfigCondition): Promise<Array<string>>;
    /**
     * Empty implementation as Config already IConfig,
     * so we can just return itself.
     *
     * @returns this object
     * @override
     *
     * @public
     */
    build(): this;
    /**
     * Compare current config with another config.
     * This function WILL ignore all function from comparison
     *
     * @param c - another config
     * @returns true if this config is equal to other config
     *
     * @beta
     */
    compare(c: Config<string>): boolean;
    private _resolveAction;
}

/**
 * Condition to getCommand from config
 *
 * @public
 */
export declare type ConfigCondition = (
/** each action will have key correspond to action function */
key: string, 
/** files regex for execute specific action */
regex: Array<string>) => Array<string>;

/**
 * Function that we use to export from lint-staged config file
 *
 * @public
 */
export declare type ConfigFn = (filenames: Array<string>) => CommandType;

/**
 * Custom type for default configuration builder
 * @beta
 */
export declare interface CustomDefaultConfig {
    /** custom config for jsts eslint */
    eslint?: OnlyAppOptions<IEslintOptions> | false;
    /** custom config for jsts prettier */
    jstsPrettier?: OnlyAppOptions<IPrettierOptions> | false;
    /** custom config for json prettier */
    jsonPrettier?: OnlyAppOptions<IPrettierOptions> | false;
    /** custom config for shellcheck */
    shellcheck?: OnlyAppOptions<IShellcheckOptions> | false;
    /** custom config for yamllint */
    yamllint?: OnlyAppOptions<IYamllintOptions> | false;
}

/**
 * Default yamllint config path from root repository
 *
 * @beta
 */
export declare const DEFAULT_YAMLLINT_CONFIGS: string[];

/**
 * Default possible key
 *
 * @public
 */
export declare type DefaultKey = "jsts" | "json" | "sh" | "yaml";

/**
 * This is a function to define a configuration for lintstaged file.
 *
 * @param builder - a setting for configure lintstaged.
 * @returns a lintstaged configuration.
 *
 * @example
 *
 * Use lintstaged-config with default configuration
 * ```ts
 * const { default: defineConfig, Config } = require("@kcws/lintstaged-config");
 * module.exports = defineConfig(Config.default());
 * ```
 *
 * @example
 *
 * Use lintstaged-config with custom configuration
 * ```ts
 * const { default: defineConfig, Config } = require("@kcws/lintstaged-config");
 * module.exports = defineConfig(Config.builder().append("group_name", {}));
 * ```
 *
 * @beta
 */
declare function defineConfig(builder: IConfigBuilder): ConfigFn;
export default defineConfig;

/**
 * create command with input option.
 *
 * @remarks
 *
 * Function type: {@link BaseActionFn} and
 * Option type: {@link IEslintOptions}
 *
 * @param option - customize option
 * @returns command
 *
 * @beta
 */
export declare const eslint: BaseActionFn<IEslintOptions>;

/**
 * build command using internal command finder.
 *
 * @param cmd - command name
 * @param args - command arguments
 * @returns command string
 *
 * @beta
 */
export declare const generic: (cmd: string, ...args: Array<string>) => string;

/**
 * Base action options, every action option should implement this type.
 *
 * @public
 */
export declare interface IBaseActionOptions {
    /**
     * list of files changed
     * @readonly
     */
    files?: Array<string>;
}

/**
 * A lintstaged configuration
 *
 * @public
 */
export declare interface IConfig {
    /**
     * select series of command needed to execute based on input condition
     *
     * @remarks
     *
     * we will select all static and dynamic actions from
     * any config group that regex return non-empty array.
     * and execute action to get command and merge them together.
     *
     * @param condition - condition to select specify config values
     * @returns commands to execute on terminal
     *
     * @public
     */
    getCommands(condition: ConfigCondition): Promise<Array<string>>;
}

/**
 * A configuration builder for lintstaged.
 *
 * @public
 */
export declare interface IConfigBuilder {
    /**
     * Build configuration object.
     */
    build(): IConfig;
}

/**
 * All possible values contains in configuration mapper.
 *
 * @public
 */
export declare interface IConfigValue {
    /**
     * Regular Expression for matching staged files
     *
     * @remarks
     * This values will be passed to
     * {@link https://github.com/micromatch/micromatch | micromatch} to apply.
     */
    regexs: Array<string>;
    /**
     * Action after staged file matched with regex values.
     *
     * @remarks
     * This values will execute as static command
     * without any matched files name,
     * if you would like to include staged file in the command.
     * Please use {@link IConfigValue.actionFn} instead.
     * You can specify both values.
     */
    actions: CommandType;
    /**
     * Function execute with matched regex values.
     *
     * @remarks
     * This function will include staged files matched with provide regex,
     * if you would like to run simple command(s).
     * Please use {@link IConfigValue.actions} instead.
     * You can specify both values.
     */
    actionFn: ConfigFn;
}

/**
 * Option for create eslint command
 *
 * @beta
 */
export declare interface IEslintOptions extends IBaseActionOptions {
    fix?: boolean;
    maxWarnings?: number;
}

/**
 * Option for create prettier command
 *
 * @beta
 */
export declare interface IPrettierOptions extends IBaseActionOptions {
    fix?: boolean;
}

/**
 * Option for create shellcheck command
 *
 * @beta
 */
export declare interface IShellcheckOptions extends IBaseActionOptions {
}

/**
 * Option for create yamllint command
 *
 * @beta
 */
export declare interface IYamllintOptions extends IBaseActionOptions {
    /** yamllint config file; recommend to use absolute path */
    config?: string;
    /**
     * enabled yamllint strict mode;
     * Strict means return non-zero code when warning occur
     */
    strict?: boolean;
}

/**
 * A helper type for select only application options without base action.
 * @beta
 */
export declare type OnlyAppOptions<T> = Pick<T, Exclude<keyof T, keyof IBaseActionOptions>>;

/**
 * create command with input option
 *
 * @remarks
 *
 * Function type: {@link BaseActionFn} and
 * Option type: {@link IPrettierOptions}
 *
 * @param option - customize option
 * @returns command
 *
 * @beta
 */
export declare const prettier: BaseActionFn<IPrettierOptions>;

/**
 * build rush command using internal command finder.
 * this will automatically resolve package to run
 * using cwd and package.json file.
 *
 * @param cmd - rush command to execute
 * @param args - additional command arguments
 * @returns command string
 *
 * @beta
 */
export declare const rush: (cmd: string, ...args: Array<string>) => ConfigFn;

/**
 * build rush command using internal command finder.
 *
 * @param pkg - package name that will run on
 * @param cmd - rush command to execute
 * @param args - additional command arguments
 * @returns command string
 *
 * @beta
 */
export declare const rushOn: (pkg: string | undefined, cmd: string, ...args: Array<string>) => string;

/**
 * create command with input option
 *
 * @remarks
 *
 * Function type: {@link BaseActionFn} and
 * Option type: {@link IShellcheckOptions}
 *
 * @param option - customize option
 * @returns command
 *
 * @beta
 */
export declare const shellcheck: BaseActionFn<IShellcheckOptions>;

/**
 * A walking callback with walk nested directory
 *
 * @internal
 */
export declare type _WalkCallback = (directory: string) => string | undefined;

/**
 * create command with input option
 *
 * @remarks
 *
 * Function type: {@link BaseActionFn} and
 * Option type: {@link IYamllintOptions}
 *
 * @param option - customize option
 * @returns command
 *
 * @beta
 */
export declare const yamllint: BaseActionFn<IYamllintOptions>;

export { }
