/**
 * @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 { html, TemplateResult } from 'lit/html.js';
import { define } from '../../../elements-sk/modules/define';
import { toParamSet } from '../../../infra-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/modules/icons/sort-icon-sk';
import '../../../elements-sk/modules/icons/arrow-drop-down-icon-sk';
import '../../../elements-sk/modules/icons/arrow-drop-up-icon-sk';
import { fromKey } from '../paramtools';
import { MISSING_DATA_SENTINEL } from '../const/const';

/** 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) => {
    if (ele.shouldValidate()) {
      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>`;
    }
    return html``;
  };

  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 shouldValidate(): boolean {
    return !this.hasAttribute('disable_validation');
  }

  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 === MISSING_DATA_SENTINEL) {
      return '-';
    }
    return value.toPrecision(4);
  }
}

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