/**
 * @license
 * Copyright 2018 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import '../../shared/gr-comment-thread/gr-comment-thread';
import '../../checks/gr-diff-check-result';
import '../../../embed/diff/gr-diff/gr-diff';
import {
  GerritNav,
  GeneratedWebLink,
} from '../../core/gr-navigation/gr-navigation';
import {
  anyLineTooLong,
  getDiffLength,
  getLine,
  getSide,
  SYNTAX_MAX_LINE_LENGTH,
} from '../../../embed/diff/gr-diff/gr-diff-utils';
import {getAppContext} from '../../../services/app-context';
import {
  getParentIndex,
  isAParent,
  isMergeParent,
  isNumber,
} from '../../../utils/patch-set-util';
import {
  CommentThread,
  equalLocation,
  isInBaseOfPatchRange,
  isInRevisionOfPatchRange,
} from '../../../utils/comment-util';
import {
  CommitRange,
  CoverageRange,
  DiffLayer,
  PatchSetFile,
} from '../../../types/types';
import {
  Base64ImageFile,
  BlameInfo,
  ChangeInfo,
  EDIT,
  NumericChangeId,
  PARENT,
  PatchRange,
  PatchSetNum,
  RepoName,
  RevisionPatchSetNum,
  UrlEncodedCommentId,
} from '../../../types/common';
import {
  DiffInfo,
  DiffPreferencesInfo,
  IgnoreWhitespaceType,
} from '../../../types/diff';
import {
  CreateCommentEventDetail,
  GrDiff,
} from '../../../embed/diff/gr-diff/gr-diff';
import {DiffViewMode, Side, CommentSide} from '../../../constants/constants';
import {FilesWebLinks} from '../gr-patch-range-select/gr-patch-range-select';
import {LineNumber, FILE} from '../../../embed/diff/gr-diff/gr-diff-line';
import {GrCommentThread} from '../../shared/gr-comment-thread/gr-comment-thread';
import {KnownExperimentId} from '../../../services/flags/flags';
import {
  firePageError,
  fireAlert,
  fireServerError,
  fireEvent,
  waitForEventOnce,
  fire,
} from '../../../utils/event-util';
import {getPluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader';
import {assertIsDefined} from '../../../utils/common-util';
import {DiffContextExpandedEventDetail} from '../../../embed/diff/gr-diff-builder/gr-diff-builder';
import {TokenHighlightLayer} from '../../../embed/diff/gr-diff-builder/token-highlight-layer';
import {Timing, Interaction} from '../../../constants/reporting';
import {ChangeComments} from '../gr-comment-api/gr-comment-api';
import {Subscription} from 'rxjs';
import {DisplayLine, RenderPreferences} from '../../../api/diff';
import {resolve} from '../../../models/dependency';
import {browserModelToken} from '../../../models/browser/browser-model';
import {commentsModelToken} from '../../../models/comments/comments-model';
import {checksModelToken, RunResult} from '../../../models/checks/checks-model';
import {GrDiffCheckResult} from '../../checks/gr-diff-check-result';
import {distinctUntilChanged, map} from 'rxjs/operators';
import {deepEqual} from '../../../utils/deep-util';
import {Category} from '../../../api/checks';
import {GrSyntaxLayerWorker} from '../../../embed/diff/gr-syntax-layer/gr-syntax-layer-worker';
import {CODE_MAX_LINES} from '../../../services/highlight/highlight-service';
import {html, LitElement, PropertyValues} from 'lit';
import {customElement, property, query, state} from 'lit/decorators';
import {ValueChangedEvent} from '../../../types/events';
import {debounceP, DelayedPromise} from '../../../utils/async-util';
import {subscribe} from '../../lit/subscription-controller';

const EMPTY_BLAME = 'No blame information for this diff.';

const EVENT_AGAINST_PARENT = 'diff-against-parent';
const EVENT_ZERO_REBASE = 'rebase-percent-zero';
const EVENT_NONZERO_REBASE = 'rebase-percent-nonzero';

function isImageDiff(diff?: DiffInfo) {
  if (!diff) return false;

  const isA = diff.meta_a && diff.meta_a.content_type.startsWith('image/');
  const isB = diff.meta_b && diff.meta_b.content_type.startsWith('image/');

  return !!(diff.binary && (isA || isB));
}

// visible for testing
export interface LineInfo {
  beforeNumber?: LineNumber;
  afterNumber?: LineNumber;
}

declare global {
  interface HTMLElementEventMap {
    /* prettier-ignore */
    'render': CustomEvent;
    'diff-context-expanded': CustomEvent<DiffContextExpandedEventDetail>;
    'create-comment': CustomEvent<CreateCommentEventDetail>;
    'is-blame-loaded-changed': ValueChangedEvent<boolean>;
    'diff-changed': ValueChangedEvent<DiffInfo | undefined>;
    'edit-weblinks-changed': ValueChangedEvent<GeneratedWebLink[] | undefined>;
    'files-weblinks-changed': ValueChangedEvent<FilesWebLinks | undefined>;
    'is-image-diff-changed': ValueChangedEvent<boolean>;
    // Fired when the user selects a line (See gr-diff).
    'line-selected': CustomEvent;
    // Fired if being logged in is required.
    'show-auth-required': void;
  }
}

/**
 * Wrapper around gr-diff.
 *
 * Webcomponent fetching diffs and related data from restAPI and passing them
 * to the presentational gr-diff for rendering. <gr-diff-host> is a Gerrit
 * specific component, while <gr-diff> is a re-usable component.
 */
@customElement('gr-diff-host')
export class GrDiffHost extends LitElement {
  @query('#diff')
  diffElement?: GrDiff;

  @property({type: Number})
  changeNum?: NumericChangeId;

  @property({type: Object})
  change?: ChangeInfo;

  @property({type: Boolean})
  noAutoRender = false;

  @property({type: Object})
  patchRange?: PatchRange;

  @property({type: Object})
  file?: PatchSetFile;

  @property({type: String})
  path?: string;

  @property({type: Object})
  prefs?: DiffPreferencesInfo;

  @property({type: String})
  projectName?: RepoName;

