/**
 * @license
 * Copyright 2015 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import '../../../styles/shared-styles';
import '../../../elements/shared/gr-button/gr-button';
import '../../../elements/shared/gr-icon/gr-icon';
import '../gr-diff-builder/gr-diff-builder-element';
import '../gr-diff-highlight/gr-diff-highlight';
import '../gr-diff-selection/gr-diff-selection';
import '../gr-syntax-themes/gr-syntax-theme';
import '../gr-ranged-comment-themes/gr-ranged-comment-theme';
import '../gr-ranged-comment-hint/gr-ranged-comment-hint';
import {LineNumber} from './gr-diff-line';
import {
  getLine,
  getLineElByChild,
  getLineNumber,
  getRange,
  getSide,
  GrDiffThreadElement,
  isLongCommentRange,
  isThreadEl,
  rangesEqual,
  getResponsiveMode,
  isResponsive,
  getDiffLength,
} from './gr-diff-utils';
import {BlameInfo, CommentRange, ImageInfo} from '../../../types/common';
import {DiffInfo, DiffPreferencesInfo} from '../../../types/diff';
import {
  CreateRangeCommentEventDetail,
  GrDiffHighlight,
} from '../gr-diff-highlight/gr-diff-highlight';
import {
  GrDiffBuilderElement,
  getLineNumberCellWidth,
} from '../gr-diff-builder/gr-diff-builder-element';
import {CoverageRange, DiffLayer} from '../../../types/types';
import {CommentRangeLayer} from '../gr-ranged-comment-layer/gr-ranged-comment-layer';
import {
  createDefaultDiffPrefs,
  DiffViewMode,
  Side,
} from '../../../constants/constants';
import {KeyLocations} from '../gr-diff-processor/gr-diff-processor';
import {fire, fireAlert} from '../../../utils/event-util';
import {MovedLinkClickedEvent, ValueChangedEvent} from '../../../types/events';
import {getContentEditableRange} from '../../../utils/safari-selection-util';
import {AbortStop} from '../../../api/core';
import {
  CreateCommentEventDetail as CreateCommentEventDetailApi,
  RenderPreferences,
  GrDiff as GrDiffApi,
  DisplayLine,
} from '../../../api/diff';
import {isSafari, toggleClass} from '../../../utils/dom-util';
import {assertIsDefined} from '../../../utils/common-util';
import {
  debounceP,
  DelayedPromise,
  DELAYED_CANCELLATION,
} from '../../../utils/async-util';
import {GrDiffSelection} from '../gr-diff-selection/gr-diff-selection';
import {customElement, property, query, state} from 'lit/decorators.js';
import {sharedStyles} from '../../../styles/shared-styles';
import {html, LitElement, nothing, PropertyValues} from 'lit';
import {when} from 'lit/directives/when.js';
import {grSyntaxTheme} from '../gr-syntax-themes/gr-syntax-theme';
import {grRangedCommentTheme} from '../gr-ranged-comment-themes/gr-ranged-comment-theme';
import {classMap} from 'lit/directives/class-map.js';
import {iconStyles} from '../../../styles/gr-icon-styles';
import {expandFileMode} from '../../../utils/file-util';
import {DiffModel, diffModelToken} from '../gr-diff-model/gr-diff-model';
import {provide} from '../../../models/dependency';
import {grDiffStyles} from './gr-diff-styles';

const NO_NEWLINE_LEFT = 'No newline at end of left file.';
const NO_NEWLINE_RIGHT = 'No newline at end of right file.';

const LARGE_DIFF_THRESHOLD_LINES = 10000;
const FULL_CONTEXT = -1;

const COMMIT_MSG_PATH = '/COMMIT_MSG';
/**
 * 72 is the unofficial length standard for git commit messages.
 * Derived from the fact that git log/show appends 4 ws in the beginning of
 * each line when displaying commit messages. To center the commit message
 * in an 80 char terminal a 4 ws border is added to the rightmost side:
 * 4 + 72 + 4
 */
const COMMIT_MSG_LINE_LENGTH = 72;

export interface CreateCommentEventDetail extends CreateCommentEventDetailApi {
  path: string;
}

@customElement('gr-diff')
export class GrDiff extends LitElement implements GrDiffApi {
  /**
   * Fired when the user selects a line.
   *
   * @event line-selected
   */

  /**
   * Fired if being logged in is required.
   *
   * @event show-auth-required
   */

