/** Shows code size statistics about a single binary. */

import { html, TemplateResult } from 'lit-html';
import { load } from '@google-web-components/google-chart/loader';
import Fuse from 'fuse.js';
import { jsonOrThrow } from '../../../infra-sk/modules/jsonOrThrow';
import { define } from '../../../elements-sk/modules/define';
import { $$ } from '../../../infra-sk/modules/dom';
import { ElementSk } from '../../../infra-sk/modules/ElementSk';
import { isDarkMode } from '../../../infra-sk/modules/theme-chooser-sk/theme-chooser-sk';
import { CodesizeScaffoldSk } from '../codesize-scaffold-sk/codesize-scaffold-sk';
import {
  BloatyOutputMetadata,
  BinaryRPCRequest,
  BinaryRPCResponse,
  TreeMapDataTableRow,
} from '../rpc_types';
import '../../../infra-sk/modules/human-date-sk';
import '@google-web-components/google-chart/';

/**
 * Convert the data we get from the server into a format that can be visualized by the treemap.
 * It will shorten file names by removing the path, for example "foo/bar/baz.cc" becomes "baz.cc".
 * Because the name is the key to the row, we also then must shorten usages of those names later
 * (in the parent column), but cannot shorten the same name more than once (e.g. we have two
 * files with the same name in different subfolders).
 */
export function convertResponseToDataTable(
  inputRows: TreeMapDataTableRow[]
): [string, string, string | number][] {
  const out: [string, string, string | number][] = [];
  out.push(['Name', 'Parent', 'Size']);

  const shortNames = new Set<string>();
  const parentsWhichWereShortened = new Set<string>();

  for (const row of inputRows) {
    // Shorten the file name, but only if the resulting shortened file name is unique.
    const shortenedName = shortenName(row.name);
    const shortenedNameIsUnique = !shortNames.has(shortenedName);
    if (shortenedNameIsUnique && row.name !== shortenedName) {
      shortNames.add(shortenedName);
      parentsWhichWereShortened.add(row.name);
    }
    // If the parent was shortened, use the shortened version.
    // Otherwise, it was a duplicate, so keep the full name.
    out.push([
      shortenedNameIsUnique ? shortenedName : row.name,
      parentsWhichWereShortened.has(row.parent)
        ? shortenName(row.parent)
        : row.parent,
      row.size,
    ]);
  }
  return out;
}

/**
 * Shortens a file name path to be just the name by splitting the string that contains '.'
 * (indicating that it is a file and not a folder or function) on '/' and taking the last element
 * which should be the file name.
 */
export function shortenName(rowName: string): string {
  if (!rowName) {
    return '';
  }
  if (rowName.includes('.') && rowName.includes('/')) {
    rowName = rowName.split('/').pop()!;
  }
  return rowName;
}

const MAX_SEARCH_RESULTS = 10;

export class BinaryPageSk extends ElementSk {
  private static template = (el: BinaryPageSk) => {
    if (el.metadata === null) {
      return html`<p>Loading...</p>`;
    }

    const isTryJob = el.metadata?.patch_issue || el.metadata?.patch_set;
    const commitOrCLAnchorText = isTryJob
      ? `Issue ${el.metadata?.patch_issue}, PS ${el.metadata?.patch_set}`
      : el.metadata?.revision.substring(0, 7);
    const commitOrCLAnchorHref = isTryJob
      ? `https://review.skia.org/${el.metadata?.patch_issue}/${el.metadata?.patch_set}`
      : `https://skia.googlesource.com/skia/+/${el.metadata?.revision}`;

    const compileTaskNameHref = `https://task-scheduler.skia.org/task/${el.metadata?.task_id}`;
    return html`
      <h2>
        Code size statistics for <code>${el.metadata?.binary_name}</code>
        <span class="compile-task">
          (<a href="${compileTaskNameHref}">${el.metadata?.compile_task_name}</a
          >)
        </span>
      </h2>

      <p>
        <a href="${commitOrCLAnchorHref}">${commitOrCLAnchorText}</a>
        ${el.metadata?.subject}
        <br />
        <span class="author-and-timestamp">
          ${el.metadata?.author},
          <human-date-sk
            .date=${el.metadata?.timestamp}
            .diff=${true}></human-date-sk>
          ago.
        </span>
      </p>

      <p class="instructions">Instructions:</p>

      <ul>
        <li><strong>Click</strong> on a node to navigate down the tree.</li>
        <li>
          <strong>Right click</strong> anywhere on the treemap go back up one
          level.
        </li>
        <li>
          <strong> Use the seach bar</strong> to navigate to a node within the
          tree
        </li>
      </ul>

      <div class="search-bar">
        <input
          type="search"
          placeholder="Search for node..."
          aria-label="Search for node..."
          autocomplete="on"
          @input=${el.onSearchInput}
          @keyup=${el.onSearchKeyUp} />
        <ol
          id="searchSuggestions"
          class="search-match-list"
          ?hidden=${!el.listOfSearchResults.length}
          @mouseover=${el.clearDefaultSelected}>
          ${el.listOfSearchResults.map((result, i) =>
            el.searchResult(result, i)
          )}
        </ol>
      </div>

      <div id="treemap"></div>
    `;
  };

  // Returns a <li> with the matching string. If it is the first element, mark it selected to
  // give an affordance that something is auto selected and the user can hit enter to pick it.
  private searchResult = (
    match: Fuse.FuseResult<string>,
    idx: number
  ): TemplateResult => html`
    <li
      class=${`search-match-list-item ${idx === 0 ? 'selected' : ''}`}
      @click=${() => this.showElement(match)}>
      ${match.item}
    </li>
  `;

