// @bun
import {
  ANSI,
  CliRenderer,
  TreeSitterClient,
  resolveRenderLib
} from "./index-n8nbvvhk.js";

// src/testing/mock-keys.ts
var KeyCodes = {
  RETURN: "\r",
  LINEFEED: `
`,
  TAB: "\t",
  BACKSPACE: "\b",
  DELETE: "\x1B[3~",
  HOME: "\x1B[H",
  END: "\x1B[F",
  ESCAPE: "\x1B",
  ARROW_UP: "\x1B[A",
  ARROW_DOWN: "\x1B[B",
  ARROW_RIGHT: "\x1B[C",
  ARROW_LEFT: "\x1B[D",
  F1: "\x1BOP",
  F2: "\x1BOQ",
  F3: "\x1BOR",
  F4: "\x1BOS",
  F5: "\x1B[15~",
  F6: "\x1B[17~",
  F7: "\x1B[18~",
  F8: "\x1B[19~",
  F9: "\x1B[20~",
  F10: "\x1B[21~",
  F11: "\x1B[23~",
  F12: "\x1B[24~"
};
function createMockKeys(renderer) {
  const pressKeys = async (keys, delayMs = 0) => {
    for (const key of keys) {
      let keyCode;
      if (typeof key === "string") {
        if (key in KeyCodes) {
          keyCode = KeyCodes[key];
        } else {
          keyCode = key;
        }
      } else {
        keyCode = KeyCodes[key];
        if (!keyCode) {
          throw new Error(`Unknown key: ${key}`);
        }
      }
      renderer.stdin.emit("data", Buffer.from(keyCode));
      if (delayMs > 0) {
        await new Promise((resolve) => setTimeout(resolve, delayMs));
      }
    }
  };
  const pressKey = (key, modifiers) => {
    let keyCode;
    if (typeof key === "string") {
      if (key in KeyCodes) {
        keyCode = KeyCodes[key];
      } else {
        keyCode = key;
      }
    } else {
      keyCode = KeyCodes[key];
      if (!keyCode) {
        throw new Error(`Unknown key: ${key}`);
      }
    }
    if (modifiers) {
      if (keyCode.startsWith("\x1B[") && keyCode.length > 2) {
        const modifier = 1 + (modifiers.shift ? 1 : 0) + (modifiers.meta ? 2 : 0) + (modifiers.ctrl ? 4 : 0);
        if (modifier > 1) {
          const ending = keyCode.slice(-1);
          keyCode = `\x1B[1;${modifier}${ending}`;
        }
      } else if (keyCode.length === 1) {
        let char = keyCode;
        if (modifiers.ctrl) {
          if (char >= "a" && char <= "z") {
            keyCode = String.fromCharCode(char.charCodeAt(0) - 96);
          } else if (char >= "A" && char <= "Z") {
            keyCode = String.fromCharCode(char.charCodeAt(0) - 64);
          }
          if (modifiers.meta) {
            keyCode = `\x1B${keyCode}`;
          }
        } else {
          if (modifiers.shift && char >= "a" && char <= "z") {
            char = char.toUpperCase();
          }
          if (modifiers.meta) {
            keyCode = `\x1B${char}`;
          } else {
            keyCode = char;
          }
        }
      } else if (modifiers.meta && !keyCode.startsWith("\x1B")) {
        keyCode = `\x1B${keyCode}`;
      }
    }
    renderer.stdin.emit("data", Buffer.from(keyCode));
  };
  const typeText = async (text, delayMs = 0) => {
    const keys = text.split("");
    await pressKeys(keys, delayMs);
  };
  const pressReturn = (modifiers) => {
    pressKey(KeyCodes.RETURN, modifiers);
  };
  const pressEscape = (modifiers) => {
    pressKey(KeyCodes.ESCAPE, modifiers);
  };
  const pressTab = (modifiers) => {
    pressKey(KeyCodes.TAB, modifiers);
  };
  const pressBackspace = (modifiers) => {
    pressKey(KeyCodes.BACKSPACE, modifiers);
  };
  const pressArrow = (direction, modifiers) => {
    const keyMap = {
      up: KeyCodes.ARROW_UP,
      down: KeyCodes.ARROW_DOWN,
      left: KeyCodes.ARROW_LEFT,
      right: KeyCodes.ARROW_RIGHT
    };
    pressKey(keyMap[direction], modifiers);
  };
  const pressCtrlC = () => {
    pressKey("c", { ctrl: true });
  };
  const pasteBracketedText = (text) => {
    return pressKeys([ANSI.bracketedPasteStart, text, ANSI.bracketedPasteEnd]);
  };
  return {
    pressKeys,
    pressKey,
    typeText,
    pressEnter: pressReturn,
    pressEscape,
    pressTab,
    pressBackspace,
    pressArrow,
    pressCtrlC,
    pasteBracketedText
  };
}