  /**
   * Fired when a comment is created
   *
   * @event create-comment
   */

  /**
   * Fired when rendering, including syntax highlighting, is done. Also fired
   * when no rendering can be done because required preferences are not set.
   *
   * @event render
   */

  /**
   * Fired for interaction reporting when a diff context is expanded.
   * Contains an event.detail with numLines about the number of lines that
   * were expanded.
   *
   * @event diff-context-expanded
   */

  @query('#diffTable')
  diffTable?: HTMLTableElement;

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

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

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

  @property({type: Object})
  renderPrefs: RenderPreferences = {};

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

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

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

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

  // explicitly highlight a range if it is not associated with any comment
  @property({type: Object})
  highlightRange?: CommentRange;

  @property({type: Array})
  coverageRanges: CoverageRange[] = [];

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

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

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

  /**
   * True when diff is changed, until the content is done rendering.
   * Use getter/setter loading instead of this.
   */
  private _loading = true;

  get loading() {
    return this._loading;
  }

  set loading(loading: boolean) {
    if (this._loading === loading) return;
    const oldLoading = this._loading;
    this._loading = loading;
    fire(this, 'loading-changed', {value: this._loading});
    this.requestUpdate('loading', oldLoading);
  }

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

  @property({type: Object})
  diff?: DiffInfo;

  @state()
  private diffTableClass = '';

  @property({type: Object})
  baseImage?: ImageInfo;

  @property({type: Object})
  revisionImage?: ImageInfo;

  /**
   * In order to allow multi-select in Safari browsers, a workaround is required
   * to trigger 'beforeinput' events to get a list of static ranges. This is
   * obtained by making the content of the diff table "contentEditable".
   */
  @property({type: Boolean})
  override isContentEditable = isSafari();

  /**
   * Whether the safety check for large diffs when whole-file is set has
   * been bypassed. If the value is null, then the safety has not been
   * bypassed. If the value is a number, then that number represents the
   * context preference to use when rendering the bypassed diff.
   *
   * Private but used in tests.
   */
  @state()
  safetyBypass: number | null = null;

  // Private but used in tests.
  @state()
  showWarning?: boolean;

  @property({type: String})
  errorMessage: string | null = null;

  @property({type: Array})
  blame: BlameInfo[] | null = null;

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

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

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

  // Private but used in tests.
  @state()
  diffLength?: number;

  /**
   * Observes comment nodes added or removed at any point.
   * Can be used to unregister upon detachment.
   */
  private nodeObserver?: MutationObserver;

  @property({type: Array})
  layers?: DiffLayer[];

  // Private but used in tests.
  renderDiffTableTask?: DelayedPromise<void>;

  // Private but used in tests.
  diffSelection = new GrDiffSelection();

  // Private but used in tests.
  highlights = new GrDiffHighlight();

  // Private but used in tests.
  diffBuilder = new GrDiffBuilderElement();

  private diffModel = new DiffModel(undefined);

  static override get styles() {
    return [
      iconStyles,
      sharedStyles,
      grSyntaxTheme,
      grRangedCommentTheme,
      grDiffStyles,
    ];
  }

  constructor() {
    super();
    provide(this, diffModelToken, () => this.diffModel);
    this.addEventListener(
      'create-range-comment',
      (e: CustomEvent<CreateRangeCommentEventDetail>) =>
        this.handleCreateRangeComment(e)
    );
    this.addEventListener('render-content', () => this.handleRenderContent());
    this.addEventListener('moved-link-clicked', (e: MovedLinkClickedEvent) => {
      this.dispatchSelectedLine(e.detail.lineNum, e.detail.side);
    });
  }

  override connectedCallback() {
    super.connectedCallback();
    if (this.loggedIn) {
      this.addSelectionListeners();
    }
    if (this.diff && this.diffTable) {
      this.diffSelection.init(this.diff, this.diffTable);
    }
    if (this.diffTable && this.diffBuilder) {
      this.highlights.init(this.diffTable, this.diffBuilder);
    }
    this.diffBuilder.init();
  }

  override disconnectedCallback() {
    this.removeSelectionListeners();
    this.renderDiffTableTask?.cancel();
    this.diffSelection.cleanup();
    this.highlights.cleanup();
    this.diffBuilder.cleanup();
    super.disconnectedCallback();
  }