  @property({type: Boolean})
  displayLine = false;

  @state()
  private _isImageDiff = false;

  get isImageDiff() {
    return this._isImageDiff;
  }

  set isImageDiff(isImageDiff: boolean) {
    if (this._isImageDiff === isImageDiff) return;
    this._isImageDiff = isImageDiff;
    fire(this, 'is-image-diff-changed', {value: isImageDiff});
  }

  @property({type: Object})
  commitRange?: CommitRange;

  @state()
  private _editWeblinks?: GeneratedWebLink[];

  get editWeblinks() {
    return this._editWeblinks;
  }

  set editWeblinks(editWeblinks: GeneratedWebLink[] | undefined) {
    if (this._editWeblinks === editWeblinks) return;
    this._editWeblinks = editWeblinks;
    fire(this, 'edit-weblinks-changed', {value: editWeblinks});
  }

  @state()
  private _filesWeblinks?: FilesWebLinks;

  get filesWeblinks() {
    return this._filesWeblinks;
  }

  set filesWeblinks(filesWeblinks: FilesWebLinks | undefined) {
    if (this._filesWeblinks === filesWeblinks) return;
    this._filesWeblinks = filesWeblinks;
    fire(this, 'files-weblinks-changed', {value: filesWeblinks});
  }

  @property({type: Boolean, reflect: true})
  override hidden = false;

  @property({type: Boolean})
  noRenderOnPrefsChange = false;

  // Private but used in tests.
  @state()
  threads: CommentThread[] = [];

  @property({type: Boolean})
  lineWrapping = false;

  @property({type: Object})
  lineOfInterest?: DisplayLine;

  @property({type: String})
  viewMode = DiffViewMode.SIDE_BY_SIDE;

  @property({type: Boolean})
  showLoadFailure?: boolean;

  @state()
  private loggedIn = false;

  // Private but used in tests.
  @state()
  errorMessage: string | null = null;

  @state()
  private baseImage?: Base64ImageFile;

  @state()
  private revisionImage?: Base64ImageFile;

  // Do not use, use diff instead through the getters and setters.
  // This is not a regular @state because we need to also send the
  // 'diff-changed' event when it is changed. And if we rely on @state
  // then the name to look for in willUpdate/update/updated is '_diff'.
  private _diff?: DiffInfo;

  get diff() {
    return this._diff;
  }

  set diff(diff: DiffInfo | undefined) {
    if (this._diff === diff) return;
    const oldDiff = this._diff;
    this._diff = diff;
    this.isImageDiff = isImageDiff(this._diff);
    fire(this, 'diff-changed', {value: this._diff});
    this.requestUpdate('diff', oldDiff);
  }

  @state()
  private changeComments?: ChangeComments;

  @state()
  private fetchDiffPromise: Promise<DiffInfo> | null = null;

  // Do not use, use blame instead through the getters and setters.
  // This is not a regular @state because we need to also send tgetImagesForDiffhe
  // 'is-blame-loading-changed' event when it is changed. And if we
  // rely on @state then the name to look for in willUpdate/update/updated
  // is '_blame'.
  private _blame: BlameInfo[] | null = null;

  @state()
  get blame() {
    return this._blame;
  }

  set blame(blame: BlameInfo[] | null) {
    if (this._blame === blame) return;
    const oldBlame = this._blame;
    this._blame = blame;
    fire(this, 'is-blame-loaded-changed', {value: !!this._blame});
    this.requestUpdate('blame', oldBlame);
  }

  @state()
  private coverageRanges: CoverageRange[] = [];

  @state()
  private loadedWhitespaceLevel?: IgnoreWhitespaceType;

  @state()
  private layers: DiffLayer[] = [];

  @state()
  private renderPrefs: RenderPreferences = {
    num_lines_rendered_at_once: 128,
  };

  // Debounces across multiple reload calls and ensures that waiters can
  // wait on it whenever a reload is requested.  If more than one reload is
  // requested within a given time-frame, the first one is canceled but will
  // still be resolved when the second one is resolved. (and inductively, any
  // further ones that were requested within a animation-frame).
  private reloadPromise?: DelayedPromise<void>;

  private readonly getBrowserModel = resolve(this, browserModelToken);

  private readonly getCommentsModel = resolve(this, commentsModelToken);

  private readonly getChecksModel = resolve(this, checksModelToken);

  // visible for testing
  readonly reporting = getAppContext().reportingService;

  private readonly flags = getAppContext().flagsService;

  private readonly restApiService = getAppContext().restApiService;

  // visible for testing
  readonly userModel = getAppContext().userModel;

  // visible for testing
  readonly jsAPI = getAppContext().jsApiService;

  // visible for testing
  readonly syntaxLayer: GrSyntaxLayerWorker;

  private checksSubscription?: Subscription;

  constructor() {
    super();
    this.syntaxLayer = new GrSyntaxLayerWorker();
    this.renderPrefs = {
      ...this.renderPrefs,
      use_lit_components: this.flags.isEnabled(
        KnownExperimentId.DIFF_RENDERING_LIT
      ),
    };
    this.addEventListener(
      // These are named inconsistently for a reason:
      // The create-comment event is fired to indicate that we should
      // create a comment.
      // The comment-* events are just notifying that the comments did already
      // change in some way, and that we should update any models we may want
      // to keep in sync.
      'create-comment',
      e => this.handleCreateThread(e)
    );
    this.addEventListener('diff-context-expanded', event =>
      this.handleDiffContextExpanded(event)
    );
    subscribe(
      this,
      () => this.getBrowserModel().diffViewMode$,
      diffView => (this.viewMode = diffView)
    );
    subscribe(
      this,
      () => this.userModel.loggedIn$,
      loggedIn => (this.loggedIn = loggedIn)
    );
    subscribe(
      this,
      () => this.getCommentsModel().changeComments$,
      changeComments => {
        this.changeComments = changeComments;
      }
    );
    subscribe(
      this,
      () => this.userModel.diffPreferences$,
      diffPreferences => {
        this.prefs = diffPreferences;
      }
    );
  }

  override connectedCallback() {
    super.connectedCallback();
    this.subscribeToChecks();
  }

