import { ServiceIdentifier } from '../../instantiation/common/instantiation.js';
import { Event } from '../../../base/common/event.js';
import { OperatingSystem, IProcessEnvironment } from '../../../base/common/platform.js';
import { URI } from '../../../base/common/uri.js';
import { ISerializedCommandDetectionCapability, ITerminalCapabilityStore } from './capabilities/capabilities.js';
import { IProcessDetails } from './terminalProcess.js';
import { ThemeIcon } from '../../../base/common/themables.js';
import { ISerializableEnvironmentVariableCollections } from './environmentVariable.js';
import { IWorkspaceFolder } from '../../workspace/common/workspace.js';
import { PerformanceMark } from '../../../base/common/performance.js';
import { ILogService } from '../../log/common/log.js';

declare const enum PosixShellType {
    PowerShell = "pwsh",
    Bash = "bash",
    Fish = "fish",
    Sh = "sh",
    Csh = "csh",
    Ksh = "ksh",
    Zsh = "zsh",
    Python = "python"
}
declare const enum WindowsShellType {
    CommandPrompt = "cmd",
    PowerShell = "pwsh",
    Wsl = "wsl",
    GitBash = "gitbash",
    Python = "python"
}
type TerminalShellType = PosixShellType | WindowsShellType;
interface IRawTerminalInstanceLayoutInfo<T> {
    relativeSize: number;
    terminal: T;
}
interface IRawTerminalTabLayoutInfo<T> {
    isActive: boolean;
    activePersistentProcessId: number | undefined;
    terminals: IRawTerminalInstanceLayoutInfo<T>[];
}
type ITerminalTabLayoutInfoById = IRawTerminalTabLayoutInfo<number>;
interface IRawTerminalsLayoutInfo<T> {
    tabs: IRawTerminalTabLayoutInfo<T>[];
}
interface IPtyHostAttachTarget {
    id: number;
    pid: number;
    title: string;
    titleSource: TitleEventSource;
    cwd: string;
    workspaceId: string;
    workspaceName: string;
    isOrphan: boolean;
    icon: TerminalIcon | undefined;
    fixedDimensions: IFixedTerminalDimensions | undefined;
    environmentVariableCollections: ISerializableEnvironmentVariableCollections | undefined;
    reconnectionProperties?: IReconnectionProperties;
    waitOnExit?: WaitOnExitValue;
    hideFromUser?: boolean;
    isFeatureTerminal?: boolean;
    type?: TerminalType;
    hasChildProcesses: boolean;
    shellIntegrationNonce: string;
}
interface IReconnectionProperties {
    ownerId: string;
    data?: unknown;
}
type TerminalType = 'Task' | 'Local' | undefined;
declare enum TitleEventSource {
    /** From the API or the rename command that overrides any other type */
    Api = 0,
    /** From the process name property*/
    Process = 1,
    /** From the VT sequence */
    Sequence = 2,
    /** Config changed */
    Config = 3
}
type ITerminalsLayoutInfo = IRawTerminalsLayoutInfo<IPtyHostAttachTarget | null>;
type ITerminalsLayoutInfoById = IRawTerminalsLayoutInfo<number>;
declare const enum ProcessPropertyType {
    Cwd = "cwd",
    InitialCwd = "initialCwd",
    FixedDimensions = "fixedDimensions",
    Title = "title",
    ShellType = "shellType",
    HasChildProcesses = "hasChildProcesses",
    ResolvedShellLaunchConfig = "resolvedShellLaunchConfig",
    OverrideDimensions = "overrideDimensions",
    FailedShellIntegrationActivation = "failedShellIntegrationActivation",
    UsedShellIntegrationInjection = "usedShellIntegrationInjection"
}
interface IProcessProperty<T extends ProcessPropertyType> {
    type: T;
    value: IProcessPropertyMap[T];
}
interface IProcessPropertyMap {
    [ProcessPropertyType.Cwd]: string;
    [ProcessPropertyType.InitialCwd]: string;
    [ProcessPropertyType.FixedDimensions]: IFixedTerminalDimensions;
    [ProcessPropertyType.Title]: string;
    [ProcessPropertyType.ShellType]: TerminalShellType | undefined;
    [ProcessPropertyType.HasChildProcesses]: boolean;
    [ProcessPropertyType.ResolvedShellLaunchConfig]: IShellLaunchConfig;
    [ProcessPropertyType.OverrideDimensions]: ITerminalDimensionsOverride | undefined;
    [ProcessPropertyType.FailedShellIntegrationActivation]: boolean | undefined;
    [ProcessPropertyType.UsedShellIntegrationInjection]: boolean | undefined;
}
interface IFixedTerminalDimensions {
    /**
     * The fixed columns of the terminal.
     */
    cols?: number;
    /**
     * The fixed rows of the terminal.
     */
    rows?: number;
}
interface IPtyHostLatencyMeasurement {
    label: string;
    latency: number;
}
interface IShellLaunchConfig {
    /**
     * The name of the terminal, if this is not set the name of the process will be used.
     */
    name?: string;
    /**
     * A string to follow the name of the terminal with, indicating the type of terminal
     */
    type?: 'Task' | 'Local';
    /**
     * The shell executable (bash, cmd, etc.).
     */
    executable?: string;
    /**
     * The CLI arguments to use with executable, a string[] is in argv format and will be escaped,
     * a string is in "CommandLine" pre-escaped format and will be used as is. The string option is
     * only supported on Windows and will throw an exception if used on macOS or Linux.
     */
    args?: string[] | string;
    /**
     * The current working directory of the terminal, this overrides the `terminal.integrated.cwd`
     * settings key.
     */
    cwd?: string | URI;
    /**
     * A custom environment for the terminal, if this is not set the environment will be inherited
     * from the VS Code process.
     */
    env?: ITerminalEnvironment;
    /**
     * Whether to ignore a custom cwd from the `terminal.integrated.cwd` settings key (e.g. if the
     * shell is being launched by an extension).
     */
    ignoreConfigurationCwd?: boolean;
    /**
     * The reconnection properties for this terminal
     */
    reconnectionProperties?: IReconnectionProperties;
    /** Whether to wait for a key press before closing the terminal. */
    waitOnExit?: WaitOnExitValue;
    /**
     * A string including ANSI escape sequences that will be written to the terminal emulator
     * _before_ the terminal process has launched, when a string is specified, a trailing \n is
     * added at the end. This allows for example the terminal instance to display a styled message
     * as the first line of the terminal. Use \x1b over \033 or \e for the escape control character.
     */
    initialText?: string | {
        text: string;
        trailingNewLine: boolean;
    };
    /**
     * Custom PTY/pseudoterminal process to use.
     */
    customPtyImplementation?: (terminalId: number, cols: number, rows: number) => ITerminalChildProcess;
    /**
     * A UUID generated by the extension host process for terminals created on the extension host process.
     */
    extHostTerminalId?: string;
    /**
     * This is a terminal that attaches to an already running terminal.
     */
    attachPersistentProcess?: {
        id: number;
        findRevivedId?: boolean;
        pid: number;
        title: string;
        titleSource: TitleEventSource;
        cwd: string;
        icon?: TerminalIcon;
        color?: string;
        hasChildProcesses?: boolean;
        fixedDimensions?: IFixedTerminalDimensions;
        environmentVariableCollections?: ISerializableEnvironmentVariableCollections;
        reconnectionProperties?: IReconnectionProperties;
        type?: TerminalType;
        waitOnExit?: WaitOnExitValue;
        hideFromUser?: boolean;
        isFeatureTerminal?: boolean;
        shellIntegrationNonce: string;
    };
    /**
     * Whether the terminal process environment should be exactly as provided in
     * `TerminalOptions.env`. When this is false (default), the environment will be based on the
     * window's environment and also apply configured platform settings like
     * `terminal.integrated.env.windows` on top. When this is true, the complete environment must be
     * provided as nothing will be inherited from the process or any configuration.
     */
    strictEnv?: boolean;
    /**
     * Whether the terminal process environment will inherit VS Code's "shell environment" that may
     * get sourced from running a login shell depnding on how the application was launched.
     * Consumers that rely on development tools being present in the $PATH should set this to true.
     * This will overwrite the value of the inheritEnv setting.
     */
    useShellEnvironment?: boolean;
    /**
     * When enabled the terminal will run the process as normal but not be surfaced to the user
     * until `Terminal.show` is called. The typical usage for this is when you need to run
     * something that may need interactivity but only want to tell the user about it when
     * interaction is needed. Note that the terminals will still be exposed to all extensions
     * as normal. The hidden terminals will not be restored when the workspace is next opened.
     */
    hideFromUser?: boolean;
    /**
     * Whether this terminal is not a terminal that the user directly created and uses, but rather
     * a terminal used to drive some VS Code feature.
     */
    isFeatureTerminal?: boolean;
    /**
     * Whether this terminal was created by an extension.
     */
    isExtensionOwnedTerminal?: boolean;
    /**
     * The icon for the terminal, used primarily in the terminal tab.
     */
    icon?: TerminalIcon;
    /**
     * The color ID to use for this terminal. If not specified it will use the default fallback
     */
    color?: string;
    /**
     * When a parent terminal is provided via API, the group needs
     * to find the index in order to place the child
     * directly to the right of its parent.
     */
    parentTerminalId?: number;
    /**
     * The dimensions for the instance as set by the user
     * or via Size to Content Width
     */
    fixedDimensions?: IFixedTerminalDimensions;
    /**
     * Opt-out of the default terminal persistence on restart and reload
     */
    isTransient?: boolean;
    /**
     * Attempt to force shell integration to be enabled by bypassing the {@link isFeatureTerminal}
     * equals false requirement.
     */
    forceShellIntegration?: boolean;
    /**
     * Create a terminal without shell integration even when it's enabled
     */
    ignoreShellIntegration?: boolean;
}
type WaitOnExitValue = boolean | string | ((exitCode: number) => string);
declare enum TerminalLocation {
    Panel = 1,
    Editor = 2
}
declare const enum TerminalLocationString {
    TerminalView = "view",
    Editor = "editor"
}
type TerminalIcon = ThemeIcon | URI | {
    light: URI;
    dark: URI;
};
/**
 * A set of options for the terminal process. These differ from the shell launch config in that they
 * are set internally to the terminal component, not from the outside.
 */