  protected override willUpdate(changedProperties: PropertyValues<this>): void {
    if (
      changedProperties.has('path') ||
      changedProperties.has('lineWrapping') ||
      changedProperties.has('viewMode') ||
      changedProperties.has('useNewImageDiffUi') ||
      changedProperties.has('prefs')
    ) {
      this.prefsChanged();
    }
    if (changedProperties.has('blame')) {
      this.blameChanged();
    }
    if (changedProperties.has('renderPrefs')) {
      this.renderPrefsChanged();
    }
    if (changedProperties.has('loggedIn')) {
      if (this.loggedIn && this.isConnected) {
        this.addSelectionListeners();
      } else {
        this.removeSelectionListeners();
      }
    }
    if (changedProperties.has('coverageRanges')) {
      this.diffBuilder.updateCoverageRanges(this.coverageRanges);
    }
    if (changedProperties.has('lineOfInterest')) {
      this.lineOfInterestChanged();
    }
  }

  protected override updated(changedProperties: PropertyValues<this>): void {
    if (changedProperties.has('diff')) {
      // diffChanged relies on diffTable ahving been rendered.
      this.diffChanged();
    }
  }

  override render() {
    return html`
      ${this.renderHeader()} ${this.renderContainer()}
      ${this.renderNewlineWarning()} ${this.renderLoadingError()}
      ${this.renderSizeWarning()}
    `;
  }

  private renderHeader() {
    const diffheaderItems = this.computeDiffHeaderItems();
    if (diffheaderItems.length === 0) return nothing;
    return html`
      <div id="diffHeader">
        ${diffheaderItems.map(item => html`<div>${item}</div>`)}
      </div>
    `;
  }

  private renderContainer() {
    const cssClasses = {
      diffContainer: true,
      unified: this.viewMode === DiffViewMode.UNIFIED,
      sideBySide: this.viewMode === DiffViewMode.SIDE_BY_SIDE,
      canComment: this.loggedIn,
    };
    return html`
      <div class=${classMap(cssClasses)} @click=${this.handleTap}>
        <table
          id="diffTable"
          class=${this.diffTableClass}
          ?contenteditable=${this.isContentEditable}
        ></table>
        ${when(
          this.showNoChangeMessage(),
          () => html`
            <div class="whitespace-change-only-message">
              This file only contains whitespace changes. Modify the whitespace
              setting to see the changes.
            </div>
          `
        )}
      </div>
    `;
  }

  private renderNewlineWarning() {
    const newlineWarning = this.computeNewlineWarning();
    if (!newlineWarning) return nothing;
    return html`<div class="newlineWarning">${newlineWarning}</div>`;
  }

  private renderLoadingError() {
    if (!this.errorMessage) return nothing;
    return html`<div id="loadingError">${this.errorMessage}</div>`;
  }

  private renderSizeWarning() {
    if (!this.showWarning) return nothing;
    // TODO: Update comment about 'Whole file' as it's not in settings.
    return html`
      <div id="sizeWarning">
        <p>
          Prevented render because "Whole file" is enabled and this diff is very
          large (about ${this.diffLength} lines).
        </p>
        <gr-button @click=${this.collapseContext}>
          Render with limited context
        </gr-button>
        <gr-button @click=${this.handleFullBypass}>
          Render anyway (may be slow)
        </gr-button>
      </div>
    `;
  }

  private addSelectionListeners() {
    document.addEventListener('selectionchange', this.handleSelectionChange);
    document.addEventListener('mouseup', this.handleMouseUp);
  }

  private removeSelectionListeners() {
    document.removeEventListener('selectionchange', this.handleSelectionChange);
    document.removeEventListener('mouseup', this.handleMouseUp);
  }

  getLineNumEls(side: Side): HTMLElement[] {
    return this.diffBuilder.getLineNumEls(side);
  }

  // Private but used in tests.
  showNoChangeMessage() {
    return (
      !this.loading &&
      this.diff &&
      !this.diff.binary &&
      this.prefs &&
      this.prefs.ignore_whitespace !== 'IGNORE_NONE' &&
      this.diffLength === 0
    );
  }

  private readonly handleSelectionChange = () => {
    // Because of shadow DOM selections, we handle the selectionchange here,
    // and pass the shadow DOM selection into gr-diff-highlight, where the
    // corresponding range is determined and normalized.
    const selection = this.getShadowOrDocumentSelection();
    this.highlights.handleSelectionChange(selection, false);
  };

