import type { ExecutableInstruction } from "../grl/ir/index.js";
import type { MotionDiagnostic } from "../kdl/types.js";
import type { RuntimeSourceLocation } from "./sourceMap.js";

export type RuntimeTraceEventKind =
  | "load"
  | "state"
  | "instruction"
  | "motion"
  | "io"
  | "wait"
  | "alarm"
  | "breakpoint"
  | "diagnostic"
  | "script";

export interface RuntimeTraceEvent {
  id: number;
  time: number;
  kind: RuntimeTraceEventKind;
  procedure?: string;
  pc?: number;
  instructionKind?: ExecutableInstruction["kind"] | string;
  message?: string;
  source?: RuntimeSourceLocation;
  diagnostic?: MotionDiagnostic;
  data?: Record<string, unknown>;
}

export class TraceBuffer {
  private readonly events: RuntimeTraceEvent[] = [];
  private nextId = 1;

  constructor(private readonly capacity = 1000) {}

  push(event: Omit<RuntimeTraceEvent, "id">): RuntimeTraceEvent {
    const next: RuntimeTraceEvent = {
      ...event,
      id: this.nextId
    };
    this.nextId += 1;
    this.events.push(next);
    while (this.events.length > this.capacity) {
      this.events.shift();
    }
    return next;
  }

  all(): RuntimeTraceEvent[] {
    return this.events.map((event) => ({ ...event }));
  }

  clear(): void {
    this.events.length = 0;
  }
}
