/**
 * @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 { define } from 'elements-sk/define';
import { html, TemplateResult } from 'lit-html';
import { ElementDocSk } from '../element-doc-sk/element-doc-sk';
import { PlaySk } from '../play-sk/play-sk';
import { DefaultMap } from '../default-map';

import 'elements-sk/icon/save-icon-sk';
import 'elements-sk/icon/content-copy-icon-sk';
import 'elements-sk/icon/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);
