/**
 * @module module/list-page-sk
 * @description <h2><code>list-page-sk</code></h2>
 *
 * This page summarizes the outputs of various tests. It shows the amount of digests produced,
 * as well as a few options to configure what range of traces to enumerate.
 *
 * It is a top level element.
 */
import { define } from 'elements-sk/define';
import { html } from 'lit-html';
import { $$ } from 'common-sk/modules/dom';
import { jsonOrThrow } from 'common-sk/modules/jsonOrThrow';
import { stateReflector } from 'common-sk/modules/stateReflector';
import { fromObject } from 'common-sk/modules/query';
import { HintableObject } from 'common-sk/modules/hintable';
import { ElementSk } from '../../../infra-sk/modules/ElementSk';
import { sendBeginTask, sendEndTask, sendFetchError } from '../common';
import { defaultCorpus } from '../settings';

import '../corpus-selector-sk';
import '../query-dialog-sk';
import '../sort-toggle-sk';
import 'elements-sk/checkbox-sk';
import 'elements-sk/icon/group-work-icon-sk';
import 'elements-sk/icon/tune-icon-sk';
import { SearchCriteriaToHintableObject } from '../search-controls-sk';
import { QueryDialogSk } from '../query-dialog-sk/query-dialog-sk';
import { SortToggleSk } from '../sort-toggle-sk/sort-toggle-sk';
import { SearchCriteriaHintableObject } from '../search-controls-sk/search-controls-sk';
import { ListTestsResponse, ParamSet, TestSummary } from '../rpc_types';

const searchQuery = (corpus: string, query: string): string => {
  if (!query) {
    return `source_type=${corpus}`;
  }
  return `source_type=${corpus}, \n${query.split('&').join(',\n')}`;
};

export class ListPageSk extends ElementSk {
  private static template = (ele: ListPageSk) => html`
    <div>
      <corpus-selector-sk .corpora=${ele.corpora}
          .selectedCorpus=${ele.currentCorpus} @corpus-selected=${ele.currentCorpusChanged}>
      </corpus-selector-sk>

      <div class=query_params>
        <button class=show_query_dialog @click=${ele.showQueryDialog}>
          <tune-icon-sk></tune-icon-sk>
        </button>
        <pre>${searchQuery(ele.currentCorpus, ele.currentQuery)}</pre>
        <checkbox-sk label="Disregard Ignore Rules" class=ignore_rules
                 ?checked=${ele.disregardIgnoreRules} @click=${ele.toggleIgnoreRules}></checkbox-sk>
      </div>
    </div>

    <!-- lit-html (or maybe html in general) doesn't like sort-toggle-sk to go inside the table.-->
    <sort-toggle-sk id=sort_table .data=${ele.byTestCounts} @sort-changed=${ele._render}>
      <table>
         <thead>
             <tr>
              <th data-key=name data-sort-toggle-sk=up>Test name</th>
              <th data-key=positive_digests>Positive</th>
              <th data-key=negative_digests>Negative</th>
              <th data-key=untriaged_digests>Untriaged</th>
              <th data-key=total_digests>Total</th>
              <th>Cluster View</th>
            </tr>
        </thead>
        <tbody>
          <!-- repeat was tested here; map is about twice as fast as using the repeat directive
               (which moves the existing elements). This is because reusing the existing templates
               is pretty fast because there isn't a lot to change.-->
          ${ele.byTestCounts.map((row) => ListPageSk.testRow(row, ele))}
        </tbody>
      </table>
    </sort-toggle-sk>

    <query-dialog-sk @edit=${ele.currentQueryChanged}></query-dialog-sk>
  `;

  private static testRow = (row: TestSummary, ele: ListPageSk) => {
    interface MakeSearchCriteriaOpts {
      positive: boolean;
      negative: boolean;
      untriaged: boolean;
    }

    // Returns a HintableObject for building the GET parameters to the search page.
    const makeSearchCriteria = (opts: MakeSearchCriteriaOpts): SearchCriteriaHintableObject => SearchCriteriaToHintableObject({
      corpus: ele.currentCorpus,
      leftHandTraceFilter: { name: [row.name] },
      includePositiveDigests: opts.positive,
      includeNegativeDigests: opts.negative,
      includeUntriagedDigests: opts.untriaged,
      includeIgnoredDigests: ele.disregardIgnoreRules,
      includeDigestsNotAtHead: false,
    });

    const searchPageHref = (opts: MakeSearchCriteriaOpts) => {
      const searchCriteria = makeSearchCriteria(opts);
      const queryParameters = fromObject(searchCriteria as HintableObject);
      return `/search?${queryParameters}`;
    };

    const clusterPageHref = () => {
      const hintableObject: HintableObject = {
        ...makeSearchCriteria({
          positive: true,
          negative: true,
          untriaged: true,

        }),
        left_filter: '',
        grouping: row.name,
      };
      return `/cluster?${fromObject(hintableObject)}`;
    };

    return html`
      <tr>
        <td>
          <a href="${searchPageHref({ positive: true, negative: true, untriaged: true })}"
             target=_blank rel=noopener>
            ${row.name}
          </a>
        </td>
        <td class=center>
          <a href="${searchPageHref({ positive: true, negative: false, untriaged: false })}"
             target=_blank rel=noopener>
           ${row.positive_digests}
          </a>
        </td>
        <td class=center>
          <a href="${searchPageHref({ positive: false, negative: true, untriaged: false })}"
             target=_blank rel=noopener>
           ${row.negative_digests}
          </a>
        </td>
        <td class=center>
          <a href="${searchPageHref({ positive: false, negative: false, untriaged: true })}"
             target=_blank rel=noopener>
           ${row.untriaged_digests}
          </a>
        </td>
        <td class=center>
          <a href="${searchPageHref({ positive: true, negative: true, untriaged: true })}"
             target=_blank rel=noopener>
            ${row.total_digests}
          </a>
        </td>
        <td class=center>
          <a href="${clusterPageHref()}" target=_blank rel=noopener>
            <group-work-icon-sk></group-work-icon-sk>
          </a>
        </td>
      </tr>
    `;
  };

