/**
 * @module module/digest-details-sk
 * @description <h2><code>digest-details-sk</code></h2>
 *
 * Displays the details about a digest. These details include comparing it to other digests in the
 * same grouping (e.g. test), if those are available. It provides the affordances to triage the
 * given digest and makes the POST request to triage this given digest.
 *
 * <h2>Events</h2>
 *   This element produces the following events:
 * @evt begin-task/end-task - when a POST request is in flight to handle triaging.
 * @evt triage - Emitted when the user triages the digest. e.detail contains the assigned Label.
 *
 *   Children elements emit the following events of note:
 * @evt show-commits - Event generated when a trace dot is clicked. e.detail contains
 *   the blamelist (an array of commits that could have made up that dot).
 *
 */
import { define } from 'elements-sk/define';
import { html } from 'lit-html';
import { errorMessage } from 'elements-sk/errorMessage';
import { fromObject } from 'common-sk/modules/query';
import dialogPolyfill from 'dialog-polyfill';
import { HintableObject } from 'common-sk/modules/hintable';
import { diffDate } from 'common-sk/modules/human';
import { ElementSk } from '../../../infra-sk/modules/ElementSk';
import { truncate } from '../../../infra-sk/modules/string';
import {
  detailHref, diffPageHref, sendBeginTask, sendEndTask, sendFetchError,
} from '../common';


import 'elements-sk/icon/group-work-icon-sk';
import '../dots-sk';
import '../dots-legend-sk';
import '../triage-sk';
import '../image-compare-sk';
import '../blamelist-panel-sk';
import '../../../infra-sk/modules/paramset-sk';
import { SearchCriteriaToHintableObject } from '../search-controls-sk';
import {
  Commit, Digest, Label, ParamSet, SearchResult, SRDiffDigest, TestName, TraceGroup, TraceID, TriageHistory, TriageRequest,
} from '../rpc_types';
import { SearchCriteria, SearchCriteriaHintableObject } from '../search-controls-sk/search-controls-sk';
import { DotsSk } from '../dots-sk/dots-sk';
import { BlamelistPanelSk } from '../blamelist-panel-sk/blamelist-panel-sk';
import { LabelOrEmpty, TriageSk } from '../triage-sk/triage-sk';
import { ImageComparisonData } from '../image-compare-sk/image-compare-sk';

function toggleButtonMouseover(canToggle: boolean) {
  if (canToggle) {
    return 'By default, Gold shows the closest image, whether it has been marked positive or '
    + 'negative. This button allows you to explicitly select the closest positive or negative.';
  }
  return 'There are no other reference image types to compare against.';
}

const validRefs = ['pos', 'neg'];

export class DigestDetailsSk extends ElementSk {
  private static template = (ele: DigestDetailsSk) => html`
    <div class=container>
      <div class=top_bar>
        <span class=grouping_name>Test: ${ele.grouping}</span>
        <span class=expand></span>
        <a href=${ele.clusterHref()} target=_blank rel=noopener class=cluster_link>
          <group-work-icon-sk title="Cluster view of this digest and all others for this test.">
          </group-work-icon-sk>
        </a>
      </div>

      <div class=comparison>
        <div class=digest_labels>
          <span class="digest_label left">Left: ${ele.digest}</span>
          <span class=expand></span>
          <span class="digest_label right" ?hidden=${!ele.right}>
            Right: ${ele.right && ele.right.digest}
          </span>
        </div>
        <div class=comparison_data>
          <div>${DigestDetailsSk.detailsAndTriageTemplate(ele)}</div>
          <div>${DigestDetailsSk.imageComparisonTemplate(ele)}</div>
          <div>
            <button
                @click=${ele.toggleRightRef}
                ?disabled=${!ele.canToggle()}
                class=toggle_ref
                ?hidden=${ele._overrideRight || !ele.right}
                title=${toggleButtonMouseover(ele.canToggle())}>
              Toggle Reference
            </button>
            <div ?hidden=${!ele.right || ele.right.status !== 'negative'} class=negative_warning>
              Closest image is negative!
            </div>
            <!-- TODO(kjlubick) Comments would go here -->
          </div>
        </div>
      </div>
    ${DigestDetailsSk.traceInfoTemplate(ele)}
    ${DigestDetailsSk.paramsetTemplate(ele)}
    </div>
    <dialog class=blamelist_dialog>
      <blamelist-panel-sk></blamelist-panel-sk>
      <button class=close_btn @click=${ele.closeBlamelistDialog}>Close</button>
    </dialog>
  `;