  override disconnectedCallback() {
    if (this.reloadPromise) {
      this.reloadPromise.cancel();
      this.reloadPromise = undefined;
    }
    if (this.checksSubscription) {
      this.checksSubscription.unsubscribe();
      this.checksSubscription = undefined;
    }
    this.clear();
    super.disconnectedCallback();
  }

  protected override willUpdate(changedProperties: PropertyValues) {
    // Important to call as this will call render, see LitElement.
    super.willUpdate(changedProperties);
    if (changedProperties.has('diff')) {
      this.isImageDiff = isImageDiff(this.diff);
    }
    if (
      changedProperties.has('changeComments') ||
      changedProperties.has('patchRange') ||
      changedProperties.has('file')
    ) {
      this.threads = this.computeFileThreads(
        this.changeComments,
        this.patchRange,
        this.file
      );
    }
    if (
      changedProperties.has('noRenderOnPrefsChange') ||
      changedProperties.has('prefs') ||
      changedProperties.has('path') ||
      changedProperties.has('changeNum')
    ) {
      this.syntaxHighlightingChanged(
        this.noRenderOnPrefsChange,
        changedProperties.get('prefs'),
        this.prefs,
        this.path,
        this.changeNum
      );
    }
    if (
      changedProperties.has('prefs') ||
      changedProperties.has('loadedWhitespaceLevel') ||
      changedProperties.has('noRenderOnPrefsChange') ||
      changedProperties.has('path') ||
      changedProperties.has('changeNum')
    ) {
      this.whitespaceChanged(
        this.prefs?.ignore_whitespace,
        this.loadedWhitespaceLevel,
        this.noRenderOnPrefsChange,
        this.path,
        this.changeNum
      );
    }
  }

  protected override updated(changedProperties: PropertyValues) {
    super.updated(changedProperties);
    // This needs to happen in updated() because it has to happen post-render as
    // this method calls getThreadEls which inspects the DOM.
    if (changedProperties.has('threads')) {
      this.threadsChanged(this.threads);
    }
  }

  async waitForReloadToRender(): Promise<void> {
    await this.updateComplete;
    if (this.reloadPromise) {
      try {
        // If we are reloading, wait for the reload to finish and then ensure
        // that any changes are captured in another update.
        await this.reloadPromise;
      } catch (e: unknown) {
        // TODO: Consider moving this logic to a helper method on
        if (e instanceof Error) {
          this.reporting.error(e);
        } else {
          this.reporting.error(new Error('reloadPromise error'), undefined, e);
        }
      }
      await this.updateComplete;
    }
  }

  override render() {
    const showNewlineWarningLeft =
      this.hasTrailingNewlines(this.diff, true) === false;
    const showNewlineWarningRight =
      this.hasTrailingNewlines(this.diff, false) === false;
    const useNewImageDiffUi = this.flags.isEnabled(
      KnownExperimentId.NEW_IMAGE_DIFF_UI
    );

    return html` <gr-diff
      id="diff"
      ?hidden=${this.hidden}
      .noAutoRender=${this.noAutoRender}
      .path=${this.path}
      .prefs=${this.prefs}
      .displayLine=${this.displayLine}
      .isImageDiff=${this.isImageDiff}
      .noRenderOnPrefsChange=${this.noRenderOnPrefsChange}
      .renderPrefs=${this.renderPrefs}
      .lineWrapping=${this.lineWrapping}
      .viewMode=${this.viewMode}
      .lineOfInterest=${this.lineOfInterest}
      .loggedIn=${this.loggedIn}
      .errorMessage=${this.errorMessage}
      .baseImage=${this.baseImage}
      .revisionImage=${this.revisionImage}
      .coverageRanges=${this.coverageRanges}
      .blame=${this.blame}
      .layers=${this.layers}
      .diff=${this.diff}
      .showNewlineWarningLeft=${showNewlineWarningLeft}
      .showNewlineWarningRight=${showNewlineWarningRight}
      .useNewImageDiffUi=${useNewImageDiffUi}
    ></gr-diff>`;
  }

  async initLayers() {
    const preferencesPromise = this.restApiService.getPreferences();
    await getPluginLoader().awaitPluginsLoaded();
    const prefs = await preferencesPromise;
    const enableTokenHighlight = !prefs?.disable_token_highlighting;

    assertIsDefined(this.path, 'path');
    this.layers = this.getLayers(this.path, enableTokenHighlight);
    this.coverageRanges = [];
    // We kick off fetching the data here, but we don't return the promise,
    // so awaiting initLayers() will not wait for coverage data to be
    // completely loaded.
    this.getCoverageData();
  }

  /**
   * @param shouldReportMetric indicate a new Diff Page. This is a
   * signal to report metrics event that started on location change.
   */
  reload(shouldReportMetric?: boolean): Promise<void> {
    this.reloadPromise = debounceP(
      this.reloadPromise,
      async () => {
        try {
          await this.reloadInternal(shouldReportMetric);
          return;
        } catch (e: unknown) {
          if (e instanceof Error) {
            this.reporting.error(e);
          } else {
            this.reporting.error(
              new Error('reloadInternal error'),
              undefined,
              e
            );
          }
        } finally {
          this.reloadPromise = undefined;
        }
      },
      0
    );
    return this.reloadPromise;
  }

  // for DIFF_AUTOCLOSE logging purposes only
  private reloadOngoing = false;

