import { DebugTrace, SlotInfo } from '../debug-trace/debug-trace';

// The TraceOp enum must stay in sync with SkSL::SkVMTraceInfo::Op.
enum TraceOp {
  Line = 0,
  Var = 1,
  Enter = 2,
  Exit = 3,
  Scope = 4,
}

// The NumberKind enum must stay in sync with SkSL::Type::NumberKind.
enum NumberKind {
  Float = 0,
  Signed = 1,
  Unsigned = 2,
  Boolean = 3,
  Nonnumeric = 4,
}

// Trace data comes in from the JSON as a number[]. We unpack it into a TraceInfo for ease of use.
type TraceInfo = {
  op: TraceOp;
  data: number[];
};

type StackFrame = {
  // A FunctionInfo from trace.functions.
  func: number;
  // The current line number within the function.
  line: number;
  // Any variable slots which have been touched in this function.
  displayMask: boolean[];
};

type Slot = {
  // The current raw value held in this slot (as a 32-bit integer, not bit-punned).
  value: number;
  // The scope depth associated with this slot (as indicated by trace_scope).
  scope: number;
  // When was the variable in this slot most recently written? (as a cursor position)
  writeTime: number;
};

export type VariableData = {
  // A SlotInfo from trace.slots.
  slotIndex: number;
  // Has this slot been written-to since the last step call?
  dirty: boolean;
  // The current value held in this slot (properly bit-punned/cast to the expected type)
  value: number | boolean;
};

export class DebugTracePlayer {
  private trace: DebugTrace | null = null;

  // The position of the read head within the trace array.
  private cursor: number = 0;

  // Tracks the current scope depth (as indicated by trace_scope).
  private scope: number = 0;

  // Tracks assignments into our data slots.
  private slots: Slot[] = [];

  // Tracks the trace stack (as indicated by trace_enter and trace_exit).
  private stack: StackFrame[] = []; // the execution stack

  // Tracks which line numbers are reached by the trace, and the number of times it's reached.
  private lineNumbers: Map<number, number> = new Map();

  // Tracks all the data slots which have been touched during the current step.
  private dirtyMask: boolean[] = [];

  // Tracks all the data slots which hold function return values.
  private returnValues: boolean[] = [];

  // Tracks line numbers that have breakpoints set on them.
  private breakpointLines: Set<number> = new Set();

  /** Throws an error if a precondition is not met. Indicates a logic bug or invalid trace. */
  private check(result: boolean): void {
    if (!result) {
      throw new Error('check failed');
    }
  }

  /** Copies trace info from the JSON number array into a TraceInfo struct. */
  private getTraceInfo(position: number): TraceInfo {
    this.check(position < this.trace!.trace.length);
    this.check(this.trace!.trace[position][0] in TraceOp);

    const info: TraceInfo = {
      op: this.trace!.trace[position][0] as TraceOp,
      data: this.trace!.trace[position].slice(1),
    };
    return info;
  }

  /** Resets playback to the start of the trace. Breakpoints are not cleared. */
  public reset(trace: DebugTrace | null): void {
    const nslots = trace?.slots?.length ?? 0;

    const globalStackFrame: StackFrame = {
      func: -1,
      line: -1,
      displayMask: Array<boolean>(nslots).map(() => false),
    };

    this.trace = trace;
    this.cursor = 0;
    this.slots = [];
    this.stack = [globalStackFrame];
    this.dirtyMask = Array<boolean>(nslots).map(() => false);
    this.returnValues = Array<boolean>(nslots).map(() => false);

    if (trace !== null) {
      this.slots = trace.slots.map(
        (): Slot => ({
          value: 0,
          scope: Infinity,
          writeTime: 0,
        })
      );
      this.returnValues = trace.slots.map(
        (slotInfo: SlotInfo): boolean => (slotInfo.retval ?? -1) >= 0
      );

      // Build a map holding the number of times each line is reached.
      this.lineNumbers.clear();
      trace.trace.forEach((_, traceIdx: number) => {
        const info: TraceInfo = this.getTraceInfo(traceIdx);
        if (info.op === TraceOp.Line) {
          const lineNumber = info.data[0];
          const lineCount = this.lineNumbers.get(lineNumber) ?? 0;
          this.lineNumbers.set(lineNumber, lineCount + 1);
        }
      });
    }
  }

