/**
 * @module modules/pivot-table-sk
 * @description <h2><code>pivot-table-sk</code></h2>
 *
 * Displays a DataFrame that has been pivoted and contains summary values (as
 * opposed to a DataFrame that has been pivoted and contains summary traces).
 * These values are displayed in a table, as opposed to being displayed on in a
 * plot.
 *
 * The inputs required are a DataFrame and a pivot.Request, which has details on
 * how the input DataFrame was pivoted.
 *
 * @evt Emits a change event with the sort history encoded as a string when the
 *    user sorts on a column.
 */
import { define } from 'elements-sk/define';
import { html, TemplateResult } from 'lit-html';
import { toParamSet } from 'common-sk/modules/query';
import { ElementSk } from '../../../infra-sk/modules/ElementSk';
import { pivot, DataFrame, TraceSet } from '../json';
import { operationDescriptions, validateAsPivotTable } from '../pivotutil';

import '../../../infra-sk/modules/paramset-sk';
import 'elements-sk/icon/sort-icon-sk';
import 'elements-sk/icon/arrow-drop-down-icon-sk';
import 'elements-sk/icon/arrow-drop-up-icon-sk';
import { fromKey } from '../paramtools';

/** The direction a column is sorted in. */
export type direction = 'up' | 'down';

/** The different kinds of columns. */
export type columnKind = 'keyValues' | 'summaryValues';

/** Type for a function that can be passed to Array.sort(). */
export type compareFunc = (a: string, b: string)=> number;

/** For each key in a traceset, this stores the values for key,value pair in the
 * traceid that appear in pivot.Request.group_by, and holds them in the order as
 * determined by pivot.Request.group_by.
 */
export type KeyValues = {[key: string]: string[]};

// The event detail is the sort history of the table encoded as a string.
export type PivotTableSkChangeEventDetail = string;

/** Represents a how a single column in the table is to be sorted.
 */
export class SortSelection {
  // The column to sort on, the value is interpreted differently based
  // on the value of this.sortKind:
  //
  // If this.kind === 'keyValues' then it is an index into the keyValues.
  // If this.Kind === 'summaryValues' then it is an index into the trace values.
  column: number = 0;

  kind: columnKind = 'summaryValues';

  dir: direction = 'up';

  constructor(column: number, kind: columnKind, dir: direction) {
    this.column = column;
    this.kind = kind;
    this.dir = dir;
  }

  toggleDirection(): void {
    if (this.dir === 'down') {
      this.dir = 'up';
    } else {
      this.dir = 'down';
    }
  }

  /** Returns a compareFunc that sorts based on the state of this SortSelection.
   */
  buildCompare(traceset: TraceSet, keyValues: {[key: string]: string[]}): compareFunc {
    const compare = (a: string, b: string): number => {
      let ret = 0;
      if (this.kind === 'keyValues') {
        const aString = keyValues[a][this.column];
        const bString = keyValues[b][this.column];
        if (aString < bString) {
          ret = -1;
        } else if (bString < aString) {
          ret = 1;
        } else {
          return 0;
        }
      } else {
        ret = traceset[a][this.column] - traceset[b][this.column];
      }

      if (this.dir === 'down') {
        ret = -ret;
      }
      return ret;
    };

    return compare;
  }

  /** Encodes the SortSelection as a string. */
  encode(): string {
    const encodedDir = this.dir === 'up' ? 'u' : 'd';
    const encodedKind = this.kind === 'keyValues' ? 'k' : 's';
    return `${encodedDir}${encodedKind}${this.column}`;
  }

  /** Decode an encoded SortSelection from a string encoded by
   * SortSelection.encode(). */
  static decode(s: string): SortSelection {
    const dir = s[0] === 'u' ? 'up' : 'down';
    const kind: columnKind = s[1] === 'k' ? 'keyValues' : 'summaryValues';
    const column = +s.slice(2);
    return new SortSelection(column, kind, dir);
  }
}