  private tree: google.visualization.TreeMap | null = null;

  private fuse: Fuse<string> | null = null;

  private listOfSearchResults: Fuse.FuseResult<string>[] = [];

  // Uses Fuse.js to match a users input to a node within the tree. Returns the top
  // MAX_SEARCH_RESULTS results.
  private onSearchInput(e: Event): void {
    if (!this.fuse) {
      return;
    }
    const target = e.target as HTMLInputElement;
    this.listOfSearchResults = this.fuse
      .search(target.value)
      .slice(0, MAX_SEARCH_RESULTS);
    this._render();
  }

  private showElement(match: Fuse.FuseResult<string> | undefined): void {
    if (match) {
      // https://developers.google.com/chart/interactive/docs/events#the-select-event
      // The row number should correspond to the order of which the data was passed into the
      // treemap upon creation. This is the same order we passed into Fuse, and we can find
      // that matching index by looking at refIndex.
      const selectedIdx = match.refIndex;
      this.tree!.setSelection([{ column: null, row: selectedIdx }]);
    }
    this.listOfSearchResults = []; // hide other results
    $$<HTMLInputElement>('.search-bar input', this)!.value = ''; // clear search bar
    this._render();
  }

  // If the user hits enter, change the selected element to the top search result.
  // Otherwise, make sure the first element is highlighted to indicate this behavior.
  private onSearchKeyUp(e: Event): void {
    if (!this.tree) {
      return;
    }
    const evt = e as KeyboardEvent;
    if (evt.key === 'Enter') {
      // User hit enter, use the top result.
      this.showElement(this.listOfSearchResults[0]);
      return;
    }
    // Auto-highlight the first list element again (in case it was cleared via mouse over),
    // thus resetting the affordance that it is the auto-picked version.
    if (this.listOfSearchResults.length >= 1) {
      const firstItem = $$<HTMLLIElement>(
        '#searchSuggestions li:first-child',
        this
      );
      if (firstItem) {
        firstItem.classList.add('selected');
      }
    }
  }

  // If the user starts typing, then mouses over the list, we clear the default selected option.
  private clearDefaultSelected(e: Event): void {
    const defaultSelected = $$<HTMLLIElement>(
      '#searchSuggestions li.selected',
      this
    );
    if (defaultSelected) {
      defaultSelected.classList.remove('selected');
    }
  }

  private metadata: BloatyOutputMetadata | null = null;

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

  connectedCallback(): void {
    super.connectedCallback();
    this._render();
    // Show a loading indicator while the tree is loading.
    CodesizeScaffoldSk.waitFor(this.loadTreeMap());
  }

  private async loadTreeMap(): Promise<void> {
    const params = new URLSearchParams(window.location.search);
    const request: BinaryRPCRequest = {
      commit: params.get('commit') || '',
      patch_issue: params.get('patch_issue') || '',
      patch_set: params.get('patch_set') || '',
      binary_name: params.get('binary_name') || '',
      compile_task_name: params.get('compile_task_name') || '',
    };
    const [, response] = await Promise.all([
      load({ packages: ['treemap'] }),
      fetch('/rpc/binary/v1', { method: 'POST', body: JSON.stringify(request) })
        .then(jsonOrThrow)
        .then((r: BinaryRPCResponse) => r),
    ]);

    this.metadata = response.metadata;
    this._render();

    const rows = convertResponseToDataTable(response.rows);
    const data = google.visualization.arrayToDataTable(rows);
    this.tree = new google.visualization.TreeMap(
      this.querySelector('#treemap')!
    );

    // For some reason the type definition for TreeMapOptions does not include the generateTooltip
    // option (https://developers.google.com/chart/interactive/docs/gallery/treemap#tooltips), so
    // a type assertion is necessary to keep the TypeScript compiler happy.
    const treeOptions = {
      generateTooltip: showTooltip,
      minColor: '#E8DAFF', // We really wanted to have categorical coloring, but that appears
      midColor: '#E8DAFF', // infeasible. Setting the fourth column works for leaf nodes, but not
      maxColor: '#E8DAFF', // parent nodes as one would expect.
    } as google.visualization.TreeMapOptions;

    const searchOptions = {
      isCaseSensitive: false,
      // Ignore single character matches
      minMatchCharLength: 1,
      // At what point does the algorithm gives up (0.0 is a perfect match)
      threshold: 0.6,
    };

    // Strip off the first row, which is the column headings.
    this.fuse = new Fuse(
      rows.slice(1, rows.length).map((row): string => row[0]),
      searchOptions
    );

    // Draw the tree and wait until the tree finishes drawing.
    await new Promise((resolve) => {
      google.visualization.events.addOneTimeListener(
        this.tree,
        'ready',
        resolve
      );
      this.tree!.draw(data, treeOptions);
      document.addEventListener('theme-chooser-toggle', () => {
        // if a user toggles the theme to/from darkmode then redraw
        this.tree!.draw(data, treeOptions);
      });
    });

    // Shows the label of the treemap cell. Returns a string with the HTML to be shown whenever.
    // the user hovers over a treemap cell.
    function showTooltip(row: number, size: string) {
      const escapedLabel = data
        .getValue(row, 0)
        .replace('&', '&amp;')
        .replace('<', '&lt;')
        .replace('>', '&gt;');
      const backgroundColor = isDarkMode() ? '#232F34' : '#FFFFFF';
      return `<div class= "cell-tooltip" style="background: ${backgroundColor};">
          <span>
            ${escapedLabel} <br/>
            Size: ${size} <br/>
          </span>
        </div>`;
    }
  }
}
define('binary-page-sk', BinaryPageSk);
