/**
 * @module module/cluster-page-sk
 * @description <h2><code>cluster-page-sk</code></h2>
 *
 * The cluster-page-sk shows many digests and clusters them based on how similar they are. This
 * can help identify incorrectly triaged images or other interesting patterns.
 *
 * It is a top level element.
 */
import { html } from 'lit-html';
import { define } from '../../../elements-sk/modules/define';
import { jsonOrThrow } from '../../../infra-sk/modules/jsonOrThrow';
import { stateReflector } from '../../../infra-sk/modules/stateReflector';
import {
  fromParamSet,
  fromObject,
  ParamSet,
} from '../../../infra-sk/modules/query';
import { HintableObject } from '../../../infra-sk/modules/hintable';
import { sendBeginTask, sendEndTask, sendFetchError } from '../common';
import { ElementSk } from '../../../infra-sk/modules/ElementSk';
import {
  SearchCriteriaToHintableObject,
  SearchCriteriaFromHintableObject,
} from '../search-controls-sk';

import '../cluster-digests-sk';
import '../digest-details-sk';
import '../../../infra-sk/modules/paramset-sk';
import { SearchCriteria } from '../search-controls-sk/search-controls-sk';
import {
  ClusterDiffLink,
  ClusterDiffResult,
  DetailsRequest,
  Digest,
  DigestComparison,
  DigestDetails,
  GroupingsResponse,
  Params,
} from '../rpc_types';
import {
  ClusterDiffNodeWithLabel,
  ClusterDigestsSk,
} from '../cluster-digests-sk/cluster-digests-sk';
import { ParamSetSkClickEventDetail } from '../../../infra-sk/modules/paramset-sk/paramset-sk';

function mergeParamsets(base: ParamSet, extra: ParamSet) {
  for (const key in extra) {
    const values = base[key] || [];
    for (const value of extra[key]) {
      if (!values.includes(value)) {
        values.push(value);
      }
    }
    base[key] = values;
  }
}

function sortParamset(ps: ParamSet) {
  for (const key in ps) {
    ps[key].sort();
  }
}

export class ClusterPageSk extends ElementSk {
  private static template = (ele: ClusterPageSk) => {
    if (Object.keys(ele.grouping).length === 0) {
      return html`<h1>Need a test to cluster by</h1>`;
    }
    return html`
      <div class="page-container">
        <search-controls-sk
          .corpora=${ele.corpora}
          .paramSet=${ele.paramset}
          .searchCriteria=${ele.searchCriteria}
          @search-controls-sk-change=${ele.searchControlsChanged}
        >
        </search-controls-sk>

        <cluster-digests-sk
          @selection-changed=${ele.selectionChanged}
        ></cluster-digests-sk>

        ${ClusterPageSk.infoPanel(ele)}
      </div>
    `;
  };

  private static infoPanel = (ele: ClusterPageSk) => {
    if (!ele.selectedDigests.length) {
      return html`
        <div>
          Click on one digest or shift click multiple digests to see more
          specific information. Use A/Z to Zoom In/Out and S/X to
          increase/decrease node distance.
        </div>

        <paramset-sk
          clickable
          .paramsets=${[ele.paramsetOfAllDigests]}
          @paramset-key-click=${ele.paramKeyClicked}
          @paramset-key-value-click=${ele.paramValueClicked}
        >
        </paramset-sk>
      `;
    }
    if (ele.selectedDigests.length === 1) {
      if (ele.digestDetails) {
        return html`
          <digest-details-sk
            .details=${ele.digestDetails.digest}
            .commits=${ele.digestDetails.commits}
            .groupings=${ele.groupings}
          >
          </digest-details-sk>
        `;
      }
      return html`<h2>Loading digest details</h2>`;
    }
    if (ele.selectedDigests.length === 2) {
      if (ele.diffDetails) {
        return html` <digest-details-sk
          .details=${ele.diffDetails.left}
          .right=${ele.diffDetails.right}
          .groupings=${ele.groupings}
        >
        </digest-details-sk>`;
      }
      return html`<h2>Loading diff details</h2>`;
    }

    const selectedDigestParamset = {};
    for (const digest of ele.selectedDigests) {
      mergeParamsets(selectedDigestParamset, ele.paramsetsByDigest[digest]);
    }
    sortParamset(selectedDigestParamset);

    return html`
      <div>Summary of ${ele.selectedDigests.length} digests</div>

      <paramset-sk
        clickable
        .paramsets=${[selectedDigestParamset]}
        @paramset-key-click=${ele.paramKeyClicked}
        @paramset-key-value-click=${ele.paramValueClicked}
      >
      </paramset-sk>
    `;
  };

  private corpora: string[] = [];

  private paramset: ParamSet = {};

