'use strict';

(function initTerminalRestoreState(root, factory) {
  if (typeof module === 'object' && module.exports) {
    module.exports = factory();
  } else {
    root.TerminalRestoreState = factory();
  }
})(typeof globalThis !== 'undefined' ? globalThis : this, function buildTerminalRestoreState() {
  const STATES = Object.freeze({
    INACTIVE: 'inactive',
    ACTIVATING: 'activating',
    RESTORE_SAVED: 'restore_saved',
    RESTORE_SNAPSHOT: 'restore_snapshot',
    WAIT_FRESH_SNAPSHOT: 'wait_fresh_snapshot',
    REUSE_HOT_TERMINAL: 'reuse_hot_terminal',
    ATTACHING: 'attaching',
    SNAPSHOT_REQUESTED: 'snapshot_requested',
  });

  const PHASES = Object.freeze({
    IDLE: 'idle',
    HOT_VISIBLE: 'hot-visible',
    ATTACH_REQUESTED: 'attach-requested',
    INTERIM_PAINTED: 'interim-painted',
    SNAPSHOT_REQUESTED: 'snapshot-requested',
    SNAPSHOT_WRITING: 'snapshot-writing',
    PAINT_SETTLING: 'paint-settling',
    READY: 'ready',
    DEGRADED: 'degraded',
  });

  const EPOCH_KEYS = Object.freeze([
    'contentEpoch',
    'layoutEpoch',
    'rendererEpoch',
    'attachEpoch',
    'restoreEpoch',
  ]);

  function shouldShowInitialOverlay({ hasTerminal, canRestoreExitedText, hasCachedSnapshot, shouldRestoreSavedText }) {
    return Boolean(hasTerminal && !canRestoreExitedText && !hasCachedSnapshot && !shouldRestoreSavedText);
  }

  function activationRestoreDecision({
    canRestoreExitedText,
    shouldRestoreSavedText,
    hasCachedSnapshot,
    cachedSnapshotDimsMatch,
  } = {}) {
    if (canRestoreExitedText) {
      return { state: STATES.RESTORE_SAVED, action: 'restore-saved-scrollback', reason: 'exited-saved-scrollback' };
    }
    if (shouldRestoreSavedText) {
      return { state: STATES.RESTORE_SAVED, action: 'restore-saved-scrollback', reason: 'snapshot-shorter-than-saved' };
    }
    if (hasCachedSnapshot && cachedSnapshotDimsMatch) {
      return { state: STATES.RESTORE_SNAPSHOT, action: 'restore-cached-snapshot', reason: 'cached-dims-match' };
    }
    if (hasCachedSnapshot && !cachedSnapshotDimsMatch) {
      return { state: STATES.WAIT_FRESH_SNAPSHOT, action: 'show-loading-overlay', reason: 'cached-dims-mismatch' };
    }
    return { state: STATES.WAIT_FRESH_SNAPSHOT, action: 'wait-fresh-snapshot', reason: 'no-local-restore' };
  }

  function activationRequestDecision({ needsAttach, hasReusableHotTerminal, isExited } = {}) {
    if (isExited) {
      return {
        state: STATES.REUSE_HOT_TERMINAL,
        messageType: null,
        clearStaleQueue: false,
        reason: 'exited-local-terminal',
      };
    }
    if (hasReusableHotTerminal && !needsAttach) {
      return {
        state: STATES.REUSE_HOT_TERMINAL,
        messageType: null,
        clearStaleQueue: false,
        reason: 'reuse-hot-terminal',
      };
    }
    return needsAttach
      ? { state: STATES.ATTACHING, messageType: 'attach', clearStaleQueue: true, reason: 'needs-attach' }
      : { state: STATES.SNAPSHOT_REQUESTED, messageType: 'snapshot', clearStaleQueue: true, reason: 'refresh-snapshot' };
  }

  function createViewState(seed = {}) {
    return {
      viewEpoch: Number(seed.viewEpoch || 0),
      contentEpoch: Number(seed.contentEpoch || 0),
      layoutEpoch: Number(seed.layoutEpoch || 0),
      rendererEpoch: Number(seed.rendererEpoch || 0),
      attachEpoch: Number(seed.attachEpoch || 0),
      restoreEpoch: Number(seed.restoreEpoch || 0),
      visibility: seed.visibility || 'hidden',
      phase: seed.phase || PHASES.IDLE,
      blockers: Array.isArray(seed.blockers) ? seed.blockers.slice() : [],
      lastReadyAt: Number(seed.lastReadyAt || 0),
      lastPaintSettledAt: Number(seed.lastPaintSettledAt || 0),
      lastReadyTuple: seed.lastReadyTuple || null,
    };
  }

  function epochTuple(view = {}) {
    const tuple = {};
    for (const key of EPOCH_KEYS) tuple[key] = Number(view[key] || 0);
    return tuple;
  }

  function tuplesEqual(a, b) {
    if (!a || !b) return false;
    return EPOCH_KEYS.every((key) => Number(a[key] || 0) === Number(b[key] || 0));
  }

  function requestPhase(type) {
    if (type === 'attach') return PHASES.ATTACH_REQUESTED;
    if (type === 'reflow' || type === 'snapshot') return PHASES.SNAPSHOT_REQUESTED;
    return PHASES.IDLE;
  }

  return {
    STATES,
    PHASES,
    EPOCH_KEYS,
    shouldShowInitialOverlay,
    activationRestoreDecision,
    activationRequestDecision,
    createViewState,
    epochTuple,
    tuplesEqual,
    requestPhase,
  };
});