  private readonly handleMouseUp = () => {
    // To handle double-click outside of text creating comments, we check on
    // mouse-up if there's a selection that just covers a line change. We
    // can't do that on selection change since the user may still be dragging.
    const selection = this.getShadowOrDocumentSelection();
    this.highlights.handleSelectionChange(selection, true);
  };

  /** Gets the current selection, preferring the shadow DOM selection. */
  private getShadowOrDocumentSelection() {
    // When using native shadow DOM, the selection returned by
    // document.getSelection() cannot reference the actual DOM elements making
    // up the diff in Safari because they are in the shadow DOM of the gr-diff
    // element. This takes the shadow DOM selection if one exists.
    return this.shadowRoot?.getSelection
      ? this.shadowRoot.getSelection()
      : isSafari()
      ? getContentEditableRange()
      : document.getSelection();
  }

  private updateRanges(
    addedThreadEls: GrDiffThreadElement[],
    removedThreadEls: GrDiffThreadElement[]
  ) {
    function commentRangeFromThreadEl(
      threadEl: GrDiffThreadElement
    ): CommentRangeLayer | undefined {
      const side = getSide(threadEl);
      if (!side) return undefined;
      const range = getRange(threadEl);
      if (!range) return undefined;

      return {side, range, rootId: threadEl.rootId};
    }

    // TODO(brohlfs): Rewrite `.map().filter() as ...` with `.reduce()` instead.
    const addedCommentRanges = addedThreadEls
      .map(commentRangeFromThreadEl)
      .filter(range => !!range) as CommentRangeLayer[];
    const removedCommentRanges = removedThreadEls
      .map(commentRangeFromThreadEl)
      .filter(range => !!range) as CommentRangeLayer[];
    for (const removedCommentRange of removedCommentRanges) {
      const i = this.commentRanges.findIndex(
        cr =>
          cr.side === removedCommentRange.side &&
          rangesEqual(cr.range, removedCommentRange.range)
      );
      this.commentRanges.splice(i, 1);
    }

    if (addedCommentRanges?.length) {
      this.commentRanges.push(...addedCommentRanges);
    }
    if (this.highlightRange) {
      this.commentRanges.push({
        side: Side.RIGHT,
        range: this.highlightRange,
        rootId: '',
      });
    }

    this.diffBuilder.updateCommentRanges(this.commentRanges);
  }

  /**
   * The key locations based on the comments and line of interests,
   * where lines should not be collapsed.
   *
   */
  private computeKeyLocations() {
    const keyLocations: KeyLocations = {left: {}, right: {}};
    if (this.lineOfInterest) {
      const side = this.lineOfInterest.side;
      keyLocations[side][this.lineOfInterest.lineNum] = true;
    }
    const threadEls = [...this.childNodes].filter(isThreadEl);

    for (const threadEl of threadEls) {
      const side = getSide(threadEl);
      if (!side) continue;
      const lineNum = getLine(threadEl);
      const commentRange = getRange(threadEl);
      keyLocations[side][lineNum] = true;
      // Add start_line as well if exists,
      // the being and end of the range should not be collapsed.
      if (commentRange?.start_line) {
        keyLocations[side][commentRange.start_line] = true;
      }
    }
    return keyLocations;
  }

  // Dispatch events that are handled by the gr-diff-highlight.
  private redispatchHoverEvents(
    hoverEl: HTMLElement,
    threadEl: GrDiffThreadElement
  ) {
    hoverEl.addEventListener('mouseenter', () => {
      fire(threadEl, 'comment-thread-mouseenter', {});
    });
    hoverEl.addEventListener('mouseleave', () => {
      fire(threadEl, 'comment-thread-mouseleave', {});
    });
  }

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

  getCursorStops(): Array<HTMLElement | AbortStop> {
    if (this.hidden && this.noAutoRender) return [];

    // Get rendered stops.
    const stops: Array<HTMLElement | AbortStop> =
      this.diffBuilder.getLineNumberRows();

    // If we are still loading this diff, abort after the rendered stops to
    // avoid skipping over to e.g. the next file.
    if (this.loading) {
      stops.push(new AbortStop());
    }
    return stops;
  }

  isRangeSelected() {
    return !!this.highlights.selectedRange;
  }

  toggleLeftDiff() {
    toggleClass(this, 'no-left');
  }

