import { Renderable, RootRenderable } from "./Renderable.js";
import { DebugOverlayCorner, type CursorStyleOptions, type MousePointerStyle, type RenderContext, type TerminalCapabilities, type ThemeMode, type WidthMethod } from "./types.js";
import { RGBA, type ColorInput } from "./lib/RGBA.js";
import { OptimizedBuffer } from "./buffer.js";
import { type NativeBufferedOutput, type NativeRenderStats, type RendererHandle } from "./zig.js";
import { TerminalConsole, type ConsoleOptions } from "./console.js";
import { type MouseEventType, type RawMouseEvent, type ScrollInfo } from "./lib/parse.mouse.js";
import { Selection } from "./lib/selection.js";
import { type ClipboardTarget } from "./lib/clipboard.js";
import { EventEmitter } from "events";
import { KeyHandler, InternalKeyHandler } from "./lib/KeyHandler.js";
import { type EditBufferRenderable } from "./renderables/EditBufferRenderable.js";
import { type TerminalColors, type GetPaletteOptions } from "./lib/terminal-palette.js";
import { type Clock } from "./lib/clock.js";
export interface CliRendererConfig {
    stdin?: NodeJS.ReadStream;
    stdout?: NodeJS.WriteStream;
    width?: number;
    height?: number;
    remote?: boolean;
    bufferedOutput?: NativeBufferedOutput;
    exitOnCtrlC?: boolean;
    exitSignals?: NodeJS.Signals[];
    clearOnShutdown?: boolean;
    forwardEnvKeys?: string[];
    debounceDelay?: number;
    targetFps?: number;
    maxFps?: number;
    memorySnapshotInterval?: number;
    useThread?: boolean;
    gatherStats?: boolean;
    maxStatSamples?: number;
    consoleOptions?: Omit<ConsoleOptions, "clock">;
    postProcessFns?: ((buffer: OptimizedBuffer, deltaTime: number) => void)[];
    enableMouseMovement?: boolean;
    useMouse?: boolean;
    autoFocus?: boolean;
    screenMode?: ScreenMode;
    footerHeight?: number;
    externalOutputMode?: ExternalOutputMode;
    consoleMode?: ConsoleMode;
    useKittyKeyboard?: KittyKeyboardOptions | null;
    backgroundColor?: ColorInput;
    openConsoleOnError?: boolean;
    prependInputHandlers?: ((sequence: string) => boolean)[];
    stdinParserMaxBufferBytes?: number;
    clock?: Clock;
    onDestroy?: () => void;
}
export type ScreenMode = "alternate-screen" | "main-screen" | "split-footer";
export type ExternalOutputMode = "capture-stdout" | "passthrough";
export interface CliRendererExternalOutputEvent {
    snapshot: OptimizedBuffer;
    rowColumns: number;
    startOnNewLine: boolean;
    trailingNewline: boolean;
}
export type ConsoleMode = "console-overlay" | "disabled";
export type PixelResolution = {
    width: number;
    height: number;
};
export interface CliRendererStats extends NativeRenderStats {
    fps: number;
    frameCount: number;
    frameTimes: number[];
    averageFrameTime: number;
    minFrameTime: number;
    maxFrameTime: number;
    frameCallbackTime: number;
}
export interface CliRendererFrameEvent {
    frameId: number;
}
export interface RendererSchedulerState {
    isRunning: boolean;
    isRendering: boolean;
    hasScheduledRender: boolean;
}
export interface ScrollbackRenderContext {
    width: number;
    widthMethod: WidthMethod;
    tailColumn: number;
    renderContext: RenderContext;
}
export interface ScrollbackSnapshot {
    root: Renderable;
    width?: number;
    height?: number;
    rowColumns?: number;
    startOnNewLine?: boolean;
    trailingNewline?: boolean;
    teardown?: () => void;
}
export type ScrollbackWriter = (ctx: ScrollbackRenderContext) => ScrollbackSnapshot;
export interface ScrollbackSurfaceOptions {
    startOnNewLine?: boolean;
}
export interface ScrollbackSurfaceCommitOptions {
    rowColumns?: number;
    trailingNewline?: boolean;
}
export interface ScrollbackSurface {
    readonly renderContext: RenderContext;
    readonly root: Renderable;
    readonly width: number;
    readonly height: number;
    readonly isDestroyed: boolean;
    render(): void;
    settle(timeoutMs?: number): Promise<void>;
    commitRows(startRow: number, endRowExclusive: number, options?: ScrollbackSurfaceCommitOptions): void;
    destroy(): void;
}
export interface SplitFooterReplayResetOptions {
    clearSavedLines?: boolean;
}
/**
 * Kitty Keyboard Protocol configuration options
 * See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/#progressive-enhancement
 */