  private static detailsAndTriageTemplate = (ele: DigestDetailsSk) => {
    if (!ele.right) {
      return html`
        <div class=metrics_and_triage>
          <triage-sk @change=${ele.triageChangeHandler} .value=${ele.status}></triage-sk>
          ${DigestDetailsSk.triageHistoryTemplate(ele)}
      </div>
      `;
    }

    // TODO(kjlubick) would it be clearer to just tell the user the images differ in size and omit
    //  the (probably useless metrics)? Could we also include the actual dimensions of the two?

    return html`
      <div class=metrics_and_triage>
        <div>
          <a href=${diffPageHref(
      ele.grouping,
      ele.digest,
      ele.right.digest,
      ele.changeListID,
      ele.crs,
    )}
             target=_blank rel=noopener class=diffpage_link>
            Diff Details
          </a>
        </div>
        <div class=size_warning ?hidden=${!ele.right.dimDiffer}>Images differ in size!</div>
        <div class=metric>
          <span>Diff metric:</span>
          <span>${ele.right.combinedMetric.toFixed(3)}</span>
        </div>
        <div class=metric>
          <span>Diff %:</span>
          <span>${ele.right.pixelDiffPercent.toFixed(2)}</span>
        </div>
        <div class=metric>
          <span>Pixels:</span>
          <span>${ele.right.numDiffPixels}</span>
        </div>
        <div class=metric>
          <span>Max RGBA:</span>
          <span>[${ele.right.maxRGBADiffs.join(',')}]</span>
        </div>
        <triage-sk @change=${ele.triageChangeHandler} .value=${ele.status}></triage-sk>
        ${DigestDetailsSk.triageHistoryTemplate(ele)}
      </div>
    `;
  };

  private static triageHistoryTemplate = (ele: DigestDetailsSk) => {
    if (ele.triageHistory.length === 0) return '';

    const mostRecent = ele.triageHistory[0];
    return html`
      <div class=triage-history title="Last triaged on ${mostRecent.ts} by ${mostRecent.user}">
        ${diffDate(mostRecent.ts)} ago by
        ${mostRecent.user.includes('@')
      ? mostRecent.user.substring(0, mostRecent.user.indexOf('@') + 1)
      : mostRecent.user}
      </div>
    `;
  }

  private static imageComparisonTemplate = (ele: DigestDetailsSk) => {
    const left: ImageComparisonData = {
      digest: ele.digest,
      title: truncate(ele.digest, 15),
      detail: detailHref(ele.grouping, ele.digest, ele.changeListID, ele.crs),
    };
    if (!ele.right) {
      const hasOtherDigests = (ele.traces?.digests?.length || 0) > 1;
      return html`<image-compare-sk .left=${left}
        .isComputingDiffs=${hasOtherDigests}></image-compare-sk>`;
    }

    const right: ImageComparisonData = {
      digest: ele.right.digest,
      title: ele.right.status === 'positive' ? 'Closest Positive' : 'Closest Negative',
      detail: detailHref(ele.grouping, ele.right.digest, ele.changeListID, ele.crs),
    };
    if (ele._overrideRight) {
      right.title = truncate(ele.right.digest, 15);
    }

    return html`<image-compare-sk .left=${left} .right=${right}></image-compare-sk>`;
  };