  async reloadInternal(shouldReportMetric?: boolean) {
    this.reporting.time(Timing.DIFF_TOTAL);
    this.reporting.time(Timing.DIFF_LOAD);
    this.clear();
    assertIsDefined(this.path, 'path');
    assertIsDefined(this.changeNum, 'changeNum');
    this.diff = undefined;
    this.errorMessage = null;
    const whitespaceLevel = this.getIgnoreWhitespace();
    if (this.reloadOngoing) {
      this.reporting.reportInteraction(Interaction.DIFF_AUTOCLOSE_DIFF_ONGOING);
    }
    this.reloadOngoing = true;

    try {
      // We are carefully orchestrating operations that have to wait for another
      // and operations that can be run in parallel. Plugins may provide layers,
      // so we have to wait on plugins being loaded before we can initialize
      // layers and proceed to rendering. OTOH we want to fetch diffs and diff
      // assets in parallel.
      const layerPromise = this.initLayers();
      const diff = await this.getDiff();
      if (diff === undefined) {
        this.reporting.reportInteraction(
          Interaction.DIFF_AUTOCLOSE_DIFF_UNDEFINED
        );
      }
      this.loadedWhitespaceLevel = whitespaceLevel;
      this.reportDiff(diff);

      await this.loadDiffAssets(diff);
      // Only now we are awaiting layers (and plugin loading), which was kicked
      // off above.
      await layerPromise;

      // Not waiting for coverage ranges intentionally as
      // plugin loading should not block the content rendering

      this.editWeblinks = this.getEditWeblinks(diff);
      this.filesWeblinks = this.getFilesWeblinks(diff);
      this.diff = diff;
      this.reporting.timeEnd(Timing.DIFF_LOAD, this.timingDetails());

      this.reporting.time(Timing.DIFF_CONTENT);
      this.syntaxLayer.setEnabled(this.isSyntaxHighlightingEnabled());
      const syntaxLayerPromise = this.syntaxLayer.process(diff);
      await waitForEventOnce(this, 'render');
      this.subscribeToChecks();
      this.reporting.timeEnd(Timing.DIFF_CONTENT, this.timingDetails());

      if (shouldReportMetric) {
        // We report diffViewContentDisplayed only on reload caused
        // by params changed - expected only on Diff Page.
        this.reporting.diffViewContentDisplayed();
      }

      this.reporting.time(Timing.DIFF_SYNTAX);
      await syntaxLayerPromise;
      this.reporting.timeEnd(Timing.DIFF_SYNTAX, this.timingDetails());
    } catch (e: unknown) {
      if (e instanceof Response) {
        this.handleGetDiffError(e);
      } else if (e instanceof Error) {
        this.reporting.error(e);
      } else {
        this.reporting.error(new Error('reload error'), undefined, e);
      }
    } finally {
      this.reporting.timeEnd(Timing.DIFF_TOTAL, this.timingDetails());
      this.reloadOngoing = false;
    }
  }

  /**
   * Produces an event detail object for reporting.
   */
  private timingDetails() {
    if (!this.diff) return {};
    const metaLines =
      (this.diff.meta_a?.lines ?? 0) + (this.diff.meta_b?.lines ?? 0);

    let contentLines = 0;
    let contentChanged = 0;
    let contentUnchanged = 0;
    for (const chunk of this.diff.content) {
      const ab = chunk.ab?.length ?? 0;
      const a = chunk.a?.length ?? 0;
      const b = chunk.b?.length ?? 0;
      contentLines += ab + ab + a + b;
      contentChanged += a + b;
      contentUnchanged += ab + ab;
    }
    return {
      metaLines,
      contentLines,
      contentUnchanged,
      contentChanged,
      height:
        this.diffElement?.shadowRoot?.querySelector('.diffContainer')
          ?.clientHeight,
    };
  }

  private getLayers(path: string, enableTokenHighlight: boolean): DiffLayer[] {
    const layers = [];
    if (enableTokenHighlight) {
      layers.push(new TokenHighlightLayer(this));
    }
    layers.push(this.syntaxLayer);
    // Get layers from plugins (if any).
    layers.push(...this.jsAPI.getDiffLayers(path));
    return layers;
  }

  clear() {
    if (this.path) this.jsAPI.disposeDiffLayers(this.path);
    this.layers = [];
  }

  /**
   * This should be called when either `path` or `patchRange` has changed.
   * We will then subscribe to the checks model and filter the relevant
   * check results for this diff. Path and patchset must match, and a code
   * pointer must be included.
   */
  private subscribeToChecks() {
    if (this.checksSubscription) {
      this.checksSubscription.unsubscribe();
      this.checksSubscription = undefined;
      this.checksChanged([]);
    }

    const path = this.path;
    const patchNum = this.patchRange?.patchNum;
    if (!path || !patchNum || patchNum === EDIT) return;
    this.checksSubscription = this.getChecksModel()
      .allResults$.pipe(
        map(results =>
          results.filter(result => {
            if (result.patchset !== patchNum) return false;
            if (result.category === Category.SUCCESS) return false;
            // Only one code pointer is supported. See API docs.
            const pointer = result.codePointers?.[0];
            return pointer?.path === this.path && !!pointer?.range;
          })
        ),
        distinctUntilChanged(deepEqual)
      )
      .subscribe(results => this.checksChanged(results));
  }

  /**
   * Similar to threadsChanged(), but a bit simpler. We compare the elements
   * that are already in <gr-diff> with the current results emitted from the
   * model. Exists? Update. New? Create and attach. Old? Remove.
   */
  private checksChanged(checks: RunResult[]) {
    const idToEl = new Map<string, GrDiffCheckResult>();
    const checkEls = this.getCheckEls();
    const dontRemove = new Set<GrDiffCheckResult>();
    let createdCount = 0;
    let updatedCount = 0;
    let removedCount = 0;
    const checksCount = checks.length;
    const checkElsCount = checks.length;
    if (checksCount === 0 && checkElsCount === 0) return;
    for (const el of checkEls) {
      const id = el.result?.internalResultId;
      assertIsDefined(id, 'result.internalResultId of gr-diff-check-result');
      idToEl.set(id, el);
    }
    for (const check of checks) {
      const id = check.internalResultId;
      const existingEl = idToEl.get(id);
      if (existingEl) {
        existingEl.result = check;
        dontRemove.add(existingEl);
        updatedCount++;
      } else {
        const newEl = this.createCheckEl(check);
        dontRemove.add(newEl);
        createdCount++;
      }
    }
    // Remove all check els that don't have a matching check anymore.
    for (const el of checkEls) {
      if (dontRemove.has(el)) continue;
      el.remove();
      removedCount++;
    }
    this.reporting.reportInteraction(
      Interaction.COMMENTS_AUTOCLOSE_CHECKS_UPDATED,
      {createdCount, updatedCount, removedCount, checksCount, checkElsCount}
    );
  }