  private blameChanged() {
    this.diffBuilder.setBlame(this.blame);
    if (this.blame) {
      this.classList.add('showBlame');
    } else {
      this.classList.remove('showBlame');
    }
  }

  // Private but used in tests.
  handleTap(e: Event) {
    const el = e.target as Element;

    if (
      el.getAttribute('data-value') !== 'LOST' &&
      (el.classList.contains('lineNum') ||
        el.classList.contains('lineNumButton'))
    ) {
      this.addDraftAtLine(el);
    } else if (
      el.tagName === 'HL' ||
      el.classList.contains('content') ||
      el.classList.contains('contentText')
    ) {
      const target = getLineElByChild(el);
      if (target) {
        this.selectLine(target);
      }
    }
  }

  // Private but used in tests.
  selectLine(el: Element) {
    const lineNumber = Number(el.getAttribute('data-value'));
    const side = el.classList.contains('left') ? Side.LEFT : Side.RIGHT;
    this.dispatchSelectedLine(lineNumber, side);
  }

  private dispatchSelectedLine(number: LineNumber, side: Side) {
    fire(this, 'line-selected', {
      number,
      side,
      path: this.path,
    });
  }

  addDraftAtLine(el: Element) {
    this.selectLine(el);

    const lineNum = getLineNumber(el);
    if (lineNum === null) {
      fireAlert(this, 'Invalid line number');
      return;
    }

    this.createComment(el, lineNum);
  }

  createRangeComment() {
    if (!this.isRangeSelected()) {
      throw Error('Selection is needed for new range comment');
    }
    const selectedRange = this.highlights.selectedRange;
    if (!selectedRange) throw Error('selected range not set');
    const {side, range} = selectedRange;
    this.createCommentForSelection(side, range);
  }

  createCommentForSelection(side: Side, range: CommentRange) {
    const lineNum = range.end_line;
    const lineEl = this.diffBuilder.getLineElByNumber(lineNum, side);
    if (lineEl) {
      this.createComment(lineEl, lineNum, side, range);
    }
  }

  private handleCreateRangeComment(
    e: CustomEvent<CreateRangeCommentEventDetail>
  ) {
    const range = e.detail.range;
    const side = e.detail.side;
    this.createCommentForSelection(side, range);
  }

  // Private but used in tests.
  createComment(
    lineEl: Element,
    lineNum: LineNumber,
    side?: Side,
    range?: CommentRange
  ) {
    const contentEl = this.diffBuilder.getContentTdByLineEl(lineEl);
    if (!contentEl) throw new Error('content el not found for line el');
    side = side ?? this.getCommentSideByLineAndContent(lineEl, contentEl);
    assertIsDefined(this.path, 'path');
    fire(this, 'create-comment', {
      path: this.path,
      side,
      lineNum,
      range,
    });
  }

  private getCommentSideByLineAndContent(
    lineEl: Element,
    contentEl: Element
  ): Side {
    return lineEl.classList.contains(Side.LEFT) ||
      contentEl.classList.contains('remove')
      ? Side.LEFT
      : Side.RIGHT;
  }

  private lineOfInterestChanged() {
    if (this.loading) return;
    if (!this.lineOfInterest) return;
    const lineNum = this.lineOfInterest.lineNum;
    if (typeof lineNum !== 'number') return;
    this.diffBuilder.unhideLine(lineNum, this.lineOfInterest.side);
  }

  private cleanup() {
    this.cancel();
    this.blame = null;
    this.safetyBypass = null;
    this.showWarning = false;
    this.clearDiffContent();
  }

  private prefsChanged() {
    if (!this.prefs) return;
    this.diffModel.updateState({diffPrefs: this.prefs});

    this.blame = null;
    this.updatePreferenceStyles();

    if (this.diff && !this.noRenderOnPrefsChange) {
      this.debounceRenderDiffTable();
    }
  }

