import { fileURLToPath as __fileURLToPath } from 'url';
import { dirname as __pathDirname } from 'path';
const __filename = __fileURLToPath(import.meta.url);
const __dirname = __pathDirname(__filename);
import { join } from "path";
import { writeFileSync, existsSync, mkdirSync } from "fs";
import { execSync } from "child_process";
import { SweepStateWatcher } from "./state-watcher.js";
import { StatusBar } from "./status-bar.js";
import { TabInterceptor } from "./tab-interceptor.js";
const HOME = process.env["HOME"] || "/tmp";
const PENDING_FILE = join(HOME, ".stackmemory", "sweep-pending.json");
const ALT_SCREEN_ENTER = "\x1B[?1049h";
const ALT_SCREEN_EXIT = "\x1B[?1049l";
class PtyWrapper {
  config;
  stateWatcher;
  statusBar;
  tabInterceptor;
  currentPrediction = null;
  inAltScreen = false;
  ptyProcess = null;
  constructor(config = {}) {
    this.config = {
      claudeBin: config.claudeBin || this.findClaude(),
      claudeArgs: config.claudeArgs || [],
      stateFile: config.stateFile || join(HOME, ".stackmemory", "sweep-state.json")
    };
    this.stateWatcher = new SweepStateWatcher(this.config.stateFile);
    this.statusBar = new StatusBar();
    this.tabInterceptor = new TabInterceptor({
      onAccept: () => this.acceptPrediction(),
      onDismiss: () => this.dismissPrediction(),
      onPassthrough: (data) => this.ptyProcess?.write(data.toString("utf-8"))
    });
  }
  async start() {
    let pty;
    try {
      pty = await import("node-pty");
    } catch {
      throw new Error(
        "node-pty is required for the PTY wrapper.\nInstall with: npm install node-pty"
      );
    }
    const cols = process.stdout.columns || 80;
    const rows = process.stdout.rows || 24;
    const env = {};
    for (const [k, v] of Object.entries(process.env)) {
      if (v !== void 0) env[k] = v;
    }
    this.ptyProcess = pty.spawn(this.config.claudeBin, this.config.claudeArgs, {
      name: process.env["TERM"] || "xterm-256color",
      cols,
      rows: rows - 1,
      cwd: process.cwd(),
      env
    });
    if (process.stdin.isTTY) {
      process.stdin.setRawMode(true);
    }
    process.stdin.resume();
    this.ptyProcess.onData((data) => {
      if (data.includes(ALT_SCREEN_ENTER)) {
        this.inAltScreen = true;
        this.statusBar.hide();
      }
      if (data.includes(ALT_SCREEN_EXIT)) {
        this.inAltScreen = false;
      }
      process.stdout.write(data);
    });
    process.stdin.on("data", (data) => {
      this.tabInterceptor.process(data);
    });
    this.stateWatcher.on("loading", () => {
      if (!this.inAltScreen) {
        this.statusBar.showLoading();
      }
    });
    this.stateWatcher.on("prediction", (event) => {
      this.currentPrediction = event;
      this.tabInterceptor.setPredictionActive(true);
      if (!this.inAltScreen) {
        this.statusBar.show(
          event.prediction,
          event.file_path,
          event.latency_ms
        );
      }
    });
    this.stateWatcher.start();
    process.stdout.on("resize", () => {
      const newCols = process.stdout.columns || 80;
      const newRows = process.stdout.rows || 24;
      this.ptyProcess?.resize(newCols, newRows - 1);
      this.statusBar.resize(newRows, newCols);
    });
    this.ptyProcess.onExit(({ exitCode }) => {
      this.cleanup();
      process.exit(exitCode);
    });
    const onSignal = () => {
      this.cleanup();
      process.exit(0);
    };
    process.on("SIGINT", onSignal);
    process.on("SIGTERM", onSignal);
  }
  acceptPrediction() {
    if (!this.currentPrediction || !this.ptyProcess) return;
    const dir = join(HOME, ".stackmemory");
    if (!existsSync(dir)) {
      mkdirSync(dir, { recursive: true });
    }
    writeFileSync(
      PENDING_FILE,
      JSON.stringify(
        {
          file_path: this.currentPrediction.file_path,
          predicted_content: this.currentPrediction.prediction,
          timestamp: Date.now()
        },
        null,
        2
      )
    );
    const prompt = `Apply the Sweep prediction from ${PENDING_FILE}
`;
    this.ptyProcess.write(prompt);
    this.dismissPrediction();
  }
  dismissPrediction() {
    this.currentPrediction = null;
    this.tabInterceptor.setPredictionActive(false);
    this.statusBar.hide();
  }
  cleanup() {
    this.stateWatcher.stop();
    this.statusBar.hide();
    if (process.stdin.isTTY) {
      process.stdin.setRawMode(false);
    }
    process.stdin.pause();
  }
  findClaude() {
    try {
      const resolved = execSync("which claude", { encoding: "utf-8" }).trim();
      if (resolved) return resolved;
    } catch {
    }
    const candidates = [
      join(HOME, ".bun", "bin", "claude"),
      "/usr/local/bin/claude",
      "/opt/homebrew/bin/claude"
    ];
    for (const c of candidates) {
      if (existsSync(c)) return c;
    }
    return "claude";
  }
}
async function launchWrapper(config) {
  const wrapper = new PtyWrapper(config);
  await wrapper.start();
}
export {
  PtyWrapper,
  launchWrapper
};
//# sourceMappingURL=pty-wrapper.js.map