  /**
   * This is very similar to createThreadElement(). It creates a new
   * <gr-diff-check-result> element, sets its props/attributes and adds it to
   * <gr-diff>.
   */
  // Visible for testing
  createCheckEl(check: RunResult) {
    const pointer = check.codePointers?.[0];
    assertIsDefined(pointer, 'code pointer of check result in diff');
    const line: LineNumber =
      pointer.range?.end_line || pointer.range?.start_line || 'FILE';
    const el = document.createElement('gr-diff-check-result');
    // This is what gr-diff expects, even though this is a check, not a comment.
    el.className = 'comment-thread';
    el.rootId = check.internalResultId;
    el.result = check;
    // These attributes are the "interface" between comments/checks and gr-diff.
    // <gr-comment-thread> does not care about them and is not affected by them.
    el.setAttribute('slot', `${Side.RIGHT}-${line}`);
    el.setAttribute('diff-side', `${Side.RIGHT}`);
    el.setAttribute('line-num', `${line}`);
    if (
      pointer.range?.start_line > 0 &&
      pointer.range?.end_line > 0 &&
      pointer.range?.start_character >= 0 &&
      pointer.range?.end_character >= 0
    ) {
      el.setAttribute('range', `${JSON.stringify(pointer.range)}`);
    }
    assertIsDefined(this.diffElement);
    this.diffElement.appendChild(el);
    return el;
  }

  private getCoverageData() {
    assertIsDefined(this.changeNum, 'changeNum');
    assertIsDefined(this.change, 'change');
    assertIsDefined(this.path, 'path');
    assertIsDefined(this.patchRange, 'patchRange');
    const changeNum = this.changeNum;
    const change = this.change;
    const path = this.path;
    // Coverage providers do not provide data for EDIT and PARENT patch sets.

    const toNumberOnly = (patchNum: PatchSetNum) =>
      isNumber(patchNum) ? patchNum : undefined;

    const basePatchNum = toNumberOnly(this.patchRange.basePatchNum);
    const patchNum = toNumberOnly(this.patchRange.patchNum);
    this.jsAPI
      .getCoverageAnnotationApis()
      .then(coverageAnnotationApis => {
        coverageAnnotationApis.forEach(coverageAnnotationApi => {
          const provider = coverageAnnotationApi.getCoverageProvider();
          if (!provider) return;
          provider(changeNum, path, basePatchNum, patchNum, change)
            .then(coverageRanges => {
              assertIsDefined(this.patchRange, 'patchRange');
              if (
                !coverageRanges ||
                changeNum !== this.changeNum ||
                change !== this.change ||
                path !== this.path ||
                basePatchNum !== toNumberOnly(this.patchRange.basePatchNum) ||
                patchNum !== toNumberOnly(this.patchRange.patchNum)
              ) {
                return;
              }

              const existingCoverageRanges = this.coverageRanges;
              this.coverageRanges = coverageRanges;

              // Notify with existing coverage ranges in case there is some
              // existing coverage data that needs to be removed
              existingCoverageRanges.forEach(range => {
                coverageAnnotationApi.notify(
                  path,
                  range.code_range.start_line,
                  range.code_range.end_line,
                  range.side
                );
              });

              // Notify with new coverage data
              coverageRanges.forEach(range => {
                coverageAnnotationApi.notify(
                  path,
                  range.code_range.start_line,
                  range.code_range.end_line,
                  range.side
                );
              });
            })
            .catch(err => {
              this.reporting.error(err);
            });
        });
      })
      .catch(err => {
        this.reporting.error(err);
      });
  }

  private computeFileThreads(
    changeComments?: ChangeComments,
    patchRange?: PatchRange,
    file?: PatchSetFile
  ) {
    if (!changeComments || !patchRange || !file) return this.threads;
    return changeComments.getThreadsBySideForFile(file, patchRange);
  }

  private getEditWeblinks(diff: DiffInfo) {
    if (!this.projectName || !this.commitRange || !this.path) return undefined;
    return GerritNav.getEditWebLinks(
      this.projectName,
      this.commitRange.baseCommit,
      this.path,
      {weblinks: diff?.edit_web_links}
    );
  }

  private getFilesWeblinks(diff: DiffInfo) {
    if (!this.projectName || !this.commitRange || !this.path) return undefined;
    return {
      meta_a: GerritNav.getFileWebLinks(
        this.projectName,
        this.commitRange.baseCommit,
        this.path,
        {weblinks: diff?.meta_a?.web_links}
      ),
      meta_b: GerritNav.getFileWebLinks(
        this.projectName,
        this.commitRange.commit,
        this.path,
        {weblinks: diff?.meta_b?.web_links}
      ),
    };
  }

  /** Cancel any remaining diff builder rendering work. */
  cancel() {
    this.diffElement?.cancel();
  }

  getCursorStops() {
    assertIsDefined(this.diffElement);
    return this.diffElement.getCursorStops();
  }

  isRangeSelected() {
    assertIsDefined(this.diffElement);
    return this.diffElement.isRangeSelected();
  }

  createRangeComment() {
    assertIsDefined(this.diffElement);
    this.diffElement.createRangeComment();
  }

  toggleLeftDiff() {
    assertIsDefined(this.diffElement);
    this.diffElement.toggleLeftDiff();
  }

  /**
   * Load and display blame information for the base of the diff.
   */
  loadBlame(): Promise<BlameInfo[]> {
    assertIsDefined(this.changeNum, 'changeNum');
    assertIsDefined(this.patchRange, 'patchRange');
    assertIsDefined(this.path, 'path');
    return this.restApiService
      .getBlame(this.changeNum, this.patchRange.patchNum, this.path, true)
      .then(blame => {
        if (!blame || !blame.length) {
          fireAlert(this, EMPTY_BLAME);
          return Promise.reject(EMPTY_BLAME);
        }

        this.blame = blame;
        return blame;
      });
  }

  clearBlame() {
    this.blame = null;
  }

  getThreadEls(): GrCommentThread[] {
    assertIsDefined(this.diffElement);
    return Array.from(this.diffElement.querySelectorAll('gr-comment-thread'));
  }

  getCheckEls(): GrDiffCheckResult[] {
    return Array.from(
      this.diffElement?.querySelectorAll('gr-diff-check-result') ?? []
    );
  }