  /** Advances the simulation to the next Line op. */
  public step(): void {
    this.tidyState();
    while (!this.traceHasCompleted()) {
      if (this.execute(this.cursor++)) {
        break;
      }
    }
  }

  /**
   * Advances the simulation to the next Line op, skipping past matched Enter/Exit pairs.
   * Breakpoints will also stop the simulation even if we haven't reached an Exit.
   */
  public stepOver(): void {
    this.tidyState();
    const initialStackDepth = this.stack.length;

    while (!this.traceHasCompleted()) {
      const canEscapeFromThisStackDepth =
        this.stack.length <= initialStackDepth;
      if (this.execute(this.cursor++)) {
        if (canEscapeFromThisStackDepth || this.atBreakpoint()) {
          break;
        }
      }
    }
  }

  /**
   * Advances the simulation until we exit from the current stack frame.
   * Breakpoints will also stop the simulation even if we haven't left the stack frame.
   */
  public stepOut(): void {
    this.tidyState();
    const initialStackDepth = this.stack.length;

    while (!this.traceHasCompleted()) {
      if (this.execute(this.cursor++)) {
        const hasEscapedFromInitialStackDepth =
          this.stack.length < initialStackDepth;
        if (hasEscapedFromInitialStackDepth || this.atBreakpoint()) {
          break;
        }
      }
    }
  }

  /** Advances the simulation until we hit a breakpoint, or the trace completes. */
  public run(): void {
    this.tidyState();

    while (!this.traceHasCompleted()) {
      if (this.execute(this.cursor++)) {
        if (this.atBreakpoint()) {
          break;
        }
      }
    }
  }

  /**
   * Cleans up temporary state between steps, such as the dirty mask and function return values.
   */
  private tidyState(): void {
    this.dirtyMask.fill(false);

    const stackTop = this.stack[this.stack.length - 1];
    this.returnValues.forEach((_, slotIdx: number) => {
      stackTop.displayMask[slotIdx] &&= !this.returnValues[slotIdx];
    });
  }

  /** Returns true if we have reached the end of the trace. */
  public traceHasCompleted(): boolean {
    return this.trace == null || this.cursor >= this.trace.trace.length;
  }

  /** Reports the position of the cursor "read head" within the array of trace instructions. */
  public getCursor(): number {
    return this.cursor;
  }

  /** Returns true if the current line has a breakpoint set on it. */
  public atBreakpoint(): boolean {
    return this.breakpointLines.has(this.getCurrentLine());
  }

  /** Replaces all current breakpoints with a new set of them. */
  public setBreakpoints(breakpointLines: Set<number>): void {
    this.breakpointLines = breakpointLines;
  }

  /** Returns the current set of lines which have a breakpoint. */
  public getBreakpoints(): Set<number> {
    return this.breakpointLines;
  }

  /** Adds a breakpoint to a line (if one doesn't exist). */
  public addBreakpoint(line: number): void {
    this.breakpointLines.add(line);
  }

  /** Removes a breakpoint from a line (if one exists). */
  public removeBreakpoint(line: number): void {
    this.breakpointLines.delete(line);
  }

  /** Retrieves the current line. */
  public getCurrentLine(): number {
    this.check(this.stack.length > 0);
    return this.stack[this.stack.length - 1].line;
  }

