/**
 * @module modules/commands-sk

 * @description A list view of draw commands for a single frame, and a tool for
 * filtering them. contains the logic for processing the parsed json object from
 * wasm, and extracting things like layer info and command counts which drive
 * other modules.
 *
 * Contains play-sk as a submodule, which playes over the filtered list of
 * commands.
 *
 * Data flows along this path in one direction depending on which end triggers a
 * change.
 * filter text box <=> this._includedSet <=> histogram-sk
 *
 * @evt histogram-update: An event containing the list of histogram entries.
 *      Emitted every time the histogram is recomputed.
 *
 * @evt move-command-position: When the play-sk module or user selects a different
 * command, this event is emitted, and its detail contains the command index in
 * the unfiltered command list for this frame.
 *
 */
import { html, TemplateResult } from 'lit-html';
import { define } from '../../../elements-sk/modules/define';
import { ElementDocSk } from '../element-doc-sk/element-doc-sk';
import { PlaySk } from '../play-sk/play-sk';
import { DefaultMap } from '../default-map';

import '../../../elements-sk/modules/icons/save-icon-sk';
import '../../../elements-sk/modules/icons/content-copy-icon-sk';
import '../../../elements-sk/modules/icons/image-icon-sk';

import { SkpJsonCommand, SkpJsonCommandList, SkpJsonGpuOp } from '../debugger';

import '../play-sk';
import {
  HistogramUpdateEventDetail,
  HistogramEntry,
  HistogramUpdateEvent,
  JumpCommandEvent,
  JumpCommandEventDetail,
  MoveCommandPositionEvent,
  MoveCommandPositionEventDetail,
  MoveToEvent,
  MoveToEventDetail,
  SelectImageEvent,
  SelectImageEventDetail,
  ToggleCommandInclusionEvent,
  ToggleCommandInclusionEventDetail,
} from '../events';

export type CommandRange = [number, number];

// Represents one of the icons that can appear on a command
export interface PrefixItem {
  icon: string;
  color: string;
  count: number;
}

/** A processed command object, created from a SkpJsonCommand */
export interface Command {
  // Index of the command in the unfiltered list.
  index: number;
  // the save/restore depth before this command is executed.
  depth: number;
  // the parsed json representation of the command. exact type depends on the command.
  details: SkpJsonCommand;
  name: string;
  // if this command is one of an indenting pair, the command index range that the pair enclose
  // (save, restore)
  range?: CommandRange;
  prefixes: PrefixItem[];
  // Whether the command will be executed during playback
  visible: boolean;
  // index of any image referenced by this command
  imageIndex?: number;
}

// Information about layers collected by processCommands.
// TODO(nifong): This could be collected in the C++ and returned from
// getLayerSummaries and then commands-sk wouldn't have to be involved
// with layer things at all.
export interface LayerInfo {
  // A Map from layer ids to command indices where they were drawn
  // with a DrawImageRectLayer command. Includes only layer used this frame
  uses: DefaultMap<number, number[]>;
  // A map from layer ids to names that were provided in the render node annotations.
  // This should be sufficient for it to always contain what we attempt to look up.
  // Only valid for the duration of this frame.
  names: Map<number, string>;
}

// Colors to use for gpu op ids
const COLORS = [
  '#1B9E77',
  '#D95F02',
  '#7570B3',
  '#E7298A',
  '#66A61E',
  '#E6AB02',
  '#A6761D',
  '#666666',
  '#09c5d2',
  '#064f77',
  '#3a4ce4',
  '#d256f0',
  '#feb4c7',
  '#fa3029',
  '#ff6821',
  '#a8ff21',
  '#a5cf80',
  '#36d511',
  '#95f19c',
];
// Commands that increase save/restore depth
const INDENTERS: { [key: string]: PrefixItem } = {
  Save: { icon: 'save-icon-sk', color: '#B2DF8A', count: 1 },
  SaveLayer: { icon: 'content-copy-icon-sk', color: '#FDBF6F', count: 1 },
  BeginDrawPicture: { icon: 'image-icon-sk', color: '#A6CEE3', count: 1 },
};
// commands that decrease save/restore depth
const OUTDENTERS: string[] = ['Restore', 'EndDrawPicture'];