  addDraftAtLine(el: Element) {
    assertIsDefined(this.diffElement);
    this.diffElement.addDraftAtLine(el);
  }

  clearDiffContent() {
    this.diffElement?.clearDiffContent();
  }

  toggleAllContext() {
    assertIsDefined(this.diffElement);
    this.diffElement.toggleAllContext();
  }

  // TODO(milutin): Use rest-api with fetchCacheURL instead of this.
  prefetchDiff() {
    if (
      !!this.changeNum &&
      !!this.patchRange &&
      !!this.path &&
      this.fetchDiffPromise === null
    ) {
      this.fetchDiffPromise = this.getDiff();
    }
  }

  // Private but used in tests.
  getDiff(): Promise<DiffInfo> {
    if (this.fetchDiffPromise !== null) {
      const fetchDiffPromise = this.fetchDiffPromise;
      this.fetchDiffPromise = null;
      return fetchDiffPromise;
    }
    // Wrap the diff request in a new promise so that the error handler
    // rejects the promise, allowing the error to be handled in the .catch.
    return new Promise((resolve, reject) => {
      assertIsDefined(this.changeNum, 'changeNum');
      assertIsDefined(this.patchRange, 'patchRange');
      assertIsDefined(this.path, 'path');
      this.restApiService
        .getDiff(
          this.changeNum,
          this.patchRange.basePatchNum,
          this.patchRange.patchNum,
          this.path,
          this.getIgnoreWhitespace(),
          reject
        )
        .then(diff => resolve(diff!)); // reject is called in case of error, so we can't get undefined here
    });
  }

  // Private but used in tests.
  handleGetDiffError(response: Response) {
    // Loading the diff may respond with 409 if the file is too large. In this
    // case, use a toast error..
    if (response.status === 409) {
      fireServerError(response);
      return;
    }

    if (this.showLoadFailure) {
      this.errorMessage = [
        'Encountered error when loading the diff:',
        response.status,
        response.statusText,
      ].join(' ');
      return;
    }

    firePageError(response);
  }

  /**
   * Report info about the diff response.
   *
   * Private but used in tests.
   */
  reportDiff(diff?: DiffInfo) {
    if (!diff || !diff.content) return;

    // Count the delta lines stemming from normal deltas, and from
    // due_to_rebase deltas.
    let nonRebaseDelta = 0;
    let rebaseDelta = 0;
    diff.content.forEach(chunk => {
      if (chunk.ab) {
        return;
      }
      const deltaSize = Math.max(
        chunk.a ? chunk.a.length : 0,
        chunk.b ? chunk.b.length : 0
      );
      if (chunk.due_to_rebase) {
        rebaseDelta += deltaSize;
      } else {
        nonRebaseDelta += deltaSize;
      }
    });

    // Find the percent of the delta from due_to_rebase chunks rounded to two
    // digits. Diffs with no delta are considered 0%.
    const totalDelta = rebaseDelta + nonRebaseDelta;
    const percentRebaseDelta = !totalDelta
      ? 0
      : Math.round((100 * rebaseDelta) / totalDelta);

    // Report the due_to_rebase percentage in the "diff" category when
    // applicable.
    assertIsDefined(this.patchRange, 'patchRange');
    if (this.patchRange.basePatchNum === PARENT) {
      this.reporting.reportInteraction(EVENT_AGAINST_PARENT);
    } else if (percentRebaseDelta === 0) {
      this.reporting.reportInteraction(EVENT_ZERO_REBASE);
    } else {
      this.reporting.reportInteraction(EVENT_NONZERO_REBASE, {
        percentRebaseDelta,
      });
    }
  }

  private loadDiffAssets(diff?: DiffInfo) {
    if (isImageDiff(diff)) {
      // diff! is justified, because isImageDiff() returns false otherwise
      return this.getImages(diff!).then(images => {
        this.baseImage = images.baseImage ?? undefined;
        this.revisionImage = images.revisionImage ?? undefined;
      });
    } else {
      this.baseImage = undefined;
      this.revisionImage = undefined;
      return Promise.resolve();
    }
  }

  private threadsChanged(threads: CommentThread[]) {
    const rootIdToThreadEl = new Map<UrlEncodedCommentId, GrCommentThread>();
    const unsavedThreadEls: GrCommentThread[] = [];
    const threadEls = this.getThreadEls();
    for (const threadEl of threadEls) {
      if (threadEl.rootId) {
        rootIdToThreadEl.set(threadEl.rootId, threadEl);
      } else {
        // Unsaved thread els must have editing:true, just being defensive here.
        if (threadEl.editing) unsavedThreadEls.push(threadEl);
      }
    }
    const dontRemove = new Set<GrCommentThread>();
    let createdCount = 0;
    let updatedCount = 0;
    let removedCount = 0;
    const threadCount = threads.length;
    const threadElCount = threadEls.length;
    if (threadCount === 0 && threadElCount === 0) return;

    for (const thread of threads) {
      // Let's find an existing DOM element matching the thread. Normally this
      // is as simple as matching the rootIds.
      let existingThreadEl =
        thread.rootId && rootIdToThreadEl.get(thread.rootId);
      // But unsaved threads don't have rootIds. The incoming thread might be
      // the saved version of the unsaved thread element. To verify that we
      // check that the thread only has one comment and that their location is
      // identical.
      // TODO(brohlfs): This matching is not perfect. You could quickly create
      // two new threads on the same line/range. Then this code just makes a
      // random guess.
      if (!existingThreadEl && thread.comments?.length === 1) {
        for (const unsavedThreadEl of unsavedThreadEls) {
          if (equalLocation(unsavedThreadEl.thread, thread)) {
            existingThreadEl = unsavedThreadEl;
            break;
          }
        }
      }
      // There is a case possible where the rootIds match but the locations
      // are different. Such as when a thread was originally attached on the
      // right side of the diff but now should be attached on the left side of
      // the diff.
      // There is another case possible where the original thread element was
      // associated with a ported thread, hence had the LineNum set to LOST.
      // In this case we cannot reuse the thread element if the same thread
      // now is being attached in it's proper location since the LineNum needs
      // to be updated hence create a new thread element.
      if (
        existingThreadEl &&
        existingThreadEl.getAttribute('diff-side') ===
          this.getDiffSide(thread) &&
        existingThreadEl.thread!.ported === thread.ported
      ) {
        existingThreadEl.thread = thread;
        dontRemove.add(existingThreadEl);
        updatedCount++;
      } else {
        const threadEl = this.createThreadElement(thread);
        this.attachThreadElement(threadEl);
        dontRemove.add(threadEl);
        createdCount++;
      }
    }
    // Remove all threads that are no longer existing.
    for (const threadEl of this.getThreadEls()) {
      if (dontRemove.has(threadEl)) continue;
      // The user may have opened a couple of comment boxes for editing. They
      // might be unsaved and thus not be reflected in `threads` yet, so let's
      // keep them open.
      if (threadEl.editing && threadEl.thread?.comments.length === 0) continue;
      removedCount++;
      threadEl.remove();
    }
    this.reporting.reportInteraction(
      Interaction.COMMENTS_AUTOCLOSE_THREADS_UPDATED,
      {createdCount, updatedCount, removedCount, threadCount, threadElCount}
    );
    const portedThreadsCount = threads.filter(thread => thread.ported).length;
    const portedThreadsWithoutRange = threads.filter(
      thread => thread.ported && thread.rangeInfoLost
    ).length;
    if (portedThreadsCount > 0) {
      this.reporting.reportInteraction('ported-threads-shown', {
        ported: portedThreadsCount,
        portedThreadsWithoutRange,
      });
    }
  }