/**
 * Keeps one SortSelection for each column being displayed. As the user clicks
 * on columns the function `selectColumnToSortOn` can be called to keep
 * `this.history` up to date.
 *
 * This enables better sorting behavior, i.e. when you click on col A to sort,
 * then on col B to sort, if there are ties in col B they are broken by the
 * existing order in col A, just like you would get when sorting by columns in a
 * spreadsheet.
 *
 * This is not technically 'stable sort', while each sort action by the user
 * looks like it is doing a stable sort, which is the goal, we are really doing
 * an absolute sort based on a memory of all previous sort actions.
 */
export class SortHistory {
  /** Columns will be sorted by the first entry in history. If that yields a
   * tie, then the second entry in history will be used to break the tie, etc.
   */
  history: SortSelection[] = []

  constructor(numGroupBy: number, numSummaryValues: number) {
    for (let i = 0; i < numSummaryValues; i++) {
      this.history.push(new SortSelection(i, 'summaryValues', 'up'));
    }
    for (let i = 0; i < numGroupBy; i++) {
      this.history.push(new SortSelection(i, 'keyValues', 'up'));
    }
  }

  /** Moves the selected column to the front of the list for sorting, and also
   * reverses its current direction.
   */
  selectColumnToSortOn(column: number, kind: columnKind): void {
    // Remove the matching SortSelection from history.
    let removed: SortSelection[] = [];
    for (let i = 0; i < this.history.length; i++) {
      if (column === this.history[i].column && kind === this.history[i].kind) {
        removed = this.history.splice(i, 1);
        break;
      }
    }

    // Toggle its direction.
    removed[0].toggleDirection();

    // Then add back to the beginning of the list.
    this.history.unshift(removed[0]);
  }

  /** Returns a compareFunc that sorts based on the state of all the
   *  SortSelections in history.
   */
  buildCompare(traceset: TraceSet, keyValues: {[key: string]: string[]}): compareFunc {
    const compares = this.history.map((sel: SortSelection) => sel.buildCompare(traceset, keyValues));
    const compare = (a: string, b: string): number => {
      let ret = 0;
      // Call each compareFunc in `compares` until one of them produces a
      // non-zero result. If all calls return 0 then this compare function also
      // returns 0.
      compares.some((colCompare: compareFunc) => {
        ret = colCompare(a, b);
        return ret;
      });
      return ret;
    };
    return compare;
  }

  /** Encodes the SortHistory as a string.
   *
   * The format is of all the serialized history members joined by
   * dashes.
   */
  encode(): string {
    return this.history.map((sel: SortSelection) => sel.encode()).join('-');
  }

  /** Decodes a string previously encoded via this.encode() and uses it to set
   * the history state. */
  decode(s: string): void {
    this.history = s.split('-').map((encodedSortSelection: string) => SortSelection.decode(encodedSortSelection));
  }
}

export function keyValuesFromTraceSet(traceset: TraceSet, req: pivot.Request): KeyValues {
  const ret: KeyValues = {};
  Object.keys(traceset).forEach((traceKey) => {
    // Parse the key.
    const ps = fromKey(traceKey);
    // Store the values for each key in group_by order.
    ret[traceKey] = req.group_by!.map((colName) => ps[colName]);
  });
  return ret;
}

export class PivotTableSk extends ElementSk {
  private df: DataFrame | null = null;

  private req: pivot.Request | null = null;

  private query: string = ''

  /** Maps each traceKey to a list of the values for each key in the traceID,
   * where the order is determined by this.req.group_by.
   *
   * That is ',arch=arm,config=8888,' maps to ['8888', 'arm'] if
   * this.req.group_by is ['config', 'arch'].
   *  */
  private keyValues: KeyValues = {}

  private sortHistory: SortHistory | null = null;

  // The comparison function to use to sort the table.
  private compare: compareFunc | null = null;

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

  private static template = (ele: PivotTableSk) => {
    const invalidMessage = validateAsPivotTable(ele.req);
    if (invalidMessage) {
      return html`<h2>Cannot display: ${invalidMessage}</h2>`;
    }
    if (!ele.df) {
      return html`<h2>Cannot display: Data is missing.</h2>`;
    }
    return html`
    ${ele.queryDefinition()}
    <table>
      ${ele.tableHeader()}
      ${ele.tableRows()}
    </table>`;
  }

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