export class CommandsSk extends ElementDocSk {
  private static template = (ele: CommandsSk) => html` <div>
    ${CommandsSk.filterTemplate(ele)}
    <div class="horizontal-flex">
      <button @click=${ele._opIdFilter} class="short">Show By Op-Id</button>
      <play-sk .visual=${'full'}></play-sk>
    </div>
    <div class="list">
      ${ele._filtered.map((i: number, filtPos: number) =>
        CommandsSk.opTemplate(ele, filtPos, ele._cmd[i])
      )}
    </div>
  </div>`;

  private static opTemplate = (
    ele: CommandsSk,
    filtpos: number,
    op: Command
  ) => html`<div
    class="op"
    id="op-${op.index}"
    @click=${(e: MouseEvent) => {
      ele._clickItem(e, filtpos);
    }}
  >
    <details>
      <summary
        class="command-summary ${ele.position === op.index ? 'selected' : ''}"
      >
        <div class="command-icons-group">
          <span class="index">${op.index}</span>
          ${op.prefixes.map((pre: PrefixItem) =>
            CommandsSk.prefixItemTemplate(ele, pre)
          )}
        </div>
        <div class="command-title">${op.name}</div>
        <code class="short-desc">${op.details.shortDesc}</code>
        ${op.range
          ? html`<button
              @click=${() => {
                ele.range = op.range!;
              }}
              title="Range-filter the command list to this save/restore pair"
            >
              Zoom
            </button>`
          : ''}
        ${op.imageIndex
          ? html`<button
              @click=${() => {
                ele._jumpToImage(op.imageIndex!);
              }}
              title="Show the image referenced by this command in the resource viewer"
            >
              Image
            </button>`
          : ''}
        <div class="gpu-ops-group">
          ${op.details.auditTrail && op.details.auditTrail.Ops
            ? op.details.auditTrail.Ops.map((gpuOp: SkpJsonGpuOp) =>
                CommandsSk.gpuOpIdTemplate(ele, gpuOp)
              )
            : ''}
        </div>
      </summary>
      <div>
        <checkbox-sk
          title="Toggle command visibility"
          checked=${op.visible}
          @change=${() => ele._toggleVisible(op.index)}
        ></checkbox-sk>
        <strong>Index: </strong> <span class="index">${op.index}</span>
      </div>
      ${ele._renderRullOpRepresentation(ele, op)}
    </details>
  </div> `;

  private static prefixItemTemplate = (
    ele: CommandsSk,
    item: PrefixItem
  ) => html`${ele._icon(item)}
  ${item.count > 1
    ? html`<div title="depth of indenting operation" class="count">
        ${item.count}
      </div>`
    : ''}`;

  private static gpuOpIdTemplate = (
    ele: CommandsSk,
    gpuOp: SkpJsonGpuOp
  ) => html`<span
    title="GPU Op ID - group of commands this was executed with on the GPU"
    class="gpu-op-id"
    style="background: ${ele._gpuOpColor(gpuOp.OpsTaskID)}"
    >${gpuOp.OpsTaskID}</span
  >`;

  private static filterTemplate = (ele: CommandsSk) => html` <div
    class="horizontal-flex"
  >
    <label
      title="Filter command names (Single leading ! negates entire filter).
Command types can also be filted by clicking on their names in the histogram"
      >Filter</label
    >
    <input
      @change=${ele._textFilter}
      value="!DrawAnnotation"
      id="text-filter"
    />&nbsp;
    <label>Range</label>
    <input
      @change=${ele._rangeInputHandler}
      class="range-input"
      value="${ele._range[0]}"
      id="rangelo"
    />
    <b>:</b>
    <input
      @change=${ele._rangeInputHandler}
      class="range-input"
      value="${ele._range[1]}"
      id="rangehi"
    />
    <button @click=${ele.clearFilter} id="clear-filter-button">Clear</button>
  </div>`;

  // processed command list (no filtering applied). change with processCommands
  private _cmd: Command[] = [];

  // list of indices of commands that passed the range and name filters.
  private _filtered: number[] = [];

  // position in filtered (visible) command list
  private _item: number = 0;

  // range filter
  private _range: CommandRange = [0, 100];

  // counts of command occurrences
  private _histogram: HistogramEntry[] = [];

  // known command names (set by processCommands) names are lowercased.
  private _available = new Set<string>();

  // subset of command names that should pass the command filter
  // (names are lowercased)
  private _includedSet = new Set<string>();

  // Play bar submodule
  private _playSk: PlaySk | null = null;