  private getImages(diff: DiffInfo) {
    assertIsDefined(this.changeNum, 'changeNum');
    assertIsDefined(this.patchRange, 'patchRange');
    return this.restApiService.getImagesForDiff(
      this.changeNum,
      diff,
      this.patchRange
    );
  }

  handleCreateThread(e: CustomEvent<CreateCommentEventDetail>) {
    if (!this.patchRange) throw Error('patch range not set');

    const {lineNum, side, range} = e.detail;

    // Usually, the comment is stored on the patchset shown on the side the
    // user added the comment on, and the commentSide will be REVISION.
    // However, if the comment is added on the left side of the diff and the
    // version shown there is not a patchset that is part the change, but
    // instead a base (a PARENT or a merge parent commit), the comment is
    // stored on the patchset shown on the right, and commentSide=PARENT
    // indicates that the comment should still be shown on the left side.
    const patchNum =
      side === Side.LEFT && !isAParent(this.patchRange.basePatchNum)
        ? this.patchRange.basePatchNum
        : this.patchRange.patchNum;
    const commentSide =
      side === Side.LEFT && isAParent(this.patchRange.basePatchNum)
        ? CommentSide.PARENT
        : CommentSide.REVISION;
    if (!this.canCommentOnPatchSetNum(patchNum)) return;
    const path =
      this.file?.basePath &&
      side === Side.LEFT &&
      commentSide === CommentSide.REVISION
        ? this.file?.basePath
        : this.path;
    assertIsDefined(path, 'path');

    const parentIndex = this.computeParentIndex();
    const newThread: CommentThread = {
      rootId: undefined,
      comments: [],
      patchNum: patchNum as RevisionPatchSetNum,
      commentSide,
      // TODO: Maybe just compute from patchRange.base on the fly?
      mergeParentNum: parentIndex ?? undefined,
      path,
      line: lineNum,
      range,
    };
    const el = this.createThreadElement(newThread);
    this.attachThreadElement(el);
  }

  private canCommentOnPatchSetNum(patchNum: PatchSetNum) {
    if (!this.loggedIn) {
      fireEvent(this, 'show-auth-required');
      return false;
    }
    if (!this.patchRange) {
      fireAlert(this, 'Cannot create comment. patchRange undefined.');
      return false;
    }

    const isEdit = patchNum === EDIT;
    const isEditBase = patchNum === PARENT && this.patchRange.patchNum === EDIT;

    if (isEdit) {
      fireAlert(this, 'You cannot comment on an edit.');
      return false;
    }
    if (isEditBase) {
      fireAlert(this, 'You cannot comment on the base patchset of an edit.');
      return false;
    }
    return true;
  }

  private attachThreadElement(threadEl: Element) {
    assertIsDefined(this.diffElement);
    this.diffElement.appendChild(threadEl);
  }

  private getDiffSide(thread: CommentThread) {
    let diffSide: Side;
    assertIsDefined(this.patchRange, 'patchRange');
    const commentProps = {
      patch_set: thread.patchNum,
      side: thread.commentSide,
      parent: thread.mergeParentNum,
    };
    if (isInBaseOfPatchRange(commentProps, this.patchRange)) {
      diffSide = Side.LEFT;
    } else if (isInRevisionOfPatchRange(commentProps, this.patchRange)) {
      diffSide = Side.RIGHT;
    } else {
      const propsStr = JSON.stringify(commentProps);
      const rangeStr = JSON.stringify(this.patchRange);
      throw new Error(`comment ${propsStr} not in range ${rangeStr}`);
    }
    return diffSide;
  }

  private createThreadElement(thread: CommentThread) {
    const diffSide = this.getDiffSide(thread);

    const threadEl = document.createElement('gr-comment-thread');
    threadEl.className = 'comment-thread';
    threadEl.rootId = thread.rootId;
    threadEl.thread = thread;
    threadEl.showPatchset = false;
    threadEl.showPortedComment = !!thread.ported;
    // These attributes are the "interface" between comment threads and gr-diff.
    // <gr-comment-thread> does not care about them and is not affected by them.
    threadEl.setAttribute('slot', `${diffSide}-${thread.line || 'LOST'}`);
    threadEl.setAttribute('diff-side', `${diffSide}`);
    threadEl.setAttribute('line-num', `${thread.line || 'LOST'}`);
    if (thread.range) {
      threadEl.setAttribute('range', `${JSON.stringify(thread.range)}`);
    }
    return threadEl;
  }