  // TODO(kjlubick): Add a specific type for cluster requests.
  private searchCriteria: SearchCriteria = {
    corpus: '',
    leftHandTraceFilter: {},
    rightHandTraceFilter: {},
    includePositiveDigests: false,
    includeNegativeDigests: false,
    includeUntriagedDigests: false,
    includeDigestsNotAtHead: false,
    includeIgnoredDigests: false,
    minRGBADelta: 0,
    maxRGBADelta: 0,
    mustHaveReferenceImage: false,
    sortOrder: 'descending',
  };

  private groupings: GroupingsResponse | null = null;

  private grouping: Params = {};

  private changeListID: string = '';

  private crs: string = '';

  // Keeps track of the digests the user has selected.
  private selectedDigests: Digest[] = [];

  // The combined paramset of all digests we loaded and displayed.
  private paramsetOfAllDigests: ParamSet = {};

  // A map of digest -> paramset. Useful for showing the params of the selected digests.
  private paramsetsByDigest: { [key: string]: ParamSet } = {};

  // These are the nodes and links that are drawn in the cluster-digests-sk. Holding onto them
  // lets us update them (e.g. their labels) and easily re-layout the diagram.
  private renderedNodes: ClusterDiffNodeWithLabel[] = [];

  private renderedLinks: ClusterDiffLink[] = [];

  private digestDetails: DigestDetails | null = null;

  private diffDetails: DigestComparison | null = null;

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

  private readonly stateChanged: () => void;

  private readonly keyEventHandler: (e: KeyboardEvent) => void;

  constructor() {
    super(ClusterPageSk.template);

    this.stateChanged = stateReflector(
      /* getState */ () => {
        const state = SearchCriteriaToHintableObject(
          this.searchCriteria
        ) as any;
        state.grouping = this.grouping;
        state.changeListID = this.changeListID;
        state.crs = this.crs;
        return state;
      },
      /* setState */ (newState) => {
        if (!this._connected) {
          return;
        }
        this.searchCriteria = SearchCriteriaFromHintableObject(newState);
        this.grouping = (newState.grouping as Params) || {};
        this.changeListID = newState.changeListID as string;
        this.crs = newState.crs as string;
        this.fetchGroupingsOnce();
        this.fetchClusterData();
        this._render();
      }
    );

    this.keyEventHandler = (e: KeyboardEvent) => this.keyPressed(e);
  }

  connectedCallback() {
    super.connectedCallback();
    this._render();
    // This assumes that there is only one multi-zoom-sk rendered on the page at a time (if there
    // are multiple, they may all respond to keypresses at once).
    document.addEventListener('keydown', this.keyEventHandler);
  }

  disconnectedCallback() {
    super.disconnectedCallback();
    document.removeEventListener('keydown', this.keyEventHandler);
  }

  private async fetchGroupingsOnce() {
    // Only fetch once. We assume this doesn't change during the page's lifetime.
    if (this.groupings) return;

    try {
      sendBeginTask(this);
      this.groupings = await fetch('/json/v1/groupings', {
        method: 'GET',
      }).then(jsonOrThrow);
      this._render();
      sendEndTask(this);
    } catch (e) {
      sendFetchError(this, e, 'fetching groupings');
    }
  }

  /**
   * Creates the RPC URL for fetching the data about clustering within this test (aka grouping).
   */
  private clusterURL(): string {
    if (Object.keys(this.grouping).length === 0) {
      return '';
    }
    const sc = this.searchCriteria;

    const query: ParamSet = { ...sc.leftHandTraceFilter };
    query.name = [this.grouping.name];

    const queryObj: HintableObject = {
      source_type: sc.corpus,
      query: fromParamSet(query),
      pos: sc.includePositiveDigests,
      neg: sc.includeNegativeDigests,
      unt: sc.includeUntriagedDigests,
      head: !sc.includeDigestsNotAtHead,
      include: sc.includeIgnoredDigests,
    };
    const url = '/json/v2/clusterdiff';
    return `${url}?${fromObject(queryObj)}`;
  }