  // information about layers collected from commands
  private _layerInfo: LayerInfo = {
    uses: new DefaultMap<number, number[]>(() => []),
    names: new Map<number, string>(),
  };

  // the command count with no filtering
  get count(): number {
    return this._cmd.length;
  }

  // the command count with all filters applied
  get countFiltered(): number {
    return this._filtered.length;
  }

  get layerInfo(): LayerInfo {
    return this._layerInfo;
  }

  // set the current playback position in the list
  // (index in filtered list)
  set item(i: number) {
    this._item = i;
    this.querySelector<HTMLDivElement>(
      `#op-${this._filtered[this._item]}`
    )?.scrollIntoView({ block: 'nearest' });
    this._render();
    // notify debugger-page-sk that it needs to draw this.position
    this.dispatchEvent(
      new CustomEvent<MoveCommandPositionEventDetail>(
        MoveCommandPositionEvent,
        {
          detail: {
            position: this.position,
            paused: this._playSk!.mode === 'pause',
          },
          bubbles: true,
        }
      )
    );
    this._playSk!.movedTo(this._item);
  }

  // get the playback index in _cmd after filtering is applied.
  get position(): number {
    return this._filtered[this._item];
  }

  set range(range: CommandRange) {
    this._range = range;
    this._applyRangeFilter();
  }

  set textFilter(q: string) {
    this.querySelector<HTMLInputElement>('#text-filter')!.value = q;
    if (!this.count) {
      return;
    }
    this._textFilter(); // does render
  }

  // Return a list of op indices that pass the current filters.
  get filtered(): number[] {
    return this._filtered;
  }

  constructor() {
    super(CommandsSk.template);
  }

  connectedCallback(): void {
    super.connectedCallback();
    this._render();

    this._playSk = this.querySelector<PlaySk>('play-sk')!;

    this._playSk.addEventListener(MoveToEvent, (e) => {
      this.item = (e as CustomEvent<MoveToEventDetail>).detail.item;
    });

    this.addDocumentEventListener(ToggleCommandInclusionEvent, (e) => {
      this._toggleName(
        (e as CustomEvent<ToggleCommandInclusionEventDetail>).detail.name
      );
    });

    // Jump to a command by its unfiltered index.
    this.addDocumentEventListener(JumpCommandEvent, (e: Event) => {
      const i = (e as CustomEvent<JumpCommandEventDetail>).detail
        .unfilteredIndex;
      const filteredIndex = this._filtered.findIndex((n: number) => n === i);
      if (filteredIndex !== undefined) {
        this.item = filteredIndex;
      }
    });
  }

  // _processCommands iterates over the commands to extract several things.
  //  * A depth at every command based on Save/Restore pairs.
  //  * A histogram showing how many times each type of command is used.
  //  * A map from layer node ids to the index of any layer use events in the command list.
  //  * The full set of command names that occur
  processCommands(cmd: SkpJsonCommandList): void {
    const commands: Command[] = [];
    let depth = 0;
    const prefixes: PrefixItem[] = []; // A stack of indenting commands
    // Match up saves and restores, a stack of indices
    const matchup: number[] = [];
    // All command types that occur in this frame
    this._available = new Set<string>();

    this._layerInfo.uses = new DefaultMap<number, number[]>(() => []);
    this._layerInfo.names = new Map<number, string>();

    // Finds things like "RenderNode(id=10, name='DecorView')"
    const renderNodeRe = /^RenderNode\(id=([0-9]+), name='([A-Za-z0-9_]+)'\)/;

    cmd.commands.forEach((com, i) => {
      const name = com.command;
      this._available.add(name.toLowerCase());

      const out: Command = {
        index: i,
        depth: depth,
        details: com, // unaltered object from json
        name: name,
        prefixes: [],
        visible: true,
      };

      // DrawCommand.cpp will write this field if the command references an image
      if (com.imageIndex) {
        out.imageIndex = com.imageIndex;
      }

      if (name in INDENTERS) {
        depth++;

        matchup.push(i);
        // If this is the same type of indenting op we've already seen
        // then just increment the count, otherwise add as a new
        // op in prefixes.
        if (
          depth > 1 &&
          prefixes[prefixes.length - 1].icon === INDENTERS[name].icon
        ) {
          prefixes[prefixes.length - 1].count++;
        } else {
          prefixes.push(this._copyPrefix(INDENTERS[name]));
        }
      } else if (OUTDENTERS.indexOf(name) !== -1) {
        depth--;

        // Now that we can match an OUTDENTER with an INDENTER we can set
        // the _zoom property for both commands.
        const begin: number = matchup.pop()!;
        const range = [begin, i] as CommandRange;
        out.range = range;
        commands[begin].range = range;

        // Only pop the op from prefixes if its count has reached 1.
        if (prefixes[prefixes.length - 1].count > 1) {
          prefixes[prefixes.length - 1].count--;
        } else {
          prefixes.pop();
        }
        out.depth = depth;
      } else if (name === 'DrawImageRectLayer') {
        // A command indicating that a render node with an offscreen buffer (android only)
        // was drawn as an image.
        const node = com.layerNodeId!;
        this._layerInfo.uses.get(node).push(i);
      } else if (name === 'DrawAnnotation') {
        // DrawAnnotation is a bit of metadata added by the android view system.
        // All render nodes have names, but not all of them are drawn with offscreen buffers
        const found = com.key!.match(renderNodeRe);
        if (found) {
          // group 1 is the render node id
          // group 2 is the name of the rendernode.
          this._layerInfo.names.set(parseInt(found[1]), found[2]);
        }
      }

      // deep copy prefixes because we want a snapshot of the current list and counts
      out.prefixes = prefixes.map((p: PrefixItem) => this._copyPrefix(p));

      commands.push(out);
    });

    this._cmd = commands;
    this.range = [0, this._cmd.length - 1]; // this assignment also triggers render
  }