interface ITerminalProcessOptions {
    shellIntegration: {
        enabled: boolean;
        suggestEnabled: boolean;
        nonce: string;
    };
    windowsEnableConpty: boolean;
    environmentVariableCollections: ISerializableEnvironmentVariableCollections | undefined;
    workspaceFolder: IWorkspaceFolder | undefined;
}
interface ITerminalEnvironment {
    [key: string]: string | null | undefined;
}
interface ITerminalLaunchError {
    message: string;
    code?: number;
}
interface IProcessReadyEvent {
    pid: number;
    cwd: string;
    windowsPty: IProcessReadyWindowsPty | undefined;
}
interface IProcessReadyWindowsPty {
    /**
     * What pty emulation backend is being used.
     */
    backend: 'conpty' | 'winpty';
    /**
     * The Windows build version (eg. 19045)
     */
    buildNumber: number;
}
/**
 * An interface representing a raw terminal child process, this contains a subset of the
 * child_process.ChildProcess node.js interface.
 */
interface ITerminalChildProcess {
    /**
     * A unique identifier for the terminal process. Note that the uniqueness only applies to a
     * given pty service connection, IDs will be duplicated for remote and local terminals for
     * example. The ID will be 0 if it does not support reconnection.
     */
    id: number;
    /**
     * Whether the process should be persisted across reloads.
     */
    shouldPersist: boolean;
    onProcessData: Event<IProcessDataEvent | string>;
    onProcessReady: Event<IProcessReadyEvent>;
    onProcessReplayComplete?: Event<void>;
    onDidChangeProperty: Event<IProcessProperty<any>>;
    onProcessExit: Event<number | undefined>;
    onRestoreCommands?: Event<ISerializedCommandDetectionCapability>;
    /**
     * Starts the process.
     *
     * @returns undefined when the process was successfully started, otherwise an object containing
     * information on what went wrong.
     */
    start(): Promise<ITerminalLaunchError | {
        injectedArgs: string[];
    } | undefined>;
    /**
     * Detach the process from the UI and await reconnect.
     * @param forcePersist Whether to force the process to persist if it supports persistence.
     */
    detach?(forcePersist?: boolean): Promise<void>;
    /**
     * Frees the port and kills the process
     */
    freePortKillProcess?(port: string): Promise<{
        port: string;
        processId: string;
    }>;
    /**
     * Shutdown the terminal process.
     *
     * @param immediate When true the process will be killed immediately, otherwise the process will
     * be given some time to make sure no additional data comes through.
     */
    shutdown(immediate: boolean): void;
    input(data: string): void;
    processBinary(data: string): Promise<void>;
    resize(cols: number, rows: number): void;
    clearBuffer(): void | Promise<void>;
    /**
     * Acknowledge a data event has been parsed by the terminal, this is used to implement flow
     * control to ensure remote processes to not get too far ahead of the client and flood the
     * connection.
     * @param charCount The number of characters being acknowledged.
     */
    acknowledgeDataEvent(charCount: number): void;
    /**
     * Sets the unicode version for the process, this drives the size of some characters in the
     * xterm-headless instance.
     */
    setUnicodeVersion(version: '6' | '11'): Promise<void>;
    getInitialCwd(): Promise<string>;
    getCwd(): Promise<string>;
    refreshProperty<T extends ProcessPropertyType>(property: T): Promise<IProcessPropertyMap[T]>;
    updateProperty<T extends ProcessPropertyType>(property: T, value: IProcessPropertyMap[T]): Promise<void>;
}
interface IProcessDataEvent {
    data: string;
    trackCommit: boolean;
    /**
     * When trackCommit is set, this will be set to a promise that resolves when the data is parsed.
     */
    writePromise?: Promise<void>;
}
interface ITerminalDimensions {
    /**
     * The columns of the terminal.
     */
    cols: number;
    /**
     * The rows of the terminal.
     */
    rows: number;
}
interface ITerminalProfile {
    profileName: string;
    path: string;
    isDefault: boolean;
    /**
     * Whether the terminal profile contains a potentially unsafe {@link path}. For example, the path
     * `C:\Cygwin` is the default install for Cygwin on Windows, but it could be created by any
     * user in a multi-user environment. As such, we don't want to blindly present it as a profile
     * without a warning.
     */
    isUnsafePath?: boolean;
    /**
     * An additional unsafe path that must exist, for example a script that appears in {@link args}.
     */
    requiresUnsafePath?: string;
    isAutoDetected?: boolean;
    /**
     * Whether the profile path was found on the `$PATH` environment variable, if so it will be
     * cleaner to display this profile in the UI using only `basename(path)`.
     */
    isFromPath?: boolean;
    args?: string | string[] | undefined;
    env?: ITerminalEnvironment;
    overrideName?: boolean;
    color?: string;
    icon?: ThemeIcon | URI | {
        light: URI;
        dark: URI;
    };
}
interface ITerminalDimensionsOverride extends Readonly<ITerminalDimensions> {
    /**
     * indicate that xterm must receive these exact dimensions, even if they overflow the ui!
     */
    forceExactSize?: boolean;
}
declare const enum ProfileSource {
    GitBash = "Git Bash",
    Pwsh = "PowerShell"
}
interface IBaseUnresolvedTerminalProfile {
    args?: string | string[] | undefined;
    isAutoDetected?: boolean;
    overrideName?: boolean;
    icon?: string | ThemeIcon | URI | {
        light: URI;
        dark: URI;
    };
    color?: string;
    env?: ITerminalEnvironment;
    requiresPath?: string | ITerminalUnsafePath;
}
type OneOrN<T> = T | T[];
interface ITerminalUnsafePath {
    path: string;
    isUnsafe: true;
}
interface ITerminalExecutable extends IBaseUnresolvedTerminalProfile {
    path: OneOrN<string | ITerminalUnsafePath>;
}
interface ITerminalProfileSource extends IBaseUnresolvedTerminalProfile {
    source: ProfileSource;
}
interface ITerminalProfileContribution {
    title: string;
    id: string;
    icon?: URI | {
        light: URI;
        dark: URI;
    } | string;
    color?: string;
}
interface IExtensionTerminalProfile extends ITerminalProfileContribution {
    extensionIdentifier: string;
}
type ITerminalProfileObject = ITerminalExecutable | ITerminalProfileSource | IExtensionTerminalProfile | null;
interface IShellIntegration {
    readonly capabilities: ITerminalCapabilityStore;
    readonly status: ShellIntegrationStatus;
    readonly onDidChangeStatus: Event<ShellIntegrationStatus>;
    deserialize(serialized: ISerializedCommandDetectionCapability): void;
}
declare const enum ShellIntegrationStatus {
    /** No shell integration sequences have been encountered. */
    Off = 0,
    /** Final term shell integration sequences have been encountered. */
    FinalTerm = 1,
    /** VS Code shell integration sequences have been encountered. Supercedes FinalTerm. */
    VSCode = 2
}
declare enum TerminalExitReason {
    Unknown = 0,
    Shutdown = 1,
    Process = 2,
    User = 3,
    Extension = 4
}
interface ITerminalOutputMatch {
    regexMatch: RegExpMatchArray;
    outputLines: string[];
}
/**
 * A matcher that runs on a sub-section of a terminal command's output
 */