  private updatePreferenceStyles() {
    assertIsDefined(this.prefs, 'prefs');
    const lineLength =
      this.path === COMMIT_MSG_PATH
        ? COMMIT_MSG_LINE_LENGTH
        : this.prefs.line_length;
    const sideBySide = this.viewMode === 'SIDE_BY_SIDE';

    const responsiveMode = getResponsiveMode(this.prefs, this.renderPrefs);
    const responsive = isResponsive(responsiveMode);
    this.diffTableClass = responsive ? 'responsive' : '';
    const lineLimit = `${lineLength}ch`;
    this.style.setProperty(
      '--line-limit-marker',
      responsiveMode === 'FULL_RESPONSIVE' ? lineLimit : '-1px'
    );
    this.style.setProperty('--content-width', responsive ? 'none' : lineLimit);
    if (responsiveMode === 'SHRINK_ONLY') {
      // Calculating ideal (initial) width for the whole table including
      // width of each table column (content and line number columns) and
      // border. We also add a 1px correction as some values are calculated
      // in 'ch'.

      // We might have 1 to 2 columns for content depending if side-by-side
      // or unified mode
      const contentWidth = `${sideBySide ? 2 : 1} * ${lineLimit}`;

      // We always have 2 columns for line number
      const lineNumberWidth = `2 * ${getLineNumberCellWidth(this.prefs)}px`;

      // border-right in ".section" css definition (in gr-diff_html.ts)
      const sectionRightBorder = '1px';

      // each sign col has 1ch width.
      const signColsWidth =
        sideBySide && this.renderPrefs?.show_sign_col ? '2ch' : '0ch';

      // As some of these calculations are done using 'ch' we end up having <1px
      // difference between ideal and calculated size for each side leading to
      // lines using the max columns (e.g. 80) to wrap (decided exclusively by
      // the browser).This happens even in monospace fonts. Empirically adding
      // 2px as correction to be sure wrapping won't happen in these cases so it
      // doesn't block further experimentation with the SHRINK_MODE. This was
      // previously set to 1px but due to to a more aggressive text wrapping
      // (via word-break: break-all; - check .contextText) we need to be even
      // more lenient in some cases. If we find another way to avoid this
      // correction we will change it.
      const dontWrapCorrection = '2px';
      this.style.setProperty(
        '--diff-max-width',
        `calc(${contentWidth} + ${lineNumberWidth} + ${signColsWidth} + ${sectionRightBorder} + ${dontWrapCorrection})`
      );
    } else {
      this.style.setProperty('--diff-max-width', 'none');
    }
    if (this.prefs.font_size) {
      this.style.setProperty('--font-size', `${this.prefs.font_size}px`);
    }
  }

  private renderPrefsChanged() {
    this.diffModel.updateState({renderPrefs: this.renderPrefs});
    if (this.renderPrefs.hide_left_side) {
      this.classList.add('no-left');
    }
    if (this.renderPrefs.disable_context_control_buttons) {
      this.classList.add('disable-context-control-buttons');
    }
    if (this.renderPrefs.hide_line_length_indicator) {
      this.classList.add('hide-line-length-indicator');
    }
    if (this.renderPrefs.show_sign_col) {
      this.classList.add('with-sign-col');
    }
    if (this.prefs) {
      this.updatePreferenceStyles();
    }
    this.diffBuilder.updateRenderPrefs(this.renderPrefs);
  }

  private diffChanged() {
    this.loading = true;
    this.cleanup();
    if (this.diff) {
      this.diffLength = this.getDiffLength(this.diff);
      this.debounceRenderDiffTable();
      assertIsDefined(this.diffTable, 'diffTable');
      this.diffSelection.init(this.diff, this.diffTable);
      this.highlights.init(this.diffTable, this.diffBuilder);
    }
  }

  // Implemented so the test can stub it.
  getDiffLength(diff?: DiffInfo) {
    return getDiffLength(diff);
  }

  /**
   * When called multiple times from the same task, will call
   * _renderDiffTable only once, in the next task (scheduled via `setTimeout`).
   *
   * This should be used instead of calling _renderDiffTable directly to
   * render the diff in response to an input change, because there may be
   * multiple inputs changing in the same microtask, but we only want to
   * render once.
   */
  private debounceRenderDiffTable() {
    // at this point gr-diff might be considered as rendered from the outside
    // (client), although it was not actually rendered. Clients need to know
    // when it is safe to perform operations like cursor moves, for example,
    // and if changing an input actually requires a reload of the diff table.
    // Since `fire` is synchronous it allows clients to be aware when an
    // async render is needed and that they can wait for a further `render`
    // event to actually take further action.
    fire(this, 'render-required', {});
    this.renderDiffTableTask = debounceP(
      this.renderDiffTableTask,
      async () => await this.renderDiffTable()
    );
    this.renderDiffTableTask.catch((e: unknown) => {
      if (e === DELAYED_CANCELLATION) return;
      throw e;
    });
  }