  // User clicked the clear filter button, clear both filters
  clearFilter(): void {
    this.querySelector<HTMLInputElement>('#text-filter')!.value = '';
    if (!this.count) {
      return;
    }
    this.range = [0, this._cmd.length - 1]; // setter triggers _applyRangeFilter, follow that
  }

  // Stop playback and move by a given offset in the filtered list.
  keyMove(offset: number): void {
    this._playSk!.mode = 'pause';
    this.item = Math.max(0, Math.min(this._item + offset, this.countFiltered));
  }

  end(): void {
    this.item = this._filtered.length - 1;
  }

  private _clickItem(e: MouseEvent, filtIndex: number) {
    if (this._item !== filtIndex) {
      // Don't open the dropdown unless you click the already selected item again
      e.preventDefault();
    }
    this.item = filtIndex;
  }

  // filter change coming from histogram
  private _toggleName(name: string) {
    const lowerName = name.toLowerCase();
    if (!this._available.has(lowerName)) {
      return;
    }
    if (this._includedSet.has(lowerName)) {
      this._includedSet.delete(lowerName);
    } else {
      this._includedSet.add(lowerName);
    }

    // represent _includedSet as a negative text filter and put it in the box
    const diff = new Set(this._available);
    for (const c of this._includedSet) {
      diff.delete(c);
    }
    let filter = '';
    if (diff.size > 0) {
      filter = `!${Array.from(diff).join(' ')}`;
    }
    this.querySelector<HTMLInputElement>('#text-filter')!.value = filter;
    // don't trigger _textFilter() since that would send an event back to histogram and
    // start an infinite loop. this._includedSet is correct, apply it and render.
    this._applyCommandFilter();
  }

  // Returns a JSON string representation of the command, augmentend with visually rich
  // or interactive elements for certain types.
  private _renderRullOpRepresentation(ele: CommandsSk, op: Command) {
    // Use json.stringify's replacer feature to replace certain objects.
    // we would like to replace them directly with html templates, but json.stringify
    // toStrings them, so instead replace them with a magic string and add the template
    // to a list, then replace those magic strings with items from the list afterwards.

    // An unlikely string meaning 'insert html template here'
    const magic = '546rftvyghbjjkjiuytre';
    // a list of templates to be used to replaces occurrences of magic.
    const inserts: TemplateResult[] = [];
    const replacer = function (name: string, value: any) {
      if (name === 'imageIndex') {
        // Show a clickable button that takes the user to the image resource viewer.
        inserts.push(html`<b>${value}</b>
          <button
            @click=${() => {
              ele._jumpToImage(value);
            }}
            title="Show the image referenced by this command in the resource viewer"
          >
            Image
          </button>`);
        return magic;
      }
      return value;
    };
    const strung = JSON.stringify(op.details, replacer, 2);
    // JSON.stringify adds some quotes around the magic word.
    // including these in our delimiter removes them.
    const jsonparts = strung.split(`"${magic}"`);
    const result = [html`${jsonparts[0]}`];
    for (let i = 1; i < jsonparts.length; i++) {
      result.push(inserts[i - 1]);
      result.push(html`${jsonparts[i]}`);
    }
    return html`<pre>${result}</pre>`;
  }