interface ITerminalOutputMatcher {
    /**
     * A string or regex to match against the unwrapped line. If this is a regex with the multiline
     * flag, it will scan an amount of lines equal to `\n` instances in the regex + 1.
     */
    lineMatcher: string | RegExp;
    /**
     * Which side of the output to anchor the {@link offset} and {@link length} against.
     */
    anchor: 'top' | 'bottom';
    /**
     * The number of rows above or below the {@link anchor} to start matching against.
     */
    offset: number;
    /**
     * The number of rows to match against, this should be as small as possible for performance
     * reasons. This is capped at 40.
     */
    length: number;
    /**
     * If multiple matches are expected - this will result in {@link outputLines} being returned
     * when there's a {@link regexMatch} from {@link offset} to {@link length}
     */
    multipleMatches?: boolean;
}
interface ITerminalBackend {
    readonly remoteAuthority: string | undefined;
    readonly isResponsive: boolean;
    /**
     * A promise that resolves when the backend is ready to be used, ie. after terminal persistence
     * has been actioned.
     */
    readonly whenReady: Promise<void>;
    /**
     * Signal to the backend that persistence has been actioned and is ready for use.
     */
    setReady(): void;
    /**
     * Fired when the ptyHost process becomes non-responsive, this should disable stdin for all
     * terminals using this pty host connection and mark them as disconnected.
     */
    onPtyHostUnresponsive: Event<void>;
    /**
     * Fired when the ptyHost process becomes responsive after being non-responsive. Allowing
     * previously disconnected terminals to reconnect.
     */
    onPtyHostResponsive: Event<void>;
    /**
     * Fired when the ptyHost has been restarted, this is used as a signal for listening terminals
     * that its pty has been lost and will remain disconnected.
     */
    onPtyHostRestart: Event<void>;
    onDidRequestDetach: Event<{
        requestId: number;
        workspaceId: string;
        instanceId: number;
    }>;
    attachToProcess(id: number): Promise<ITerminalChildProcess | undefined>;
    attachToRevivedProcess(id: number): Promise<ITerminalChildProcess | undefined>;
    listProcesses(): Promise<IProcessDetails[]>;
    getLatency(): Promise<IPtyHostLatencyMeasurement[]>;
    getDefaultSystemShell(osOverride?: OperatingSystem): Promise<string>;
    getProfiles(profiles: unknown, defaultProfile: unknown, includeDetectedProfiles?: boolean): Promise<ITerminalProfile[]>;
    getWslPath(original: string, direction: 'unix-to-win' | 'win-to-unix'): Promise<string>;
    getEnvironment(): Promise<IProcessEnvironment>;
    getShellEnvironment(): Promise<IProcessEnvironment | undefined>;
    setTerminalLayoutInfo(layoutInfo?: ITerminalsLayoutInfoById): Promise<void>;
    updateTitle(id: number, title: string, titleSource: TitleEventSource): Promise<void>;
    updateIcon(id: number, userInitiated: boolean, icon: TerminalIcon, color?: string): Promise<void>;
    getTerminalLayoutInfo(): Promise<ITerminalsLayoutInfo | undefined>;
    getPerformanceMarks(): Promise<PerformanceMark[]>;
    reduceConnectionGraceTime(): Promise<void>;
    requestDetachInstance(workspaceId: string, instanceId: number): Promise<IProcessDetails | undefined>;
    acceptDetachInstanceReply(requestId: number, persistentProcessId?: number): Promise<void>;
    persistTerminalState(): Promise<void>;
    createProcess(shellLaunchConfig: IShellLaunchConfig, cwd: string, cols: number, rows: number, unicodeVersion: '6' | '11', env: IProcessEnvironment, options: ITerminalProcessOptions, shouldPersist: boolean): Promise<ITerminalChildProcess>;
    restartPtyHost(): void;
}
declare const ITerminalLogService: ServiceIdentifier<ITerminalLogService>;
interface ITerminalLogService extends ILogService {
    /**
     * Similar to _serviceBrand but used to differentiate this service at compile time from
     * ILogService; ITerminalLogService is an ILogService, but ILogService is not an
     * ITerminalLogService.
     */
    readonly _logBrand: undefined;
}