export interface KittyKeyboardOptions {
    /** Disambiguate escape codes (fixes ESC timing, alt+key ambiguity, ctrl+c as event). Default: true */
    disambiguate?: boolean;
    /** Report alternate keys (numpad, shifted, base layout) for cross-keyboard shortcuts. Default: true */
    alternateKeys?: boolean;
    /** Report event types (press/repeat/release). Default: false */
    events?: boolean;
    /** Report all keys as escape codes. Default: false */
    allKeysAsEscapes?: boolean;
    /** Report text associated with key events. Default: false */
    reportText?: boolean;
}
/**
 * Build kitty keyboard protocol flags based on configuration
 * @param config Kitty keyboard configuration object (null/undefined = disabled)
 * @returns The combined flags value (0 = disabled, >0 = enabled)
 * @internal Exported for testing
 */
export declare function buildKittyKeyboardFlags(config: KittyKeyboardOptions | null | undefined): number;
export declare class MouseEvent {
    readonly type: MouseEventType;
    readonly button: number;
    readonly x: number;
    readonly y: number;
    readonly source?: Renderable;
    readonly modifiers: {
        shift: boolean;
        alt: boolean;
        ctrl: boolean;
    };
    readonly scroll?: ScrollInfo;
    readonly target: Renderable | null;
    readonly isDragging?: boolean;
    private _propagationStopped;
    private _defaultPrevented;
    get propagationStopped(): boolean;
    get defaultPrevented(): boolean;
    constructor(target: Renderable | null, attributes: RawMouseEvent & {
        source?: Renderable;
        isDragging?: boolean;
    });
    stopPropagation(): void;
    preventDefault(): void;
}
export declare enum MouseButton {
    LEFT = 0,
    MIDDLE = 1,
    RIGHT = 2,
    WHEEL_UP = 4,
    WHEEL_DOWN = 5
}
/**
 * Create a CLI renderer and run its async terminal setup. The constructor
 * owns all stream and backend decisions; this factory only layers on the
 * `--delay-start` flag and the `await setupTerminal()` convenience.
 */
