export const ENGINE_CHANNEL = 'malice-engine';

export type HelloAction = 'ignore' | 'yield' | 'announce';

interface BuildStamp {
  seconds: number;
  tag: string;
}

function parseBuild(build: string): BuildStamp | null {
  const match = /^(\d+)-(.+)$/.exec(build);
  return match ? { seconds: Number(match[1]), tag: match[2] } : null;
}

/** Positive when `a` is newer than `b`, null when either is not a build id. */
export function compareBuilds(a: string, b: string): number | null {
  const left = parseBuild(a);
  const right = parseBuild(b);
  if (!left || !right) return null;
  if (left.seconds !== right.seconds) return left.seconds - right.seconds;
  return left.tag < right.tag ? -1 : left.tag > right.tag ? 1 : 0;
}

/**
 * What a worker of build `own` does on hearing a hello from build `other`.
 * A newer peer wins the store lock, so the worker yields. An older peer is
 * told to yield by repeating our own hello, which it will judge the same way.
 */
export function helloAction(own: string, other: string): HelloAction {
  const order = compareBuilds(other, own);
  if (order === null || order === 0) return 'ignore';
  return order > 0 ? 'yield' : 'announce';
}

export const RELOAD_GUARD_MS = 60_000;

/** A superseded tab reloads itself once, so a shell stuck on the old build cannot loop. */
export function mayAutoReload(now: number, lastReload: number | null): boolean {
  return lastReload === null || now - lastReload >= RELOAD_GUARD_MS;
}

export function retryDelay(attempt: number): number {
  return Math.min(1000 * 2 ** attempt, 8000);
}
