import { Buffer } from 'node:buffer';
import type { InputOutputAdapter } from '@yeoman/adapter/types';
import type expand from '@inquirer/expand';
import type { Separator } from '@inquirer/expand';
import { type Change, DiffLinesOptionsNonabortable, DiffWordsOptionsNonabortable } from 'diff';
import { type FileTransform } from 'mem-fs';
import type { MemFsEditorFile } from 'mem-fs-editor';
declare const statusToSkipFile: readonly ["skip", "diff", "ignore"];
export type ConflicterLog = ['create', 'skip', 'identical', 'force', 'conflict'][number];
export type ConflicterStatus = ConflicterLog | (typeof statusToSkipFile)[number];
export type ConflicterAction = 'write' | 'abort' | 'diff' | 'reload' | 'force' | 'edit' | 'ask' | 'skip' | 'ignore';
export declare function setConflicterStatus<F extends ConflicterFile = ConflicterFile>(file: F, status?: ConflicterStatus): F;
type ConflicterData = {
    diskContents: Buffer;
};
export type ConflicterFile = MemFsEditorFile & {
    conflicter?: ConflicterStatus;
};
type ConflicterFileInternal = ConflicterFile & {
    relativePath: string;
    fileModeChanges?: [number, number];
    changesDetected?: boolean;
    binary?: boolean;
    conflicterChanges?: Change[];
    conflicterData?: ConflicterData;
};
type ConflictedFile = ConflicterFileInternal & {
    conflicterChanges: Change[];
    changesDetected: true;
    conflicterData: ConflicterData;
};
type ActionCallbackOptions = {
    file: ConflicterFileInternal | ConflictedFile;
    relativeFilePath: string;
    adapter: InputOutputAdapter;
};
type ValueActionCallback = (opt: ActionCallbackOptions) => ConflicterAction | Promise<ConflicterAction>;
type ActionChoices = Parameters<typeof expand<ConflicterAction | ValueActionCallback>>[0]['choices'];
type CustomizeActions = (actions: ActionChoices, options: {
    separator?: (separator?: string) => Separator;
}) => ActionChoices;
export type ConflicterOptions = {
    /** When set to true, we won't check for conflict. (the conflicter become a passthrough) */
    force?: boolean;
    /** When set to true, we will abort on first conflict. (used for testing reproducibility) */
    bail?: boolean;
    /** When set to true, whitespace changes should not generate a conflict. */
    ignoreWhitespace?: boolean;
    /** When set to true, identical files should be written to disc. */
    regenerate?: boolean;
    /** When set to true, no write operation will be executed. */
    dryRun?: boolean;
    /** Path to be used as reference for relative path. */
    cwd?: string;
    /** Custom diff options */
    diffOptions?: DiffWordsOptionsNonabortable | DiffLinesOptionsNonabortable;
    /** Customize file actions */
    customizeActions?: CustomizeActions;
};
type ConflicterTransformOptions = {
    yoResolveFileName?: string;
};
/**
 * The Conflicter is a module that can be used to detect conflict between files. Each
 * Generator file system helpers pass files through this module to make sure they don't
 * break a user file.
 *
 * When a potential conflict is detected, we prompt the user and ask them for
 * confirmation before proceeding with the actual write.
 */
export declare class Conflicter {
    private readonly adapter;
    force: boolean;
    bail: boolean;
    ignoreWhitespace: boolean;
    regenerate: boolean;
    dryRun: boolean;
    cwd: string;
    diffOptions?: DiffWordsOptionsNonabortable | DiffLinesOptionsNonabortable;
    customizeActions: CustomizeActions;
    constructor(adapter: InputOutputAdapter, options?: ConflicterOptions);
    private log;
    /**
     * Print the file differences to console
     *
     * @param  {Object}   file File object respecting this interface: { path, contents }
     */
    private _printDiff;
    /**
     * Detect conflicts between file contents at `filepath` with the `contents` passed to the
     * function
     *
     * If `filepath` points to a folder, we'll always return true.
     *
     * Based on detect-conflict module
     *
     * @param  {import('vinyl')} file File object respecting this interface: { path, contents }
     * @return {Boolean} `true` if there's a conflict, `false` otherwise.
     */
    private _detectConflict;
    /**
     * Check if a file conflict with the current version on the user disk
     *
     * A basic check is done to see if the file exists, if it does:
     *
     *   1. Read its content from  `fs`
     *   2. Compare it with the provided content
     *   3. If identical, mark it as is and skip the check
     *   4. If diverged, prepare and show up the file collision menu
     *
     * @param file - Vinyl file
     * @return Promise the Vinyl file
     */
    private checkForCollision;
    private _checkForCollision;
    private ask;
    /**
     * Actual prompting logic
     * @private
     * @param {import('vinyl')} file vinyl file object
     * @param {Number} counter prompts
     */
    private _ask;
    createTransform({ yoResolveFileName }?: ConflicterTransformOptions): FileTransform<MemFsEditorFile>;
}
export declare const createConflicterTransform: (adapter: InputOutputAdapter, { yoResolveFileName, ...conflicterOptions }?: ConflicterOptions & ConflicterTransformOptions) => FileTransform<MemFsEditorFile>;
export {};