export declare function createCliRenderer(config?: CliRendererConfig): Promise<CliRenderer>;
export declare enum CliRenderEvents {
    RESIZE = "resize",
    FRAME = "frame",
    EXTERNAL_OUTPUT = "external_output",
    FOCUS = "focus",
    BLUR = "blur",
    FOCUSED_RENDERABLE = "focused_renderable",
    FOCUSED_EDITOR = "focused_editor",
    THEME_MODE = "theme_mode",
    PALETTE = "palette",
    CAPABILITIES = "capabilities",
    SELECTION = "selection",
    DEBUG_OVERLAY_TOGGLE = "debugOverlay:toggle",
    DESTROY = "destroy",
    MEMORY_SNAPSHOT = "memory:snapshot"
}
export declare enum RendererControlState {
    IDLE = "idle",
    AUTO_STARTED = "auto_started",
    EXPLICIT_STARTED = "explicit_started",
    EXPLICIT_PAUSED = "explicit_paused",
    EXPLICIT_SUSPENDED = "explicit_suspended",
    EXPLICIT_STOPPED = "explicit_stopped"
}
export declare class CliRenderer extends EventEmitter implements RenderContext {
    private static animationFrameId;
    private lib;
    rendererPtr: RendererHandle;
    stdin: NodeJS.ReadStream;
    private stdout;
    private exitOnCtrlC;
    private exitSignals;
    private _exitListenersAdded;
    private _isDestroyed;
    private _destroyPending;
    private _destroyFinalized;
    private _destroyCleanupPrepared;
    private _streamLeaseAcquired;
    nextRenderBuffer: OptimizedBuffer;
    currentRenderBuffer: OptimizedBuffer;
    private _isRunning;
    private _targetFps;
    private _maxFps;
    private automaticMemorySnapshot;
    private memorySnapshotInterval;
    private memorySnapshotTimer;
    private lastMemorySnapshot;
    readonly root: RootRenderable;
    width: number;
    height: number;
    private _useThread;
    private gatherStats;
    private frameTimes;
    private maxStatSamples;
    private postProcessFns;
    private backgroundColor;
    private waitingForPixelResolution;
    private readonly clock;
    private rendering;
    private renderingNative;
    private renderTimeout;
    private lastTime;
    private frameCount;
    private _frameId;
    private lastFpsTime;
    private currentFps;
    private targetFrameTime;
    private minTargetFrameTime;
    private immediateRerenderRequested;
    private updateScheduled;
    private liveRequestCounter;
    private _controlState;
    private frameCallbacks;
    private renderStats;
    debugOverlay: {
        enabled: any;
        corner: DebugOverlayCorner;
    };
    private _console;
    private _resolution;
    private _keyHandler;
    private stdinParser;
    private readonly oscSubscribers;
    private hasLoggedStdinParserError;
    private animationRequest;
    private resizeTimeoutId;
    private capabilityTimeoutId;
    private xtVersionWaiters;
    private splitStartupSeedTimeoutId;
    private pendingSplitStartupCursorSeed;
    private resizeDebounceDelay;
    private enableMouseMovement;
    private _useMouse;
    private autoFocus;
    private _screenMode;
    private _footerHeight;
    private _externalOutputMode;
    private clearOnShutdown;
    private _suspendedMouseEnabled;
    private _previousControlState;
    private pendingSuspendedTerminalSetup;
    private suspendedNonAltSurfacePreserved;
    private capturedRenderable?;
    private lastOverRenderableNum;
    private lastOverRenderable?;
    private currentSelection;
    private selectionContainers;
    private clipboard;
    private _splitHeight;
    private renderOffset;
    private splitTailColumn;
    private pendingSplitFooterTransition;
    private forceFullRepaintRequested;
    private readonly maxSplitCommitsPerFrame;
    private _terminalWidth;
    private _terminalHeight;
    private _terminalIsSetup;
    private externalOutputQueue;
    private pendingExternalOutputMode;
    private realStdoutWrite;
    private _useConsole;
    private sigwinchHandler;
    private _capabilities;
    private _latestPointer;
    private _hasPointer;
    private _lastPointerModifiers;
    private _currentMousePointerStyle;
    private _currentFocusedRenderable;
    private lifecyclePasses;
    private _openConsoleOnError;
    private _paletteDetector;
    private _paletteCache;
    private _paletteDetectionPromise;
    private _paletteDetectionSize;
    private _paletteEpoch;
    private _nativePaletteSignature;
    private _emittedPaletteSignature;
    private _palettePublishGeneration;
    private _onDestroy?;
    private themeModeState;
    private _terminalFocusState;
    private sequenceHandlers;
    private prependedInputHandlers;
    private shouldRestoreModesOnNextFocus;
    private themeModeHandler;
    private idleResolvers;
    private _debugInputs;
    private _debugModeEnabled;
    private handleError;
    private dumpOutputCache;
    private exitHandler;
    private warningHandler;
    private readonly _usesProcessStdout;
    private _feed;
    private _detachFeed;
    private _detachFeedError;
    private feedIdleRenderScheduled;
    private ordinaryFrameWaitingForFeed;
    private ordinaryFrameWaitControlState;
    get controlState(): RendererControlState;
    /**
     * Construct a renderer over the given streams.
     *
     * If `stdout` is not `process.stdout`, a `NativeSpanFeed` is allocated
     * internally and rendered bytes are piped through it to `stdout` unless
     * `bufferedOutput: "memory"` is set. Prefer `createCliRenderer` for the async
     * `setupTerminal` convenience.
     *
     * Construction side effects (observable before the constructor returns):
     *   - Acquires exclusive ownership of the given stdin/stdout streams
     *   - Allocates a `NativeSpanFeed` (for non-process stdout unless bufferedOutput is "memory")
     *   - Calls `lib.createRenderer` → native Zig allocation
     *   - Registers in the process-wide `rendererTracker`
     *   - Adds `process.on(...)` listeners for SIGWINCH (process.stdout only),
     *     "warning", "uncaughtException", "unhandledRejection", "beforeExit",
     *     plus the configured `exitSignals`
     *   - Replaces `global.requestAnimationFrame` with the renderer's impl
     *   - When `setupTerminal()` is called, it will put `stdin` in raw mode and
     *     call `stdin.resume()`
     *
     * Some late constructor side effects are not rolled back if construction
     * throws partway; production callers should use `createCliRenderer`, which
     * wraps `setupTerminal()` in a try/catch that calls `destroy()` on failure.
     */
    constructor(stdin: NodeJS.ReadStream, stdout: NodeJS.WriteStream, width: number, height: number, config?: CliRendererConfig);
    private addExitListeners;
    private removeExitListeners;
    get isDestroyed(): boolean;
    registerLifecyclePass(renderable: Renderable): void;
    unregisterLifecyclePass(renderable: Renderable): void;
    getLifecyclePasses(): Set<Renderable>;
    get currentFocusedRenderable(): Renderable | null;
    get currentFocusedEditor(): EditBufferRenderable | null;
    private normalizeClockTime;
    private getElapsedMs;
    focusRenderable(renderable: Renderable): void;
    blurRenderable(renderable: Renderable): void;
    private setCapturedRenderable;
    addToHitGrid(x: number, y: number, width: number, height: number, id: number): void;
    pushHitGridScissorRect(x: number, y: number, width: number, height: number): void;
    popHitGridScissorRect(): void;
    clearHitGridScissorRects(): void;
    get widthMethod(): WidthMethod;
    get frameId(): number;
    private writeOut;
    private scheduleRenderAfterFeedIdle;
    private handleNativeRenderRejection;
    private reportNativeRenderFailure;
    private scheduleRenderTimer;
    private scheduleRenderAfterBackpressure;
    requestRender(): void;
    private activateFrame;
    get consoleMode(): ConsoleMode;
    set consoleMode(mode: ConsoleMode);
    get isRunning(): boolean;
    private isIdleNow;
    private resolveIdleIfNeeded;
    idle(): Promise<void>;
    getSchedulerState(): RendererSchedulerState;
    get resolution(): PixelResolution | null;
    get console(): TerminalConsole;
    get keyInput(): KeyHandler;
    get _internalKeyInput(): InternalKeyHandler;
    get terminalWidth(): number;
    get terminalHeight(): number;
    get useThread(): boolean;
    get targetFps(): number;
    set targetFps(targetFps: number);
    get maxFps(): number;
    set maxFps(maxFps: number);
    get useMouse(): boolean;
    set useMouse(useMouse: boolean);
    get screenMode(): ScreenMode;
    set screenMode(mode: ScreenMode);
    get footerHeight(): number;
    set footerHeight(footerHeight: number);
    get externalOutputMode(): ExternalOutputMode;
    set externalOutputMode(mode: ExternalOutputMode);
    private applyExternalOutputMode;
    private afterExternalOutputModeChanged;
    private applyPendingExternalOutputModeIfReady;
    private flushPendingSplitOutputBeforeLeavingSplitFooter;
    get liveRequestCount(): number;
    get currentControlState(): string;
    get capabilities(): TerminalCapabilities | null;
    triggerNotification(message: string, title?: string): boolean;
    get themeMode(): ThemeMode | null;
    waitForThemeMode(timeoutMs?: number): Promise<ThemeMode | null>;
    getDebugInputs(): Array<{
        timestamp: string;
        sequence: string;
    }>;
    get useKittyKeyboard(): boolean;
    set useKittyKeyboard(use: boolean);
    createScrollbackSurface(options?: ScrollbackSurfaceOptions): ScrollbackSurface;
    writeToScrollback(write: ScrollbackWriter): void;
    resetSplitFooterForReplay(options?: SplitFooterReplayResetOptions): void;
    private getSnapshotWidth;
    private getSnapshotHeight;
    private getSnapshotRowWidths;
    private advanceSplitTailColumn;
    private getSplitTailColumnAfterCommit;
    private recordSplitCommit;
    private getPendingSplitTailColumn;
    private enqueueRenderedScrollbackCommit;
    private enqueueSplitCommit;
    private createStdoutSnapshotCommit;
    private splitStdoutRows;
    private createStdoutSnapshotCommits;
    private flushPendingSplitCommits;
    private interceptStdoutWrite;
    private getSplitPinnedRenderOffset;
    private getSplitCursorSeedRows;
    private isSplitCursorSeedFrameBlocked;
    private canFlushSplitOutputBeforeTransition;
    private clearSplitStartupCursorSeed;
    private abortSplitStartupCursorSeed;
    private flushPendingSplitOutputBeforeTransition;
    private resetSplitScrollback;
    private syncSplitScrollback;
    private getSplitOutputOffset;
    private clearPendingSplitFooterTransition;
    private setPendingSplitFooterTransition;
    private syncSplitFooterState;
    private clearStaleSplitSurfaceRows;
    private applyScreenMode;
    private flushStdoutCache;
    private enableMouse;
    private disableMouse;
    enableKittyKeyboard(flags?: number): void;
    disableKittyKeyboard(): void;
    set useThread(useThread: boolean);
    setupTerminal(): Promise<void>;
    private stdinListener;
    addInputHandler(handler: (sequence: string) => boolean): void;
    prependInputHandler(handler: (sequence: string) => boolean): void;
    removeInputHandler(handler: (sequence: string) => boolean): void;
    private updateStdinParserProtocolContext;
    subscribeOsc(handler: (sequence: string) => void): () => void;
    private processCapabilitySequence;
    private capabilityHandler;
    private focusHandler;
    private dispatchSequenceHandlers;
    private drainStdinParser;
    private handleStdinEvent;
    private handleStdinParserFailure;
    private setupInput;
    private dispatchMouseEvent;
    private processSingleMouseEvent;
    /**
     * Recheck hover state after hit grid changes.
     * Called after render when native code detects the hit grid changed.
     * Fires out/over events if the element under the cursor changed.
     */
    private recheckHoverState;
    setMousePointer(style: MousePointerStyle): void;
    hitTest(x: number, y: number): number;
    private takeMemorySnapshot;
    private startMemorySnapshotTimer;
    private stopMemorySnapshotTimer;
    setMemorySnapshotInterval(interval: number): void;
    private handleResize;
    private queryPixelResolution;
    private processResize;
    /**
     * Programmatically resize the renderer to new dimensions.
     *
     * Use this for externally-driven resize events — for example, an SSH
     * `window-change` signal or a test harness simulating a terminal resize.
     * When the renderer is attached to `process.stdout`, `SIGWINCH` is handled
     * automatically and callers do not need this method.
     */
    resize(width: number, height: number): void;
    setBackgroundColor(color: ColorInput): void;
    toggleDebugOverlay(): void;
    configureDebugOverlay(options: {
        enabled?: boolean;
        corner?: DebugOverlayCorner;
    }): void;
    setTerminalTitle(title: string): void;
    /**
     * Reset the terminal background color to its default via OSC 111.
     * Called automatically by destroy() and suspend(), but exposed for
     * consumers that need explicit control (e.g. before SIGTSTP).
     */
    resetTerminalBgColor(): void;
    copyToClipboardOSC52(text: string, target?: ClipboardTarget): boolean;
    clearClipboardOSC52(target?: ClipboardTarget): boolean;
    isOsc52Supported(): boolean;
    dumpHitGrid(): void;
    dumpBuffers(timestamp?: number): void;
    dumpOutputBuffer(timestamp?: number): void;
    static setCursorPosition(renderer: CliRenderer, x: number, y: number, visible?: boolean): void;
    static setCursorStyle(renderer: CliRenderer, options: CursorStyleOptions): void;
    static setCursorColor(renderer: CliRenderer, color: RGBA): void;
    setCursorPosition(x: number, y: number, visible?: boolean): void;
    setCursorStyle(options: CursorStyleOptions): void;
    setCursorColor(color: RGBA): void;
    getCursorState(): import("./zig.js").CursorState;
    addPostProcessFn(processFn: (buffer: OptimizedBuffer, deltaTime: number) => void): void;
    removePostProcessFn(processFn: (buffer: OptimizedBuffer, deltaTime: number) => void): void;
    clearPostProcessFns(): void;
    setFrameCallback(callback: (deltaTime: number) => Promise<void>): void;
    removeFrameCallback(callback: (deltaTime: number) => Promise<void>): void;
    clearFrameCallbacks(): void;
    requestLive(): void;
    dropLive(): void;
    start(): void;
    auto(): void;
    private internalStart;
    pause(): void;
    suspend(): void;
    resume(): void;
    private internalPause;
    stop(): void;
    private internalStop;
    destroy(): void;
    private cleanupBeforeDestroy;
    private prepareDestroyDuringRender;
    private finalizeDestroy;
    private startRenderLoop;
    private loop;
    intermediateRender(): void;
    private renderNative;
    private collectStatSample;
    getNativeStats(): NativeRenderStats;
    getStats(): CliRendererStats;
    resetStats(): void;
    setGatherStats(enabled: boolean): void;
    getSelection(): Selection | null;
    get hasSelection(): boolean;
    getSelectionContainer(): Renderable | null;
    clearSelection(): void;
    /**
     * Start a new selection at the given coordinates.
     * Used by both mouse and keyboard selection.
     */
    startSelection(renderable: Renderable, x: number, y: number): void;
    updateSelection(currentRenderable: Renderable | undefined, x: number, y: number, options?: {
        finishDragging?: boolean;
    }): void;
    requestSelectionUpdate(): void;
    private isWithinContainer;
    private finishSelection;
    private notifySelectablesOfSelectionChange;
    private walkSelectableRenderables;
    get paletteDetectionStatus(): "idle" | "detecting" | "cached";
    private getCachedPaletteBySize;
    private ensurePaletteDetector;
    private syncNativePaletteState;
    private emitPaletteChange;
    private resolveXtVersionWaiters;
    private waitForXtVersion;
    private shouldSyncNativePaletteState;
    private refreshPalette;
    clearPaletteCache(): void;
    /**
     * Detects the terminal's color palette
     *
     * @returns Promise resolving to TerminalColors object containing palette and special colors
     * @throws Error if renderer is suspended
     */
    getPalette(options?: GetPaletteOptions): Promise<TerminalColors>;
}