// src/testing/mock-mouse.ts
var MouseButtons = {
  LEFT: 0,
  MIDDLE: 1,
  RIGHT: 2,
  WHEEL_UP: 64,
  WHEEL_DOWN: 65,
  WHEEL_LEFT: 66,
  WHEEL_RIGHT: 67
};
function createMockMouse(renderer) {
  let currentPosition = { x: 0, y: 0 };
  let buttonsPressed = new Set;
  const generateMouseEvent = (type, x, y, button = MouseButtons.LEFT, modifiers = {}) => {
    let buttonCode = button;
    if (modifiers.shift)
      buttonCode |= 4;
    if (modifiers.alt)
      buttonCode |= 8;
    if (modifiers.ctrl)
      buttonCode |= 16;
    switch (type) {
      case "move":
        buttonCode = 32 | 3;
        if (modifiers.shift)
          buttonCode |= 4;
        if (modifiers.alt)
          buttonCode |= 8;
        if (modifiers.ctrl)
          buttonCode |= 16;
        break;
      case "drag":
        buttonCode = (buttonsPressed.size > 0 ? Array.from(buttonsPressed)[0] : button) | 32;
        if (modifiers.shift)
          buttonCode |= 4;
        if (modifiers.alt)
          buttonCode |= 8;
        if (modifiers.ctrl)
          buttonCode |= 16;
        break;
      case "scroll":
        break;
    }
    const ansiX = x + 1;
    const ansiY = y + 1;
    let pressRelease = "M";
    if (type === "up" || type === "move" || type === "drag") {
      pressRelease = "m";
    }
    return `\x1B[<${buttonCode};${ansiX};${ansiY}${pressRelease}`;
  };
  const emitMouseEvent = async (type, x, y, button = MouseButtons.LEFT, options = {}) => {
    const { modifiers = {}, delayMs = 0 } = options;
    const eventSequence = generateMouseEvent(type, x, y, button, modifiers);
    renderer.stdin.emit("data", Buffer.from(eventSequence));
    currentPosition = { x, y };
    if (type === "down" && button < 64) {
      buttonsPressed.add(button);
    } else if (type === "up") {
      buttonsPressed.delete(button);
    }
    if (delayMs > 0) {
      await new Promise((resolve) => setTimeout(resolve, delayMs));
    }
  };
  const moveTo = async (x, y, options = {}) => {
    const { button = MouseButtons.LEFT, delayMs = 0, modifiers = {} } = options;
    if (buttonsPressed.size > 0) {
      await emitMouseEvent("drag", x, y, Array.from(buttonsPressed)[0], { modifiers, delayMs });
    } else {
      await emitMouseEvent("move", x, y, button, { modifiers, delayMs });
    }
    currentPosition = { x, y };
  };
  const click = async (x, y, button = MouseButtons.LEFT, options = {}) => {
    const { delayMs = 10, modifiers = {} } = options;
    await emitMouseEvent("down", x, y, button, { modifiers, delayMs });
    await new Promise((resolve) => setTimeout(resolve, delayMs));
    await emitMouseEvent("up", x, y, button, { modifiers, delayMs });
  };
  const doubleClick = async (x, y, button = MouseButtons.LEFT, options = {}) => {
    const { delayMs = 10, modifiers = {} } = options;
    await click(x, y, button, { modifiers, delayMs });
    await new Promise((resolve) => setTimeout(resolve, delayMs));
    await click(x, y, button, { modifiers, delayMs });
  };
  const pressDown = async (x, y, button = MouseButtons.LEFT, options = {}) => {
    const { modifiers = {}, delayMs = 0 } = options;
    await emitMouseEvent("down", x, y, button, { modifiers, delayMs });
  };
  const release = async (x, y, button = MouseButtons.LEFT, options = {}) => {
    const { modifiers = {}, delayMs = 0 } = options;
    await emitMouseEvent("up", x, y, button, { modifiers, delayMs });
  };
  const drag = async (startX, startY, endX, endY, button = MouseButtons.LEFT, options = {}) => {
    const { delayMs = 10, modifiers = {} } = options;
    await pressDown(startX, startY, button, { modifiers });
    const steps = 5;
    const dx = (endX - startX) / steps;
    const dy = (endY - startY) / steps;
    for (let i = 1;i <= steps; i++) {
      const currentX = Math.round(startX + dx * i);
      const currentY = Math.round(startY + dy * i);
      await emitMouseEvent("drag", currentX, currentY, button, { modifiers, delayMs });
    }
    await release(endX, endY, button, { modifiers });
  };
  const scroll = async (x, y, direction, options = {}) => {
    const { modifiers = {}, delayMs = 0 } = options;
    let button;
    switch (direction) {
      case "up":
        button = MouseButtons.WHEEL_UP;
        break;
      case "down":
        button = MouseButtons.WHEEL_DOWN;
        break;
      case "left":
        button = MouseButtons.WHEEL_LEFT;
        break;
      case "right":
        button = MouseButtons.WHEEL_RIGHT;
        break;
    }
    await emitMouseEvent("scroll", x, y, button, { modifiers, delayMs });
  };
  const getCurrentPosition = () => {
    return { ...currentPosition };
  };
  const getPressedButtons = () => {
    return Array.from(buttonsPressed);
  };
  return {
    moveTo,
    click,
    doubleClick,
    pressDown,
    release,
    drag,
    scroll,
    getCurrentPosition,
    getPressedButtons,
    emitMouseEvent
  };
}