  private static traceInfoTemplate = (ele: DigestDetailsSk) => {
    if (!ele.traces || !ele.traces.traces || !ele.traces.traces.length) {
      return '';
    }
    return html`
      <div class=trace_info>
        <dots-sk
            .value=${ele.traces}
            .commits=${ele._commits}
            @hover=${ele.hoverOverTrace}
            @mouseleave=${ele.clearTraceHighlights}
            @showblamelist=${ele.showBlamelist}>
        </dots-sk>
        <dots-legend-sk
            .digests=${ele.traces.digests}
            .changeListID=${ele.changeListID}
            .crs=${ele.crs}
            .test=${ele.grouping}
            .totalDigests=${ele.traces.total_digests || 0}>
        </dots-legend-sk>
      </div>
    `;
  };

  private static paramsetTemplate = (ele: DigestDetailsSk) => {
    if (!ele.digest || !ele.params) {
      return ''; // details might not be loaded yet.
    }

    const titles = [truncate(ele.digest, 15)];
    const paramsets = [ele.params];

    if (ele.right && ele.right.paramset) {
      titles.push(truncate(ele.right.digest, 15));
      paramsets.push(ele.right.paramset);
    }

    return html`
      <paramset-sk .titles=${titles}
                   .paramsets=${paramsets}
                   .highlight=${ele._highlightedParams}>
      </paramset-sk>
    `;
  };

  private grouping: TestName = '';

  private digest: Digest = '';

  private status: Label = 'untriaged';

  private triageHistory: TriageHistory[] = [];

  private params: ParamSet | null = null;

  private traces: TraceGroup | null = null;

  private refDiffs: { [key: string]: SRDiffDigest | null } = {};

  private _changeListID = '';

  private _crs = '';

  private _useNewAPI = false;

  private _commits: Commit[] = [];

  // This tracks which ref we are showing on the right. It will default to the closest one, but
  // can be changed with the toggle.
  private _rightRef = '';

  private _overrideRight: SRDiffDigest | null= null;

  private _highlightedParams: { [key: string]: string } = {};

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

  connectedCallback() {
    super.connectedCallback();
    this._render();
    dialogPolyfill.registerDialog(this.querySelector('dialog.blamelist_dialog')!);
  }

  /**
   * An array of the commits in the tile. Used to compute the blamelist for representing traces.
   */
  get commits(): Commit[] { return this._commits; }

  set commits(arr: Commit[]) {
    this._commits = arr;
    this._render();
  }

  /** SearchResult from which to pull the digest details to show. */
  set details(obj: SearchResult) {
    this.grouping = obj.test || '';
    this.digest = obj.digest || '';
    this.traces = obj.traces || {};
    this.params = obj.paramset;
    this.refDiffs = obj.refDiffs || {};
    this._rightRef = obj.closestRef || '';
    this.status = obj.status || '';
    this.triageHistory = obj.triage_history || [];
    this._render();
  }

  /** The changelist id (or empty string if this is the master branch). */
  get changeListID(): string { return this._changeListID; }

  set changeListID(id: string) {
    this._changeListID = id;
    this._render();
  }

  /** The Code Review System (e.g. "gerrit") if changeListID is set. */
  get crs(): string { return this._crs; }

  set crs(c: string) {
    this._crs = c;
    this._render();
  }

  /**
   * @prop right {Object} Forces the left image to be compared to the given ref.
   */
  get right(): SRDiffDigest | null {
    if (this._overrideRight) {
      return this._overrideRight;
    }
    return this.refDiffs[this._rightRef] || null;
  }

  set right(override: SRDiffDigest | null) {
    this._overrideRight = override;
    this._render();
  }

  get useNewAPI(): boolean {
    return this._useNewAPI;
  }

  set useNewAPI(b: boolean) {
    this._useNewAPI = b;
  }

  private canToggle(): boolean {
    let totalRefs = 0;
    for (const ref of validRefs) {
      if (this.refDiffs[ref]) {
        totalRefs++;
      }
    }
    return totalRefs > 1;
  }

