'use strict';
// Deterministic fingerprint of a terminal's visible grid + scrollback descriptor.
// Used on BOTH sides: the server's authoritative headless xterm and the browser
// client's xterm. Equal fingerprint => client render content matches server truth.
//
// Design choices that matter for correctness:
// - Trailing whitespace is stripped per row: xterm pads rows to `cols` with spaces,
//   so two buffers that differ only in pad width must still compare equal.
// - Dimensions (cols) are folded in: a foreign-width render IS a divergence.
// - scrollbackLen is folded in (not the whole scrollback — too expensive) so that
//   gross scrollback drift (missing/duplicated blobs above the viewport) is caught.
// - FNV-1a 32-bit: cheap, dependency-free, stable across Node and the browser.

const FNV_OFFSET = 0x811c9dc5;
const FNV_PRIME = 0x01000193;
const EMPTY_FINGERPRINT = '0:empty';

// IMPORTANT: the browser mirror (public/js/terminal-reconciler.js) MUST keep identical logic — any change here requires a matching change there, or fingerprints diverge.
function fnv1a(str, seed) {
  let h = seed >>> 0;
  for (let i = 0; i < str.length; i++) {
    h ^= str.charCodeAt(i);
    h = Math.imul(h, FNV_PRIME);
  }
  return h >>> 0;
}

// rowStrings: array of visible-row strings (already translateToString'd on server side).
// meta: { cols, rows, scrollbackLen }
function fingerprintRows(rowStrings, meta) {
  const cols = Number(meta && meta.cols) || 0;
  const rows = Number(meta && meta.rows) || 0;
  const scrollbackLen = Number(meta && meta.scrollbackLen) || 0;
  let h = FNV_OFFSET;
  let nonEmpty = false;
  // Header binds dims so width drift is divergence.
  h = fnv1a(`${cols}x${rows}|${scrollbackLen}\n`, h);
  for (let i = 0; i < rowStrings.length; i++) {
    const trimmed = String(rowStrings[i] == null ? '' : rowStrings[i]).replace(/\s+$/, '');
    if (trimmed.length) nonEmpty = true;
    // Row index is part of the hash so reordered rows differ.
    h = fnv1a(`${i}:${trimmed}\n`, h);
  }
  if (!nonEmpty) return EMPTY_FINGERPRINT;
  return `${cols}x${rows}:${h.toString(16)}`;
}

module.exports = { fingerprintRows, EMPTY_FINGERPRINT, fnv1a };
