import type { RegexSyntaxRequest } from "../model/syntax";

export interface PatternSyntaxSnapshot<TResult> {
  readonly revision: number;
  readonly request: RegexSyntaxRequest;
  readonly result: TResult;
}

function optionsEqual(
  left: RegexSyntaxRequest["options"],
  right: RegexSyntaxRequest["options"],
): boolean {
  const leftEntries = Object.entries(left);
  return (
    leftEntries.length === Object.keys(right).length &&
    leftEntries.every(([name, value]) => right[name] === value)
  );
}

export function isPatternSyntaxForInput<TResult>(
  snapshot: PatternSyntaxSnapshot<TResult> | undefined,
  request: RegexSyntaxRequest,
): snapshot is PatternSyntaxSnapshot<TResult> {
  return (
    snapshot !== undefined &&
    snapshot.request.flavour === request.flavour &&
    snapshot.request.flavourVersion === request.flavourVersion &&
    snapshot.request.pattern === request.pattern &&
    snapshot.request.flags.length === request.flags.length &&
    snapshot.request.flags.every(
      (flag, index) => flag === request.flags[index],
    ) &&
    optionsEqual(snapshot.request.options, request.options)
  );
}

export function isPatternSyntaxCurrent<TResult>(
  snapshot: PatternSyntaxSnapshot<TResult> | undefined,
  revision: number,
  request: RegexSyntaxRequest,
): snapshot is PatternSyntaxSnapshot<TResult> {
  return (
    snapshot?.revision === revision &&
    isPatternSyntaxForInput(snapshot, request)
  );
}