  // Private but used in tests.
  async renderDiffTable() {
    this.unobserveNodes();
    if (!this.diff || !this.prefs) {
      fire(this, 'render', {});
      return;
    }
    if (
      this.prefs.context === -1 &&
      this.diffLength &&
      this.diffLength >= LARGE_DIFF_THRESHOLD_LINES &&
      this.safetyBypass === null
    ) {
      this.showWarning = true;
      fire(this, 'render', {});
      return;
    }

    this.showWarning = false;

    const keyLocations = this.computeKeyLocations();

    this.diffModel.setState({
      diff: this.diff,
      path: this.path,
      renderPrefs: this.renderPrefs,
      diffPrefs: this.prefs,
    });

    // TODO: Setting tons of public properties like this is obviously a code
    // smell. We are introducing a diff model for managing all this
    // data. Then diff builder will only need access to that model.
    this.diffBuilder.prefs = this.getBypassPrefs();
    this.diffBuilder.renderPrefs = this.renderPrefs;
    this.diffBuilder.diff = this.diff;
    this.diffBuilder.path = this.path;
    this.diffBuilder.viewMode = this.viewMode;
    this.diffBuilder.layers = this.layers ?? [];
    this.diffBuilder.isImageDiff = this.isImageDiff;
    this.diffBuilder.baseImage = this.baseImage ?? null;
    this.diffBuilder.revisionImage = this.revisionImage ?? null;
    this.diffBuilder.useNewImageDiffUi = this.useNewImageDiffUi;
    this.diffBuilder.diffElement = this.diffTable;
    // `this.commentRanges` are probably empty here, because they will only be
    // populated by the node observer, which starts observing *after* rendering.
    this.diffBuilder.updateCommentRanges(this.commentRanges);
    this.diffBuilder.updateCoverageRanges(this.coverageRanges);
    await this.diffBuilder.render(keyLocations);
  }

  private handleRenderContent() {
    this.querySelectorAll('gr-ranged-comment-hint').forEach(element =>
      element.remove()
    );
    this.loading = false;
    this.observeNodes();
    // We are just converting 'render-content' into 'render' here. Maybe we
    // should retire the 'render' event in favor of 'render-content'?
    fire(this, 'render', {});
  }

  private observeNodes() {
    // First stop observing old nodes.
    this.unobserveNodes();
    // Then introduce a Mutation observer that watches for children being added
    // to gr-diff. If those children are `isThreadEl`, namely then they are
    // processed.
    this.nodeObserver = new MutationObserver(mutations => {
      const addedThreadEls = extractAddedNodes(mutations).filter(isThreadEl);
      const removedThreadEls =
        extractRemovedNodes(mutations).filter(isThreadEl);
      this.processNodes(addedThreadEls, removedThreadEls);
    });
    this.nodeObserver.observe(this, {childList: true});
    // Make sure to process existing gr-comment-threads that already exist.
    this.processNodes([...this.childNodes].filter(isThreadEl), []);
  }

  private processNodes(
    addedThreadEls: GrDiffThreadElement[],
    removedThreadEls: GrDiffThreadElement[]
  ) {
    this.updateRanges(addedThreadEls, removedThreadEls);
    addedThreadEls.forEach(threadEl =>
      this.redispatchHoverEvents(threadEl, threadEl)
    );
    // Removed nodes do not need to be handled because all this code does is
    // adding a slot for the added thread elements, and the extra slots do
    // not hurt. It's probably a bigger performance cost to remove them than
    // to keep them around. Medium term we can even consider to add one slot
    // for each line from the start.
    for (const threadEl of addedThreadEls) {
      const lineNum = getLine(threadEl);
      const commentSide = getSide(threadEl);
      const range = getRange(threadEl);
      if (!commentSide) continue;
      const lineEl = this.diffBuilder.getLineElByNumber(lineNum, commentSide);
      // When the line the comment refers to does not exist, log an error
      // but don't crash. This can happen e.g. if the API does not fully
      // validate e.g. (robot) comments
      if (!lineEl) {
        console.error(
          'thread attached to line ',
          commentSide,
          lineNum,
          ' which does not exist.'
        );
        continue;
      }
      const contentEl = this.diffBuilder.getContentTdByLineEl(lineEl);
      if (!contentEl) continue;
      if (lineNum === 'LOST') {
        this.insertPortedCommentsWithoutRangeMessage(contentEl);
      }

      const slotAtt = threadEl.getAttribute('slot');
      if (range && isLongCommentRange(range) && slotAtt) {
        const longRangeCommentHint = document.createElement(
          'gr-ranged-comment-hint'
        );
        longRangeCommentHint.range = range;
        longRangeCommentHint.setAttribute('threadElRootId', threadEl.rootId);
        longRangeCommentHint.setAttribute('slot', slotAtt);
        this.insertBefore(longRangeCommentHint, threadEl);
        this.redispatchHoverEvents(longRangeCommentHint, threadEl);
      }
    }

    for (const threadEl of removedThreadEls) {
      this.querySelector(
        `gr-ranged-comment-hint[threadElRootId="${threadEl.rootId}"]`
      )?.remove();
    }
  }