  private corpora: string[] = [];

  private paramset: ParamSet = {};

  private currentQuery = '';

  private currentCorpus = '';

  private disregardIgnoreRules = false;

  private byTestCounts: TestSummary[] = [];

  private readonly stateChanged: ()=> void;

  // Allows us to abort fetches if we fetch again.
  private fetchController?: AbortController;

  constructor() {
    super(ListPageSk.template);

    this.stateChanged = stateReflector(
      /* getState */() => ({
        // provide empty values
        disregard_ignores: this.disregardIgnoreRules,
        corpus: this.currentCorpus,
        query: this.currentQuery,
      }), /* setState */(newState) => {
        if (!this._connected) {
          return;
        }
        // default values if not specified.
        this.disregardIgnoreRules = newState.disregard_ignores as boolean || false;
        this.currentCorpus = newState.corpus as string || defaultCorpus();
        this.currentQuery = newState.query as string || '';
        this.fetch();
        this._render();
      },
    );
  }

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

  private currentCorpusChanged(e: CustomEvent<string>) {
    e.stopPropagation();
    this.currentCorpus = e.detail;
    this.stateChanged();
    this._render();
    this.fetch();
  }

  private currentQueryChanged(e: CustomEvent<string>) {
    e.stopPropagation();
    this.currentQuery = e.detail;
    this.stateChanged();
    this._render();
    this.fetch();
  }

  private fetch() {
    if (this.fetchController) {
      // Kill any outstanding requests
      this.fetchController.abort();
    }

    // Make a fresh abort controller for each set of fetches.
    // They cannot be re-used once aborted.
    this.fetchController = new AbortController();
    const extra = {
      signal: this.fetchController.signal,
    };

    sendBeginTask(this);
    sendBeginTask(this);

    const base = '/json/v2/list';
    let url = `${base}?corpus=${encodeURIComponent(this.currentCorpus)}`;
    if (this.disregardIgnoreRules) {
      url += '&include_ignored_traces=true';
    }
    if (this.currentQuery) {
      url += `&trace_values=${encodeURIComponent(this.currentQuery)}`;
    }
    fetch(url, extra)
      .then(jsonOrThrow)
      .then((response: ListTestsResponse) => {
        this.byTestCounts = response.tests || [];
        this._render();
          // By default, sort the data by name in ascending order (to match the direction set
          // above).
          $$<SortToggleSk<TestSummary>>('#sort_table', this)!.sort('name', 'up');
          sendEndTask(this);
      })
      .catch((e) => sendFetchError(this, e, 'list'));

    // TODO(kjlubick) when the search page gets a makeover to have just the params for the given
    //   corpus show up, we should do the same here. First idea is to have a separate corpora
    //   endpoint and then make paramset take a corpus.
    const paramsURL = '/json/v2/paramset';
    fetch(paramsURL, extra)
      .then(jsonOrThrow)
      .then((paramset: ParamSet) => {
        // We split the paramset into a list of corpora...
        this.corpora = paramset.source_type || [];
        // ...and the rest of the keys. This is to make it so the layout is
        // consistent with other pages (e.g. the search page, the by blame page, etc).
        delete paramset.source_type;
        this.paramset = paramset;
        this._render();
        sendEndTask(this);
      })
      .catch((e) => sendFetchError(this, e, 'paramset'));
  }

  private showQueryDialog() {
    $$<QueryDialogSk>('query-dialog-sk')!.open(this.paramset, this.currentQuery);
  }

  private toggleIgnoreRules(e: Event) {
    e.preventDefault();
    this.disregardIgnoreRules = !this.disregardIgnoreRules;
    this.stateChanged();
    this._render();
    this.fetch();
  }
}

define('list-page-sk', ListPageSk);