// src/testing/test-renderer.ts
var decoder = new TextDecoder;
async function createTestRenderer(options) {
  process.env.OTUI_USE_CONSOLE = "false";
  const renderer = await setupTestRenderer({
    ...options,
    useAlternateScreen: false,
    useConsole: false
  });
  renderer.disableStdoutInterception();
  const mockInput = createMockKeys(renderer);
  const mockMouse = createMockMouse(renderer);
  const renderOnce = async () => {
    await renderer.loop();
  };
  return {
    renderer,
    mockInput,
    mockMouse,
    renderOnce,
    captureCharFrame: () => {
      const currentBuffer = renderer.currentRenderBuffer;
      const frameBytes = currentBuffer.getRealCharBytes(true);
      return decoder.decode(frameBytes);
    },
    resize: (width, height) => {
      renderer.processResize(width, height);
    }
  };
}
async function setupTestRenderer(config) {
  const stdin = config.stdin || process.stdin;
  const stdout = config.stdout || process.stdout;
  const width = config.width || stdout.columns || 80;
  const height = config.height || stdout.rows || 24;
  const renderHeight = config.experimental_splitHeight && config.experimental_splitHeight > 0 ? config.experimental_splitHeight : height;
  const ziglib = resolveRenderLib();
  const rendererPtr = ziglib.createRenderer(width, renderHeight, { testing: true });
  if (!rendererPtr) {
    throw new Error("Failed to create test renderer");
  }
  if (config.useThread === undefined) {
    config.useThread = true;
  }
  if (process.platform === "linux") {
    config.useThread = false;
  }
  ziglib.setUseThread(rendererPtr, config.useThread);
  const renderer = new CliRenderer(ziglib, rendererPtr, stdin, stdout, width, height, config);
  return renderer;
}
// src/testing/mock-tree-sitter-client.ts
class MockTreeSitterClient extends TreeSitterClient {
  _highlightPromises = [];
  _mockResult = { highlights: [] };
  constructor() {
    super({ dataPath: "/tmp/mock" });
  }
  async highlightOnce(content, filetype) {
    const { promise, resolve } = Promise.withResolvers();
    this._highlightPromises.push({ promise, resolve });
    return promise;
  }
  setMockResult(result) {
    this._mockResult = result;
  }
  resolveHighlightOnce(index = 0) {
    if (index >= 0 && index < this._highlightPromises.length) {
      this._highlightPromises[index].resolve(this._mockResult);
      this._highlightPromises.splice(index, 1);
    }
  }
  resolveAllHighlightOnce() {
    for (const { resolve } of this._highlightPromises) {
      resolve(this._mockResult);
    }
    this._highlightPromises = [];
  }
  isHighlighting() {
    return this._highlightPromises.length > 0;
  }
}
// src/testing/spy.ts
function createSpy() {
  const calls = [];
  const spy = (...args) => {
    calls.push(args);
  };
  spy.calls = calls;
  spy.callCount = () => calls.length;
  spy.calledWith = (...expected) => {
    return calls.some((call) => JSON.stringify(call) === JSON.stringify(expected));
  };
  spy.reset = () => calls.length = 0;
  return spy;
}
export {
  createTestRenderer,
  createSpy,
  createMockMouse,
  createMockKeys,
  MouseButtons,
  MockTreeSitterClient,
  KeyCodes
};

//# debugId=334F11C8682F8A0A64756E2164756E21
//# sourceMappingURL=testing.js.map