  private fetchClusterData() {
    const url = this.clusterURL();
    if (!url) {
      console.warn('no grouping/test was specified.');
      return;
    }

    const extra = this.prefetch();
    sendBeginTask(this);
    sendBeginTask(this);

    fetch(url, extra)
      .then(jsonOrThrow)
      .then((clusterDiffResult: ClusterDiffResult) => {
        this.renderedNodes = clusterDiffResult.nodes || [];
        this.renderedLinks = clusterDiffResult.links || [];
        this.layoutCluster();
        // TODO(kjlubick) remove json.test from the RPC value ( we have it in this.grouping)
        this.paramsetOfAllDigests = clusterDiffResult.paramsetsUnion;
        this.paramsetsByDigest = clusterDiffResult.paramsetByDigest;
        this._render();
        sendEndTask(this);
      })
      .catch((e) => sendFetchError(this, e, 'clusterdiff'));

    const paramsetURL = '/json/v2/paramset';
    fetch(paramsetURL, 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 cluster page is locked into the specific grouping (aka test name); We shouldn't
        // support clustering across tests unless we absolutely need to. Doing so would probably
        // require some backend changes.
        delete paramset.name;
        this.paramset = paramset;
        this._render();
        sendEndTask(this);
      })
      .catch((e) => sendFetchError(this, e, 'paramset'));
  }

  private fetchDetails(digest: Digest) {
    const extra = this.prefetch();
    sendBeginTask(this);

    const request: DetailsRequest = {
      digest: digest,
      grouping: this.grouping,
    };
    if (this.changeListID && this.crs) {
      request.changelist_id = this.changeListID;
      request.crs = this.crs;
    }
    fetch('/json/v2/details', {
      ...extra,
      method: 'POST',
      body: JSON.stringify(request),
      headers: {
        'Content-Type': 'application/json',
      },
    })
      .then(jsonOrThrow)
      .then((digestDetails: DigestDetails) => {
        this.digestDetails = digestDetails;
        this._render();
        sendEndTask(this);
      })
      .catch((e) => sendFetchError(this, e, 'digest details'));
  }

  private fetchDiff(leftDigest: Digest, rightDigest: Digest) {
    const extra = this.prefetch();
    sendBeginTask(this);

    const urlObj: HintableObject = {
      corpus: [this.searchCriteria.corpus],
      test: [this.grouping.name],
      left: [leftDigest],
      right: [rightDigest],
    };
    if (this.changeListID) {
      urlObj.changelist_id = [this.changeListID];
      urlObj.crs = [this.crs];
    }
    const base = '/json/v2/diff';
    const url = `${base}?${fromObject(urlObj)}`;

    fetch(url, extra)
      .then(jsonOrThrow)
      .then((digestComparison: DigestComparison) => {
        this.diffDetails = digestComparison;
        this._render();
        sendEndTask(this);
      })
      .catch((e) => sendFetchError(this, e, 'diff details'));
  }

  private keyPressed(e: KeyboardEvent) {
    // Advice taken from https://medium.com/@uistephen/keyboardevent-key-for-cross-browser-key-press-check-61dbad0a067a
    const cluster = this.querySelector<ClusterDigestsSk>('cluster-digests-sk');
    if (!cluster) {
      return;
    }
    const key = e.key || e.keyCode;
    switch (key) {
      case 'z':
      case 90: // Zoom in (loosen links)
        cluster.changeLinkTightness(false);
        break;
      case 'a':
      case 65: // Zoom out (tighten links)
        cluster.changeLinkTightness(true);
        break;
      case 's':
      case 83: // Increase distance between nodes
        cluster.changeNodeRepulsion(true);
        break;
      case 'x':
      case 88: // Decrease distance between nodes
        cluster.changeNodeRepulsion(false);
        break;
      default:
        return;
    }
    // If we captured the key event, stop it from propagating.
    e.stopPropagation();
  }

  private layoutCluster() {
    this.querySelector<ClusterDigestsSk>('cluster-digests-sk')?.setData(
      this.renderedNodes,
      this.renderedLinks
    );
  }

  private paramKeyClicked(e: CustomEvent<ParamSetSkClickEventDetail>) {
    const keyClicked = e.detail.key;
    for (const node of this.renderedNodes) {
      const ps = this.paramsetsByDigest[node.name];
      node.label = (ps[keyClicked] || '').toString();
    }
    this.layoutCluster();
  }

  private paramValueClicked(e: CustomEvent<ParamSetSkClickEventDetail>) {
    const keyClicked = e.detail.key;
    const valueClicked = e.detail.value!;
    for (const node of this.renderedNodes) {
      const ps = this.paramsetsByDigest[node.name];
      if (ps[keyClicked].includes(valueClicked)) {
        node.label = ps[keyClicked].toString();
      } else {
        node.label = '';
      }
    }
    this.layoutCluster();
  }

  private prefetch(): RequestInit {
    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();
    return {
      signal: this.fetchController.signal,
    };
  }

  protected _render() {
    super._render();
    // Make the cluster draw to the full width.
    const cluster = this.querySelector<ClusterDigestsSk>('cluster-digests-sk');
    if (cluster) {
      cluster.setWidth(cluster.offsetWidth);
    }
  }

  private searchControlsChanged(e: CustomEvent<SearchCriteria>) {
    this.searchCriteria = e.detail;
    this.stateChanged();
    this.fetchClusterData();

    // Reset selection
    this.digestDetails = null;
    this.diffDetails = null;
    this.selectedDigests = [];
    this._render();
  }

  private selectionChanged(e: CustomEvent<Digest[]>) {
    this.selectedDigests = e.detail;
    const numDigests = this.selectedDigests.length;
    this.digestDetails = null;
    this.diffDetails = null;
    if (numDigests === 1) {
      this.fetchDetails(this.selectedDigests[0]);
    } else if (numDigests === 2) {
      this.fetchDiff(this.selectedDigests[0], this.selectedDigests[1]);
    }
    this._render();
  }
}

define('cluster-page-sk', ClusterPageSk);
