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

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