export { type IBaseUnresolvedTerminalProfile, type IExtensionTerminalProfile, type IFixedTerminalDimensions, type IProcessDataEvent, type IProcessProperty, type IProcessPropertyMap, type IProcessReadyEvent, type IProcessReadyWindowsPty, type IPtyHostAttachTarget, type IPtyHostLatencyMeasurement, type IRawTerminalInstanceLayoutInfo, type IRawTerminalTabLayoutInfo, type IRawTerminalsLayoutInfo, type IReconnectionProperties, type IShellIntegration, type IShellLaunchConfig, type ITerminalBackend, type ITerminalChildProcess, type ITerminalDimensions, type ITerminalDimensionsOverride, type ITerminalEnvironment, type ITerminalExecutable, type ITerminalLaunchError, ITerminalLogService, type ITerminalOutputMatch, type ITerminalOutputMatcher, type ITerminalProcessOptions, type ITerminalProfile, type ITerminalProfileContribution, type ITerminalProfileObject, type ITerminalProfileSource, type ITerminalTabLayoutInfoById, type ITerminalUnsafePath, type ITerminalsLayoutInfo, type ITerminalsLayoutInfoById, PosixShellType, ProcessPropertyType, ProfileSource, ShellIntegrationStatus, TerminalExitReason, type TerminalIcon, TerminalLocation, TerminalLocationString, type TerminalShellType, type TerminalType, TitleEventSource, type WaitOnExitValue, WindowsShellType };