  /** Retrieves the current line for a given stack frame. */
  public getCurrentLineInStackFrame(stackFrameIndex: number): number {
    // The first entry on the stack is the "global" frame before we enter main, so offset our index
    // by one to account for it.
    ++stackFrameIndex;
    this.check(stackFrameIndex > 0);
    this.check(stackFrameIndex < this.stack.length);
    return this.stack[stackFrameIndex].line;
  }

  /**
   * Returns every line number reached inside this debug trace, along with the remaining number of
   * times that this trace will reach it. e.g. {100, 2} means line 100 will be reached twice.
   */
  public getLineNumbersReached(): Map<number, number> {
    return this.lineNumbers;
  }

  /** Returns the call stack as an array of FunctionInfo indices. */
  public getCallStack(): number[] {
    this.check(this.stack.length > 0);
    return this.stack.slice(1).map((frame: StackFrame) => frame.func);
  }

  /** Returns the size of the call stack. */
  public getStackDepth(): number {
    this.check(this.stack.length > 0);
    return this.stack.length - 1;
  }

  /** Returns a slot's component as a variable-name suffix, e.g. ".x" or "[2][2]". */
  public getSlotComponentSuffix(slotIndex: number): string {
    const slot: SlotInfo = this.trace!.slots[slotIndex];

    if (slot.rows > 1) {
      return `[${Math.floor(slot.index / slot.rows)}][${
        slot.index % slot.rows
      }]`;
    }
    if (slot.columns > 1) {
      switch (slot.index) {
        case 0:
          return '.x';
        case 1:
          return '.y';
        case 2:
          return '.z';
        case 3:
          return '.w';
        default:
          return '[???]';
      }
    }
    return '';
  }

  /** Bit-casts a value for a given slot into a double, honoring the slot's NumberKind. */
  private interpretValueBits(
    slotIdx: number,
    valueBits: number
  ): number | boolean {
    const bitArray: Int32Array = new Int32Array(1);
    bitArray[0] = valueBits;
    switch (this.trace!.slots[slotIdx].kind) {
      case NumberKind.Float:
        return new Float32Array(bitArray.buffer)[0];
      case NumberKind.Unsigned:
        return new Uint32Array(bitArray.buffer)[0];
      case NumberKind.Boolean:
        return valueBits !== 0;
      case NumberKind.Signed:
        return valueBits;
      default:
        return valueBits;
    }
  }

  /** Returns a vector of the indices and values of each slot that is enabled in `bits`. */
  private getVariablesForDisplayMask(displayMask: boolean[]): VariableData[] {
    this.check(displayMask.length === this.slots.length);

    let vars: VariableData[] = [];
    displayMask.forEach((_, slot: number) => {
      if (displayMask[slot]) {
        const varData: VariableData = {
          slotIndex: slot,
          dirty: this.dirtyMask[slot],
          value: this.interpretValueBits(slot, this.slots[slot].value),
        };
        vars.push(varData);
      }
    });

    // Order the variable list so that the most recently-written variables are shown at the top.
    vars = vars.sort((a: VariableData, b: VariableData) => {
      // Order by descending write-time.
      const delta =
        this.slots[b.slotIndex].writeTime - this.slots[a.slotIndex].writeTime;
      if (delta !== 0) {
        return delta;
      }

      // If write times match, order by ascending slot index (preserving the existing order).
      return a.slotIndex - b.slotIndex;
    });

    return vars;
  }

  /** Returns the variables in a given stack frame. */
  public getLocalVariables(stackFrameIndex: number): VariableData[] {
    // The first entry on the stack is the "global" frame before we enter main, so offset our index
    // by one to account for it.
    ++stackFrameIndex;
    this.check(stackFrameIndex > 0);
    this.check(stackFrameIndex < this.stack.length);
    return this.getVariablesForDisplayMask(
      this.stack[stackFrameIndex].displayMask
    );
  }

  /** Returns the variables at global scope. */
  public getGlobalVariables(): VariableData[] {
    if (this.stack.length < 1) {
      return [];
    }
    return this.getVariablesForDisplayMask(this.stack[0].displayMask);
  }

