import { RemoteFrameWidthClamp } from "./remote-frame-clamp.js";
let nextRemoteRendererId = 0;
function jsonValue(value) {
    if (value === undefined)
        return null;
    const encoded = JSON.stringify(value);
    return encoded === undefined ? null : JSON.parse(encoded);
}
class RemoteRenderer {
    constructor(runtime, requestRender) {
        this.componentId = `remote_renderer_${++nextRemoteRendererId}`;
        this.lines = ["Loading isolated renderer…"];
        this.width = 0;
        this.requestId = 0;
        this.appliedRequestId = 0;
        this.dirty = true;
        this.disposed = false;
        this.frameClamp = new RemoteFrameWidthClamp();
        this.runtime = runtime;
        this.requestRender = requestRender;
        this.unsubscribe = runtime.onEngineMessage((message) => {
            if (!("componentId" in message) || message.componentId !== this.componentId)
                return;
            if (message.type === "engine_custom_frame") {
                if (message.requestId < this.appliedRequestId)
                    return;
                this.appliedRequestId = message.requestId;
                this.lines = message.lines;
                this.requestRender();
            }
            else if (message.type === "engine_custom_invalidate") {
                this.markDirty();
            }
        });
    }
    render(width) {
        if (!this.disposed && (this.dirty || width !== this.width)) {
            this.width = width;
            this.dirty = false;
            this.runtime.sendEngineCommand(this.command(++this.requestId, width));
        }
        // The engine child re-renders asynchronously; until the fresh frame
        // arrives, the previous frame may be wrapped for an older terminal
        // width. Clamp so a resize never replays overflowing lines (pi-tui
        // crashes on any rendered line wider than the terminal).
        return this.frameClamp.clamp(this.lines, width);
    }
    invalidate() { this.markDirty(); }
    dispose() {
        if (this.disposed)
            return;
        this.disposed = true;
        this.unsubscribe();
        this.runtime.sendEngineCommand({ type: "engine_render_dispose", componentId: this.componentId });
    }
    changed() {
        this.markDirty();
        this.requestRender();
    }
    markDirty() { this.dirty = true; }
}
export class RemoteToolExecutionComponent extends RemoteRenderer {
    constructor(toolName, toolCallId, args, options, runtime, requestRender) {
        super(runtime, requestRender);
        this.executionStarted = false;
        this.argsComplete = false;
        this.isPartial = true;
        this.expanded = false;
        this.toolName = toolName;
        this.toolCallId = toolCallId;
        this.args = args;
        this.showImages = options.showImages ?? true;
        this.imageWidthCells = options.imageWidthCells ?? 60;
    }
    updateArgs(args) { this.args = args; this.changed(); }
    markExecutionStarted() { this.executionStarted = true; this.changed(); }
    setArgsComplete() { this.argsComplete = true; this.changed(); }
    updateResult(result, isPartial = false) {
        this.result = result;
        this.isPartial = isPartial;
        this.changed();
    }
    setExpanded(expanded) { this.expanded = expanded; this.changed(); }
    setShowImages(show) { this.showImages = show; this.changed(); }
    setImageWidthCells(width) { this.imageWidthCells = Math.max(1, Math.floor(width)); this.changed(); }
    command(requestId, width) {
        return {
            type: "engine_tool_render",
            componentId: this.componentId,
            requestId,
            width,
            toolName: this.toolName,
            toolCallId: this.toolCallId,
            args: jsonValue(this.args),
            result: this.result ? jsonValue(this.result) : undefined,
            executionStarted: this.executionStarted,
            argsComplete: this.argsComplete,
            isPartial: this.isPartial,
            expanded: this.expanded,
            showImages: this.showImages,
            imageWidthCells: this.imageWidthCells,
        };
    }
}
export class RemoteCustomMessageComponent extends RemoteRenderer {
    constructor(message, runtime, requestRender) {
        super(runtime, requestRender);
        this.expanded = false;
        this.message = message;
    }
    setExpanded(expanded) { this.expanded = expanded; this.changed(); }
    command(requestId, width) {
        return {
            type: "engine_message_render",
            componentId: this.componentId,
            requestId,
            width,
            message: jsonValue(this.message),
            expanded: this.expanded,
        };
    }
}
//# sourceMappingURL=remote-renderer.js.map