  private clearTraceHighlights() {
    this._highlightedParams = {};
    this._render();
  }

  private closeBlamelistDialog() {
    this.querySelector<HTMLDialogElement>('dialog.blamelist_dialog')?.close();
  }

  private clusterHref() {
    if (!this.grouping || !this.params || !this.params.source_type
        || this.params.source_type.length === 0) {
      return '';
    }

    const searchCriteria: Partial<SearchCriteria> = {
      corpus: this.params.source_type[0],
      includePositiveDigests: true,
      includeNegativeDigests: true,
      includeUntriagedDigests: true,
      includeDigestsNotAtHead: true,
    };
    const clusterState: SearchCriteriaHintableObject & {grouping?: TestName} = SearchCriteriaToHintableObject(searchCriteria);
    clusterState.grouping = this.grouping;
    return `/cluster?${fromObject(clusterState as HintableObject)}`;
  }

  private hoverOverTrace(e: CustomEvent<TraceID>) {
    // Find the matching trace in details.traces.
    const trace = this.traces?.traces?.find((trace) => trace.label === e.detail);
    this._highlightedParams = trace?.params || {};
    this._render();
  }

  protected _render() {
    super._render();
    // By default, the browser will show this long trace scrolled all the way to the left. This
    // is the oldest traces and typically not helpful, so after we load, we ask the traces to
    // scroll itself to the left, which it will do once (and not repeatedly on each render).
    this.querySelector<DotsSk>('dots-sk')?.autoscroll();
  }

  private showBlamelist(e: CustomEvent<Commit[]>) {
    e.stopPropagation();
    const dialog = this.querySelector<HTMLDialogElement>('dialog.blamelist_dialog')!;
    const blamelist = dialog.querySelector<BlamelistPanelSk>('blamelist-panel-sk')!;
    blamelist.commits = e.detail;
    dialog.showModal();
  }

  private toggleRightRef() {
    if (!this.canToggle()) {
      return;
    }
    let idx = validRefs.indexOf(this._rightRef);
    let newRight = '';
    while (!this.refDiffs[newRight]) {
      idx = (idx + 1) % validRefs.length;
      newRight = validRefs[idx];
    }
    this._rightRef = newRight;
    this._render();
  }

  private triageChangeHandler(e: CustomEvent<LabelOrEmpty>) {
    e.stopPropagation();
    const newStatus = e.detail as Label;
    this.dispatchEvent(
      new CustomEvent<LabelOrEmpty>('triage', { bubbles: true, detail: newStatus }),
    );

    const triageRequest: TriageRequest = {
      testDigestStatus: {
        [this.grouping]: {
          [this.digest]: newStatus,
        },
      },
      changelist_id: this.changeListID,
      crs: this.crs,
    };

    sendBeginTask(this);

    const url = this._useNewAPI ? '/json/v2/triage' : '/json/v1/triage';
    fetch(url, {
      method: 'POST',
      body: JSON.stringify(triageRequest),
      headers: {
        'Content-Type': 'application/json',
      },
    }).then((resp) => {
      if (resp.ok) {
        // Triaging was successful.
        this.status = newStatus;
        this.triageHistory.unshift({
          user: 'me',
          ts: Date.now().toString(),
        });
        this._render();
        sendEndTask(this);
      } else {
        // Triaging did not work (possibly because the user was not logged in). We want to set
        // the status of the triage-sk back to what it was to give a visual indication it did not
        // go through. Additionally, toast error message should catch the user's attention.
        console.error(resp);
        errorMessage(
          `Unexpected error triaging: ${resp.status} ${resp.statusText} `
            + '(Are you logged in with the right account?)', 8000,
        );
        this.querySelector<TriageSk>('triage-sk')!.value = this.status;
        this._render();
        sendEndTask(this);
      }
    }).catch((e) => {
      sendFetchError(this, e, 'triaging');
    });
  }
}

define('digest-details-sk', DigestDetailsSk);