  /** Updates fWriteTime for the entire variable at a given slot. */
  private updateVariableWriteTime(slotIdx: number, cursor: number): void {
    // The slotIdx could point to any slot within a variable.
    // We want to update the write time on EVERY slot associated with this variable.
    // The SlotInfo's groupIndex gives us enough information to find the affected range.
    const changedSlot = this.trace!.slots[slotIdx];
    slotIdx -= changedSlot.groupIdx!;
    this.check(slotIdx >= 0);
    this.check(slotIdx < this.trace!.slots.length);

    for (;;) {
      this.slots[slotIdx++].writeTime = cursor;

      // Stop if we've reached the final slot.
      if (slotIdx >= this.trace!.slots.length) {
        break;
      }
      // Each separate variable-group starts with a groupIndex of 0; stop when we detect this.
      if (this.trace!.slots[slotIdx].groupIdx! == 0) {
        break;
      }
    }
  }

  /**
   * Executes the trace op at the passed-in cursor position. Returns true if we've reached a line
   * or exit trace op, which indicate a stopping point.
   */
  private execute(position: number): boolean {
    const trace = this.getTraceInfo(position);
    this.check(this.stack.length > 0);
    const stackTop: StackFrame = this.stack[this.stack.length - 1];
    switch (trace.op) {
      case TraceOp.Line: {
        // data: line number, (unused)
        const lineNumber = trace.data[0];
        const lineCount = this.lineNumbers.get(lineNumber) ?? 0;
        this.check(lineNumber >= 0);
        this.check(lineNumber < this.trace!.source.length);
        this.check(lineCount > 0);
        stackTop.line = lineNumber;
        this.lineNumbers.set(lineNumber, lineCount - 1);
        return true;
      }
      case TraceOp.Var: {
        // data: slot, value
        const slotIdx = trace.data[0];
        const value = trace.data[1];
        this.check(slotIdx >= 0);
        this.check(slotIdx < this.slots.length);
        this.slots[slotIdx].value = value;
        this.slots[slotIdx].scope = Math.min(
          this.slots[slotIdx].scope,
          this.scope
        );
        this.updateVariableWriteTime(slotIdx, position);
        if ((this.trace!.slots[slotIdx].retval ?? -1) < 0) {
          // Normal variables are associated with the current function.
          stackTop.displayMask[slotIdx] = true;
        } else {
          // Return values are associated with the parent function (since the current function
          // is exiting and we won't see them there).
          this.check(this.stack.length > 1);
          this.stack[this.stack.length - 2].displayMask[slotIdx] = true;
        }
        this.dirtyMask[slotIdx] = true;
        break;
      }
      case TraceOp.Enter: {
        // data: function index, (unused)
        const fnIdx = trace.data[0];
        this.check(fnIdx >= 0);
        this.check(fnIdx < this.trace!.functions.length);
        const enteredStackFrame: StackFrame = {
          func: fnIdx,
          line: -1,
          displayMask: Array<boolean>(this.slots.length).fill(false),
        };
        this.stack.push(enteredStackFrame);
        break;
      }
      case TraceOp.Exit: {
        // data: function index, (unused)
        const fnIdx = trace.data[0];
        this.check(stackTop.func === fnIdx);
        this.stack.pop();
        return true;
      }
      case TraceOp.Scope: {
        // data: scope delta, (unused)
        const scopeDelta = trace.data[0];
        this.scope += scopeDelta;
        if (scopeDelta < 0) {
          // If the scope is being reduced, discard variables that are now out of scope.
          this.slots.forEach((_, slotIdx: number) => {
            if (this.scope < this.slots[slotIdx].scope) {
              this.slots[slotIdx].scope = Infinity;
              stackTop.displayMask[slotIdx] = false;
            }
          });
        }
        break;
      }
      default: {
        throw new Error('unrecognized trace instruction');
      }
    }
    return false;
  }
}