  // Private but used in tests.
  filterThreadElsForLocation(
    threadEls: GrCommentThread[],
    lineInfo: LineInfo,
    side: Side
  ) {
    function matchesLeftLine(threadEl: GrCommentThread) {
      return (
        getSide(threadEl) === Side.LEFT &&
        getLine(threadEl) === lineInfo.beforeNumber
      );
    }
    function matchesRightLine(threadEl: GrCommentThread) {
      return (
        getSide(threadEl) === Side.RIGHT &&
        getLine(threadEl) === lineInfo.afterNumber
      );
    }
    function matchesFileComment(threadEl: GrCommentThread) {
      return getSide(threadEl) === side && getLine(threadEl) === FILE;
    }

    // Select the appropriate matchers for the desired side and line
    const matchers: ((thread: GrCommentThread) => boolean)[] = [];
    if (side === Side.LEFT) {
      matchers.push(matchesLeftLine);
    }
    if (side === Side.RIGHT) {
      matchers.push(matchesRightLine);
    }
    if (lineInfo.afterNumber === FILE || lineInfo.beforeNumber === FILE) {
      matchers.push(matchesFileComment);
    }
    return threadEls.filter(threadEl =>
      matchers.some(matcher => matcher(threadEl))
    );
  }

  private getIgnoreWhitespace(): IgnoreWhitespaceType {
    if (!this.prefs || !this.prefs.ignore_whitespace) {
      return 'IGNORE_NONE';
    }
    return this.prefs.ignore_whitespace;
  }

  private whitespaceChanged(
    preferredWhitespaceLevel: IgnoreWhitespaceType | undefined,
    loadedWhitespaceLevel: IgnoreWhitespaceType | undefined,
    noRenderOnPrefsChange: boolean | undefined,
    path: string | undefined,
    changeNum: NumericChangeId | undefined
  ): void | Promise<void> {
    if (preferredWhitespaceLevel === undefined) return;
    if (loadedWhitespaceLevel === undefined) return;
    if (noRenderOnPrefsChange === undefined) return;
    if (path === undefined) return;
    if (changeNum === undefined) return;

    this.fetchDiffPromise = null;
    if (
      preferredWhitespaceLevel !== loadedWhitespaceLevel &&
      !noRenderOnPrefsChange
    ) {
      this.reporting.reportInteraction(
        Interaction.DIFF_AUTOCLOSE_RELOAD_ON_WHITESPACE
      );
      return this.reload();
    }
  }

  private syntaxHighlightingChanged(
    noRenderOnPrefsChange: boolean | undefined,
    oldPrefs: DiffPreferencesInfo | undefined,
    prefs: DiffPreferencesInfo | undefined,
    path: string | undefined,
    changeNum: NumericChangeId | undefined
  ): void | Promise<void> {
    if (noRenderOnPrefsChange === undefined) return;
    if (prefs === undefined) return;
    if (path === undefined) return;
    if (changeNum === undefined) return;
    if (oldPrefs?.syntax_highlighting === prefs.syntax_highlighting) return;

    if (!noRenderOnPrefsChange) {
      this.reporting.reportInteraction(
        Interaction.DIFF_AUTOCLOSE_RELOAD_ON_SYNTAX
      );
      return this.reload();
    }
  }

  private computeParentIndex() {
    if (!this.patchRange) return null;
    return isMergeParent(this.patchRange.basePatchNum)
      ? getParentIndex(this.patchRange.basePatchNum)
      : null;
  }

  private isSyntaxHighlightingEnabled() {
    if (!this.prefs?.syntax_highlighting || !this.diff) {
      return false;
    }
    if (anyLineTooLong(this.diff)) {
      fireAlert(
        this,
        `Files with line longer than ${SYNTAX_MAX_LINE_LENGTH} characters` +
          '  will not be syntax highlighted.'
      );
      return false;
    }
    assertIsDefined(this.diffElement);
    if (getDiffLength(this.diff) > CODE_MAX_LINES) {
      fireAlert(
        this,
        `Files with more than ${CODE_MAX_LINES} lines` +
          '  will not be syntax highlighted.'
      );
      return false;
    }
    return true;
  }

  private handleDiffContextExpanded(
    e: CustomEvent<DiffContextExpandedEventDetail>
  ) {
    this.reporting.reportInteraction('diff-context-expanded', {
      numLines: e.detail.numLines,
    });
  }

  /**
   * Find the last chunk for the given side.
   *
   * @param leftSide true if checking the base of the diff,
   * false if testing the revision.
   * @return returns the chunk object or null if there was
   * no chunk for that side.
   *
   * Private but used in tests.
   */
  lastChunkForSide(diff: DiffInfo | undefined, leftSide: boolean) {
    if (!diff?.content.length) {
      return null;
    }

    let chunkIndex = diff.content.length;
    let chunk;

    // Walk backwards until we find a chunk for the given side.
    do {
      chunkIndex--;
      chunk = diff.content[chunkIndex];
    } while (
      // We haven't reached the beginning.
      chunkIndex >= 0 &&
      // The chunk doesn't have both sides.
      !chunk.ab &&
      // The chunk doesn't have the given side.
      ((leftSide && (!chunk.a || !chunk.a.length)) ||
        (!leftSide && (!chunk.b || !chunk.b.length)))
    );

    // If we reached the beginning of the diff and failed to find a chunk
    // with the given side, return null.
    if (chunkIndex === -1) {
      return null;
    }

    return chunk;
  }

  /**
   * Check whether the specified side of the diff has a trailing newline.
   *
   * @param leftSide true if checking the base of the diff,
   * false if testing the revision.
   * @return Return true if the side has a trailing newline.
   * Return false if it doesn't. Return null if not applicable (for
   * example, if the diff has no content on the specified side).
   *
   * Private but used in tests.
   */
  hasTrailingNewlines(diff: DiffInfo | undefined, leftSide: boolean) {
    const chunk = this.lastChunkForSide(diff, leftSide);
    if (!chunk) return null;
    let lines;
    if (chunk.ab) {
      lines = chunk.ab;
    } else {
      lines = leftSide ? chunk.a : chunk.b;
    }
    if (!lines) return null;
    return lines[lines.length - 1] === '';
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'gr-diff-host': GrDiffHost;
  }
}