  private _jumpToImage(index: number) {
    this.dispatchEvent(
      new CustomEvent<SelectImageEventDetail>(SelectImageEvent, {
        detail: { id: index },
        bubbles: true,
      })
    );
  }

  // (index is in the unfiltered list)
  private _toggleVisible(index: number) {
    this._cmd[index].visible = !this._cmd[index].visible;
  }

  // lit-html does not appear to support setting a tag's name with a ${} so here's
  // a crummy workaround
  private _icon(item: PrefixItem): TemplateResult | null {
    if (item.icon === 'save-icon-sk') {
      return html`<save-icon-sk style="fill: ${item.color};" class="icon">
      </save-icon-sk>`;
    }
    if (item.icon === 'content-copy-icon-sk') {
      return html`<content-copy-icon-sk
        style="fill: ${item.color};"
        class="icon"
      >
      </content-copy-icon-sk>`;
    }
    if (item.icon === 'image-icon-sk') {
      return html`<image-icon-sk style="fill: ${item.color};" class="icon">
      </image-icon-sk>`;
    }
    return null;
  }

  // Any deterministic mapping between integers and colors will do
  private _gpuOpColor(index: number): string {
    return COLORS[index % COLORS.length];
  }

  // deep copy
  private _copyPrefix(p: PrefixItem): PrefixItem {
    return { icon: p.icon, color: p.color, count: p.count };
  }

  private _rangeInputHandler() {
    const lo = parseInt(
      this.querySelector<HTMLInputElement>('#rangelo')!.value,
      10
    );
    const hi = parseInt(
      this.querySelector<HTMLInputElement>('#rangehi')!.value,
      10
    );
    this.range = [lo, hi];
  }

  // parse the text filter input, and if it is possible to represent it purely as
  // a command filter, store it in this._includedSet
  private _textFilter() {
    let rawFilter = this.querySelector<HTMLInputElement>('#text-filter')!
      .value.trim()
      .toLowerCase();
    const negative = rawFilter[0] === '!';

    // make sure to copy it so we don't alter this._available
    this._includedSet = new Set<string>(this._available);

    if (rawFilter !== '') {
      if (negative) {
        rawFilter = rawFilter.slice(1).trim();
        const tokens = rawFilter.split(/\s+/);
        // negative filters can always be represented with histogram selections
        for (const token of tokens) {
          this._includedSet.delete(token);
        }
      } else {
        // for positive filters, the text could either be a set of command names,
        // or a free text search.
        const tokens = rawFilter.split(/\s+/);
        this._includedSet = new Set<string>();
        for (const token of tokens) {
          if (this._available.has(token)) {
            this._includedSet.add(token);
          } else {
            // not a command name, bail out, reset this, do a free text search
            this._includedSet = new Set<string>(this._available);
            // since we just altered this._includedSet we have to let histogram know.
            this.dispatchEvent(
              new CustomEvent<HistogramUpdateEventDetail>(
                HistogramUpdateEvent,
                {
                  detail: { included: new Set<string>(this._includedSet) },
                  bubbles: true,
                }
              )
            );
            this._freeTextSearch(tokens);
            // TODO(nifong): need some visual feedback to let the user know
            console.log(`Query interpreted as free text search because ${token}\
 doesn't appear to be a command name`);
            return;
          }
        }
      }
    }
    this.dispatchEvent(
      new CustomEvent<HistogramUpdateEventDetail>(HistogramUpdateEvent, {
        detail: { included: new Set<string>(this._includedSet) },
        bubbles: true,
      })
    );
    this._applyCommandFilter(); // note we still do this for emtpy filters.
  }

  private _freeTextSearch(tokens: string[]) {
    // Free text search every command's json representation and include its index in
    // this._filtered if any token is found
    const matches = function (s: string) {
      for (const token of tokens) {
        if (s.indexOf(token) >= 0) {
          return true;
        }
      }
      return false;
    };
    this._filtered = [];
    for (let i = this._range[0]; i <= this._range[1]; i++) {
      const commandText = JSON.stringify(this._cmd[i].details).toLowerCase();
      if (matches(commandText)) {
        this._filtered.push(i);
      }
    }
    this._render();
    if (this._filtered.length > 0) {
      this.item = this._filtered.length - 1; // after render because it causes a scroll
    }
  }