  set(df: DataFrame, req: pivot.Request, query: string, encodedHistory: string = ''): void {
    this.df = df;
    this.req = req;
    this.query = query;
    this.keyValues = keyValuesFromTraceSet(this.df.traceset, this.req);
    this.sortHistory = new SortHistory(req.group_by!.length, req.summary!.length);
    if (encodedHistory !== '') {
      this.sortHistory.decode(encodedHistory);
    }
    this.compare = this.sortHistory.buildCompare(this.df.traceset, this.keyValues);
    this._render();
  }

  private queryDefinition(): TemplateResult {
    return html`
    <div class=querydef>
      <div>
        <span class=title>Query</span>
        <paramset-sk .paramsets=${[toParamSet(this.query)]}></paramset-sk>
      </div>
      <div>
        <span class=title>Group by:</span>
        ${this.req!.group_by!.join(', ')}
      </div>
      <div>
        <span class=title>Operation:</span>
        ${operationDescriptions[this.req!.operation]}
      </div>
      <div>
        <span class=title>Summaries:</span>
        ${this.req!.summary!.map((op: pivot.Operation) => operationDescriptions[op]).join(', ')}
      </div>
    </div>`;
  }

  private tableHeader(): TemplateResult {
    return html`
    <tr>
      ${this.keyColumnHeaders()}
      ${this.summaryColumnHeaders()}
    </tr>`;
  }

  private keyColumnHeaders(): TemplateResult[] {
    return this.req!.group_by!.map((groupBy: string, index: number) => html`<th>${this.sortArrow(index, 'keyValues')} ${groupBy}</th>`);
  }

  private summaryColumnHeaders(): TemplateResult[] {
    return this.req!.summary!.map((summaryOperation, index) => html`<th>${this.sortArrow(index, 'summaryValues')} ${operationDescriptions[summaryOperation]}</th>`);
  }

  private sortArrow(column: number, kind: columnKind): TemplateResult {
    const firstSortSelection = this.sortHistory!.history[0];
    if (firstSortSelection.kind === kind) {
      if (column === firstSortSelection.column) {
        if (firstSortSelection.dir === 'up') {
          return html`<arrow-drop-up-icon-sk title="Change sort order to descending." @click=${() => this.changeSort(column, kind)}></arrow-drop-up-icon-sk>`;
        }
        return html`<arrow-drop-down-icon-sk title="Change sort order to ascending." @click=${() => this.changeSort(column, kind)}></arrow-drop-down-icon-sk>`;
      }
    }
    return html`<sort-icon-sk title="Sort this column." @click=${() => this.changeSort(column, kind)}></sort-icon-sk>`;
  }

  private changeSort(column: number, kind: columnKind) {
    this.sortHistory!.selectColumnToSortOn(column, kind);
    this.compare = this.sortHistory!.buildCompare(this.df!.traceset, this.keyValues);
    this.dispatchEvent(new CustomEvent<PivotTableSkChangeEventDetail>('change', { detail: this.sortHistory!.encode(), bubbles: true }));
    this._render();
  }

  private tableRows(): TemplateResult[] {
    const traceset = this.df!.traceset;
    const sortedRowKeys = Object.keys(traceset).sort(this.compare!);
    const ret: TemplateResult[] = [];
    sortedRowKeys.forEach((key) => {
      ret.push(html`<tr>${this.keyRowValues(key)}${this.summaryRowValues(key)}</tr>`);
    });
    return ret;
  }

  private keyRowValues(traceKey: string): TemplateResult[] {
    return this.keyValues[traceKey].map((value) => html`<th class=key>${value}</th>`);
  }

  private summaryRowValues(key: string): TemplateResult[] {
    return this.df!.traceset[key]!.map((value) => html`<td>${PivotTableSk.displayValue(value)}</td>`);
  }

  /** Converts vec32.MissingDataSentinel values into '-'. */
  private static displayValue(value: number): string {
    // TODO(jcgregorio) Have a common definition of vec32.MissingDataSentinel in
    // TS and Go code.
    if (value === 1e32) {
      return '-';
    }
    return value.toPrecision(4);
  }
}

define('pivot-table-sk', PivotTableSk);