  private unobserveNodes() {
    if (this.nodeObserver) {
      this.nodeObserver.disconnect();
      this.nodeObserver = undefined;
    }
    // You only stop observing for comment thread elements when the diff is
    // completely rendered from scratch. And then comment thread elements
    // will be (re-)added *after* rendering is done. That is also when we
    // re-start observing. So it is appropriate to thoroughly clean up
    // everything that the observer is managing.
    this.commentRanges = [];
  }

  private insertPortedCommentsWithoutRangeMessage(lostCell: Element) {
    const existingMessage = lostCell.querySelector('div.lost-message');
    if (existingMessage) return;

    const div = document.createElement('div');
    div.className = 'lost-message';
    const icon = document.createElement('gr-icon');
    icon.setAttribute('icon', 'info');
    div.appendChild(icon);
    const span = document.createElement('span');
    span.innerText = 'Original comment position not found in this patchset';
    div.appendChild(span);
    lostCell.insertBefore(div, lostCell.firstChild);
  }

  /**
   * Get the preferences object including the safety bypass context (if any).
   */
  private getBypassPrefs() {
    assertIsDefined(this.prefs, 'prefs');
    if (this.safetyBypass !== null) {
      return {...this.prefs, context: this.safetyBypass};
    }
    return this.prefs;
  }

  clearDiffContent() {
    this.unobserveNodes();
    if (!this.diffTable) return;
    while (this.diffTable.hasChildNodes()) {
      this.diffTable.removeChild(this.diffTable.lastChild!);
    }
  }

  // Private but used in tests.
  computeDiffHeaderItems() {
    return (this.diff?.diff_header ?? [])
      .filter(
        item =>
          !(
            item.startsWith('diff --git ') ||
            item.startsWith('index ') ||
            item.startsWith('+++ ') ||
            item.startsWith('--- ') ||
            item === 'Binary files differ'
          )
      )
      .map(expandFileMode);
  }

  private handleFullBypass() {
    this.safetyBypass = FULL_CONTEXT;
    this.debounceRenderDiffTable();
  }

  private collapseContext() {
    // Uses the default context amount if the preference is for the entire file.
    this.safetyBypass =
      this.prefs?.context && this.prefs.context >= 0
        ? null
        : createDefaultDiffPrefs().context;
    this.debounceRenderDiffTable();
  }

  toggleAllContext() {
    if (!this.prefs) {
      return;
    }
    if (this.getBypassPrefs().context < 0) {
      this.collapseContext();
    } else {
      this.handleFullBypass();
    }
  }

  private computeNewlineWarning(): string | undefined {
    const messages = [];
    if (this.showNewlineWarningLeft) {
      messages.push(NO_NEWLINE_LEFT);
    }
    if (this.showNewlineWarningRight) {
      messages.push(NO_NEWLINE_RIGHT);
    }
    if (!messages.length) {
      return undefined;
    }
    return messages.join(' \u2014 '); // \u2014 - '—'
  }
}

function extractAddedNodes(mutations: MutationRecord[]) {
  return mutations.flatMap(mutation => [...mutation.addedNodes]);
}

function extractRemovedNodes(mutations: MutationRecord[]) {
  return mutations.flatMap(mutation => [...mutation.removedNodes]);
}

declare global {
  interface HTMLElementTagNameMap {
    'gr-diff': GrDiff;
  }
  interface HTMLElementEventMap {
    'comment-thread-mouseenter': CustomEvent<{}>;
    'comment-thread-mouseleave': CustomEvent<{}>;
    'loading-changed': ValueChangedEvent<boolean>;
    'render-required': CustomEvent<{}>;
  }
}