  // Applies range filter and recalculates command name histogram.
  // The range filter is the first filter applied. The histogram shows any command
  // that passes
  // the range filter, and shows a nonzero count for any command that passes the command
  // filter.
  private _applyRangeFilter() {
    // Despite the name, there's not much to "apply" but
    // the histogram needs to change when the range filter changes which is
    // why this function is seperate from _applyCommandFilter

    // Calculate data for histogram
    // Each command type gets two different counts
    interface tally {
      count_in_frame: number;
      count_in_range_filter: number;
    }
    const counts = new DefaultMap<string, tally>(() => ({
      count_in_frame: 0,
      count_in_range_filter: 0,
    }));
    for (let i = 0; i < this._cmd.length; i++) {
      const c = this._cmd[i];
      counts.get(c.name).count_in_frame += 1; // always increment first count
      if (i >= this._range[0] && i <= this._range[1]) {
        counts.get(c.name)!.count_in_range_filter += 1; // optionally increment filtered count.
      }
    }

    // Now format the histogram as a sorted array suitable for use in the template.
    // First convert the counts map into an Array of HistogramEntry.
    this._histogram = [];
    counts.forEach((value, key) => {
      this._histogram.push({
        name: key,
        countInFrame: value.count_in_frame,
        countInRange: value.count_in_range_filter,
      });
    });
    // Now sort the array, descending on the rangeCount, ascending
    // on the op name.
    // sort by rangeCount so entries don't move on enable/disable
    this._histogram.sort((a, b) => {
      if (a.countInRange === b.countInRange) {
        if (a.name < b.name) {
          return -1;
        }
        if (a.name > b.name) {
          return 1;
        }
        return 0;
      }
      return b.countInRange - a.countInRange;
    });

    // the user's selections are present in the text filter. Apply them now
    // triggers render
    this._textFilter();
    // that populated this._includedSet, which we also need to notify histogram of.

    // send this to the histogram element
    this.dispatchEvent(
      new CustomEvent<HistogramUpdateEventDetail>(HistogramUpdateEvent, {
        detail: {
          hist: this._histogram,
          // Make a copy so listener can't accidentally write to it.
          included: new Set<string>(this._includedSet),
        },
        bubbles: true,
      })
    );
  }

  // Apply a filter specified by this._includedSet and set the filtered list to be visible.
  private _applyCommandFilter() {
    // Try to retain the user's playback position in the unfiltered list when doing this
    // (it is not always possible)
    const oldPos = this._filtered[this._item];
    let newPos: number | null = null;
    this._filtered = [];
    for (let i = this._range[0]; i <= this._range[1]; i++) {
      if (this._includedSet.has(this._cmd[i].name.toLowerCase())) {
        this._filtered.push(i);
        if (i === oldPos) {
          newPos = this._filtered.length - 1;
        }
      }
    }
    this._playSk!.size = this._filtered.length;
    this._render(); // gotta render before you can scroll
    if (newPos !== null) {
      this.item = newPos; // setter triggers scroll
    } else {
      this.item = this._filtered.length - 1;
    }
  }

  // Filters out all but the last command of each gpu op group
  // Experimental, probably breaks assumptions elsewhere
  private _opIdFilter() {
    this._filtered = [];

    const commandsOfEachOp = new DefaultMap<number, number[]>(() => []);
    this._cmd.forEach((command, index) => {
      if (command.details.auditTrail && command.details.auditTrail.Ops) {
        const opid = command.details.auditTrail.Ops[0].OpsTaskID;
        commandsOfEachOp.get(opid).push(index);
      }
    });
    const sortedKeys: number[] = Array.from(commandsOfEachOp.keys());
    sortedKeys.sort((a, b) => a - b); // force it to sort as a number, not a string
    sortedKeys.forEach((k) => {
      commandsOfEachOp.get(k)!.forEach((i) => {
        this._filtered.push(i);
      });
    });

    this._playSk!.size = this._filtered.length;
    this.item = this._filtered.length - 1;
  }
}

define('commands-sk', CommandsSk);
