'use strict';

const RECENT_INPUT_ECHO_WINDOW_MS = 100;
const CODEX_BULK_INPUT_REDRAW_COALESCE_MS = 350;
const CODEX_SEMANTIC_REDRAW_FAST_MAX_BYTES = 2048;
// A single Codex composer keystroke echo is a small synchronized-output TUI
// redraw (cursor moves + one row repaint). It is far below a full-screen
// repaint. Flushing it at ~1ms (instead of the 8ms generic recent-input path)
// makes typing feel snappy without touching bulk-output coalescing.
const CODEX_COMPOSER_INPUT_REDRAW_FAST_MAX_BYTES = 512;

function hasTerminalControl(data) {
  return /[\x00-\x1f\x7f\x1b]/.test(String(data || ''));
}

function isCodexSession(session) {
  const value = String(
    (session && (session.agentType || session._providerId || session.type || session.cmd)) || ''
  ).toLowerCase();
  return /\bcodex\b|\/codex(?:\s|$)|\\codex(?:\s|$)/.test(value);
}

function isCodexSemanticComposerRedraw(data) {
  const text = String(data || '');
  if (!text || text.length > CODEX_SEMANTIC_REDRAW_FAST_MAX_BYTES) return false;
  if (!text.includes('\x1b[?2026h') || !text.includes('\x1b[?2026l')) return false;
  return /\[(?:Image #[0-9]+(?::[^\]]*)?|Attached images?:[^\]]+)\]/.test(text) ||
    /\x1b\[[0-9;]*m[$/][A-Za-z0-9][A-Za-z0-9_.:-]*/.test(text);
}

// A small Codex composer keystroke echo: a synchronized-output (DEC 2026)
// wrapped redraw under the composer-size bound. This is broader than
// isCodexSemanticComposerRedraw (which only matches image tokens / styled
// command triggers) — it covers ordinary character typing into the native
// composer so each keystroke echo can flush promptly instead of waiting 8ms.
function isCodexComposerInputRedraw(data) {
  const text = String(data || '');
  if (!text || text.length > CODEX_COMPOSER_INPUT_REDRAW_FAST_MAX_BYTES) return false;
  return text.includes('\x1b[?2026h') && text.includes('\x1b[?2026l');
}

function isRecentInput(session, now) {
  const ts = Number(session && (session._lastInputTs || session.lastUserInputAt) || 0);
  return !!ts && (now - ts) >= 0 && (now - ts) < RECENT_INPUT_ECHO_WINDOW_MS;
}

function terminalOutputFlushDelay(data, session, now = Date.now()) {
  const text = String(data || '');
  const len = text.length;
  if (len < 4) return 1;

  const recentInput = isRecentInput(session, now);
  const hasControl = hasTerminalControl(text);
  const bulkInputUntil = Number(session && session._codexComposerBulkInputUntil || 0);
  if (hasControl && bulkInputUntil > now) {
    return Math.max(32, Math.min(CODEX_BULK_INPUT_REDRAW_COALESCE_MS, bulkInputUntil - now));
  }

  // Plain local shell echoes should stay near-instant. ANSI/TUI redraw frames
  // need a short coalescing window; otherwise each key can fan out into many
  // websocket/browser writes and make real typing feel worse.
  if (recentInput && !hasControl && len <= 10) return 1;
  if (recentInput && hasControl && isCodexSession(session) && isCodexSemanticComposerRedraw(text)) return 1;
  // Ordinary Codex composer keystroke echo: small synchronized-output redraw on
  // recent input. Flush near-instant so native typing feels snappy. Bounded by
  // CODEX_COMPOSER_INPUT_REDRAW_FAST_MAX_BYTES so bulk frames never qualify.
  if (recentInput && hasControl && isCodexSession(session) && isCodexComposerInputRedraw(text)) return 1;
  if (recentInput && len < 512) return 8;

  return len < 256 ? 8 : 32;
}

module.exports = {
  RECENT_INPUT_ECHO_WINDOW_MS,
  CODEX_BULK_INPUT_REDRAW_COALESCE_MS,
  CODEX_SEMANTIC_REDRAW_FAST_MAX_BYTES,
  CODEX_COMPOSER_INPUT_REDRAW_FAST_MAX_BYTES,
  hasTerminalControl,
  isCodexSession,
  isCodexSemanticComposerRedraw,
  isCodexComposerInputRedraw,
  isRecentInput,
  terminalOutputFlushDelay,
};
