/**
 * @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-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 '../gr-diff-builder/gr-diff-builder-image';
import '../gr-diff-builder/gr-diff-section';
import './gr-diff-element';
import '../gr-diff-builder/gr-diff-row';
import {
  getLineNumber,
  isThreadEl,
  getResponsiveMode,
  isResponsive,
  getSideByLineEl,
  compareComments,
  getDataFromCommentThreadEl,
  FullContext,
  DiffContextExpandedEventDetail,
  GrDiffCommentThread,
} from '../gr-diff/gr-diff-utils';
import {BlameInfo, CommentRange, ImageInfo} from '../../../types/common';
import {DiffInfo, DiffPreferencesInfo} from '../../../types/diff';
import {GrDiffHighlight} from '../gr-diff-highlight/gr-diff-highlight';
import {CoverageRange, DiffLayer, isDefined} from '../../../types/types';
import {
  CommentRangeLayer,
  GrRangedCommentLayer,
} from '../gr-ranged-comment-layer/gr-ranged-comment-layer';
import {DiffViewMode, Side} from '../../../constants/constants';
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 {
  RenderPreferences,
  GrDiff as GrDiffApi,
  DisplayLine,
  LineNumber,
  ContentLoadNeededEventDetail,
  DiffContextExpandedExternalDetail,
} from '../../../api/diff';
import {isSafari} from '../../../utils/dom-util';
import {assertIsDefined} from '../../../utils/common-util';
import {GrDiffSelection} from '../gr-diff-selection/gr-diff-selection';
import {property, query, state} from 'lit/decorators.js';
import {sharedStyles} from '../../../styles/shared-styles';
import {html, LitElement, PropertyValues} from 'lit';
import {grSyntaxTheme} from '../gr-syntax-themes/gr-syntax-theme';
import {grRangedCommentTheme} from '../gr-ranged-comment-themes/gr-ranged-comment-theme';
import {iconStyles} from '../../../styles/gr-icon-styles';
import {DiffModel, diffModelToken} from '../gr-diff-model/gr-diff-model';
import {provide} from '../../../models/dependency';
import {
  grDiffBinaryStyles,
  grDiffContextControlsSectionStyles,
  grDiffElementStyles,
  grDiffIgnoredWhitespaceStyles,
  grDiffImageStyles,
  grDiffMoveStyles,
  grDiffRebaseStyles,
  grDiffRowStyles,
  grDiffSectionStyles,
  grDiffSelectionStyles,
  grDiffStyles,
  grDiffTextStyles,
} from './gr-diff-styles';
import {GrCoverageLayer} from '../gr-coverage-layer/gr-coverage-layer';
import {
  GrAnnotationImpl,
  getStringLength,
} from '../gr-diff-highlight/gr-annotation';
import {
  GrDiffGroup,
  GrDiffGroupType,
  hideInContextControl,
} from './gr-diff-group';
import {GrDiffLine} from './gr-diff-line';
import {subscribe} from '../../../elements/lit/subscription-controller';
import {GrDiffSection} from '../gr-diff-builder/gr-diff-section';
import {GrDiffRow} from '../gr-diff-builder/gr-diff-row';
import {GrDiffElement} from './gr-diff-element';

const TRAILING_WHITESPACE_PATTERN = /\s+$/;

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 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
   */

  /**
   * Deprecated. Use `diffElement` instead.
   *
   * TODO: Migrate to new diff. Remove dependency on this property from external
   * gr-diff users that instantiate TokenHighlightLayer.
   */
  @query('gr-diff-element')
  diffTable?: HTMLElement;

  @query('gr-diff-element')
  diffElement?: GrDiffElement;

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

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

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

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

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

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

  // 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;

  // TODO: Migrate users to using the same property in render preferences.
  @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;

  @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();

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

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

  // TODO: Migrate users to using the same property in render preferences.
  @property({type: Boolean})
  showNewlineWarningLeft = false;

  // TODO: Migrate users to using the same property in render preferences.
  @property({type: Boolean})
  showNewlineWarningRight = false;

  // TODO: Migrate users to using the same property in render preferences.
  @property({type: Boolean})
  useNewImageDiffUi = false;

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

  /** Observes comment nodes added or removed at any point. */
  private nodeObserver?: MutationObserver;

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

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

  // Private but used in tests.
  diffModel = new DiffModel(this);

  /**
   * Just the layers that are passed in from the outside. Will be joined with
   * `layersInternal` and sent to the diff model.
   */
  @property({type: Array})
  layers: DiffLayer[] = [];

  /**
   * Just the internal default layers. See `layers` for the property that can
   * be set from the outside.
   */
  private layersInternal: DiffLayer[] = [];

  private coverageLayerLeft = new GrCoverageLayer(Side.LEFT);

  private coverageLayerRight = new GrCoverageLayer(Side.RIGHT);

  private rangeLayer = new GrRangedCommentLayer();

  @state() groups: GrDiffGroup[] = [];

  @state() private context = 3;

  private readonly layerUpdateListener: (
    start: LineNumber,
    end: LineNumber,
    side: Side
  ) => void;

  static override get styles() {
    return [
      iconStyles,
      sharedStyles,
      grSyntaxTheme,
      grRangedCommentTheme,
      grDiffStyles,
      grDiffElementStyles,
      grDiffSectionStyles,
      grDiffContextControlsSectionStyles,
      grDiffRowStyles,
      grDiffIgnoredWhitespaceStyles,
      grDiffMoveStyles,
      grDiffRebaseStyles,
      grDiffSelectionStyles,
      grDiffTextStyles,
      grDiffImageStyles,
      grDiffBinaryStyles,
    ];
  }

  constructor() {
    super();
    provide(this, diffModelToken, () => this.diffModel);
    subscribe(
      this,
      () => this.diffModel.context$,
      context => (this.context = context)
    );
    subscribe(
      this,
      () => this.diffModel.groups$,
      groups => (this.groups = groups)
    );
    this.addEventListener('moved-link-clicked', (e: MovedLinkClickedEvent) => {
      this.diffModel.selectLine(e.detail.lineNum, e.detail.side);
    });
    this.addEventListener(
      'diff-context-expanded-internal-new',
      this.onDiffContextExpanded
    );
    this.layerUpdateListener = (
      start: LineNumber,
      end: LineNumber,
      side: Side
    ) => this.requestRowUpdates(start, end, side);
    this.layersInternalInit();
  }

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

  override disconnectedCallback() {
    if (this.nodeObserver) {
      this.nodeObserver.disconnect();
      this.nodeObserver = undefined;
    }
    this.removeSelectionListeners();
    this.diffSelection.cleanup();
    this.highlights.cleanup();
    super.disconnectedCallback();
  }

  protected override willUpdate(changedProperties: PropertyValues<this>): void {
    if (
      changedProperties.has('diff') ||
      changedProperties.has('path') ||
      changedProperties.has('renderPrefs') ||
      changedProperties.has('viewMode') ||
      changedProperties.has('loggedIn') ||
      changedProperties.has('useNewImageDiffUi') ||
      changedProperties.has('showNewlineWarningLeft') ||
      changedProperties.has('showNewlineWarningRight') ||
      changedProperties.has('prefs') ||
      changedProperties.has('lineOfInterest')
    ) {
      if (this.diff && this.prefs) {
        const renderPrefs = {...(this.renderPrefs ?? {})};
        // TODO: Migrate users to using render preferences directly. Then removes these overrides.
        if (renderPrefs.view_mode === undefined) {
          renderPrefs.view_mode = this.viewMode;
        }
        if (renderPrefs.can_comment === undefined) {
          renderPrefs.can_comment = this.loggedIn;
        }
        if (renderPrefs.use_new_image_diff_ui === undefined) {
          renderPrefs.use_new_image_diff_ui = this.useNewImageDiffUi;
        }
        if (renderPrefs.show_newline_warning_left === undefined) {
          renderPrefs.show_newline_warning_left = this.showNewlineWarningLeft;
        }
        if (renderPrefs.show_newline_warning_right === undefined) {
          renderPrefs.show_newline_warning_right = this.showNewlineWarningRight;
        }
        this.diffModel.updateState({
          diff: this.diff,
          path: this.path,
          renderPrefs,
          diffPrefs: this.prefs,
          lineOfInterest: this.lineOfInterest,
        });
      }
    }
    if (changedProperties.has('baseImage')) {
      this.diffModel.updateState({baseImage: this.baseImage});
    }
    if (changedProperties.has('revisionImage')) {
      this.diffModel.updateState({revisionImage: this.revisionImage});
    }
    if (
      changedProperties.has('path') ||
      changedProperties.has('lineWrapping') ||
      changedProperties.has('viewMode') ||
      changedProperties.has('useNewImageDiffUi') ||
      changedProperties.has('prefs')
    ) {
      this.prefsChanged();
    }
    if (changedProperties.has('layers')) {
      this.layersChanged();
    }
    if (changedProperties.has('blame')) {
      this.diffModel.updateState({blameInfo: this.blame ?? []});
    }
    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.updateCoverageRanges(this.coverageRanges);
    }
    if (changedProperties.has('lineOfInterest')) {
      this.lineOfInterestChanged();
    }
  }

  protected override async getUpdateComplete(): Promise<boolean> {
    const result = await super.getUpdateComplete();
    await this.diffElement?.updateComplete;
    return result;
  }

  protected override updated(changedProperties: PropertyValues<this>) {
    if (changedProperties.has('diff')) {
      // diffChanged relies on diffElement having been rendered.
      this.diffChanged();
    }
    if (changedProperties.has('groups')) {
      if (this.groups?.length > 0) {
        this.loading = false;
      }
    }
  }

  override render() {
    return html`<gr-diff-element></gr-diff-element>`;
  }

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

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

  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 commentThreadRedispatcher = (
    target: EventTarget | null,
    eventName: 'comment-thread-mouseenter' | 'comment-thread-mouseleave'
  ) => {
    if (!isThreadEl(target)) return;
    const data = getDataFromCommentThreadEl(target);
    if (data) fire(target, eventName, data);
  };

  private commentThreadEnterRedispatcher = (e: Event) => {
    this.commentThreadRedispatcher(e.target, 'comment-thread-mouseenter');
  };

  private commentThreadLeaveRedispatcher = (e: Event) => {
    this.commentThreadRedispatcher(e.target, 'comment-thread-mouseleave');
  };

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

    // Get rendered stops.
    const stops: Array<HTMLElement | AbortStop> = this.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;
  }

  // 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.diffModel.selectLine(lineNumber, side);
  }

  addDraftAtLine(lineNum: LineNumber, side: Side) {
    this.diffModel.createCommentOnLine(lineNum, side);
  }

  createRangeComment() {
    const selectedRange = this.highlights.selectedRange;
    assertIsDefined(selectedRange, 'no range selected');
    const {side, range} = selectedRange;
    this.diffModel.createCommentOnRange(range, side);
  }

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

  private prefsChanged() {
    if (!this.prefs) return;
    this.updatePreferenceStyles();

    if (!Number.isInteger(this.prefs.tab_size) || this.prefs.tab_size <= 0) {
      this.handlePreferenceError('tab size');
    }
    if (
      !Number.isInteger(this.prefs.line_length) ||
      this.prefs.line_length <= 0
    ) {
      this.handlePreferenceError('diff width');
    }
  }

  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);
    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.classList.toggle(
      'disable-context-control-buttons',
      !!this.renderPrefs.disable_context_control_buttons
    );
    this.classList.toggle(
      'hide-line-length-indicator',
      !!this.renderPrefs.hide_line_length_indicator
    );
    this.classList.toggle('with-sign-col', !!this.renderPrefs.show_sign_col);
    if (this.prefs) {
      this.updatePreferenceStyles();
    }
  }

  private diffChanged() {
    this.loading = true;
    if (this.diff && this.diffElement) {
      this.diffSelection.init(this.diff, this.diffElement);
      this.highlights.init(this.diffElement, this);
    }
  }

  /**
   * This must be called once, but only after diff lines are rendered. Otherwise
   * `processNodes()` will fail to lookup the HTML elements that it wants to
   * manipulate.
   *
   * TODO: Validate whether the above comment is still true. We don't look up
   * elements anymore, and processing the nodes earlier might be beneficial
   * performance wise.
   */
  private observeNodes() {
    if (this.nodeObserver) return;
    // Watches children being added to gr-diff. We are expecting only comment
    // widgets to be direct children.
    this.nodeObserver = new MutationObserver(() => this.processNodes());
    this.nodeObserver.observe(this, {childList: true});
    // Process existing comment widgets before the first observed change.
    this.processNodes();
  }

  private processNodes() {
    const threadEls = [...this.childNodes].filter(isThreadEl);
    const comments = threadEls
      .map(getDataFromCommentThreadEl)
      .filter(isDefined)
      .sort(compareComments);
    this.diffModel.updateState({comments});
    this.updateRangeLayer(comments);
    for (const el of threadEls) {
      el.addEventListener('mouseenter', this.commentThreadEnterRedispatcher);
      el.addEventListener('mouseleave', this.commentThreadLeaveRedispatcher);
    }
  }

  private updateRangeLayer(threads: GrDiffCommentThread[]) {
    const ranges: CommentRangeLayer[] = threads
      .filter(t => !!t.range)
      .map(t => {
        return {range: t.range!, side: t.side, id: t.rootId};
      });
    if (this.highlightRange) {
      ranges.push({side: Side.RIGHT, range: this.highlightRange, id: 'hl'});
    }
    this.rangeLayer.updateRanges(ranges);
  }

  // TODO: Migrate callers to just update prefs.context.
  toggleAllContext() {
    const current = this.diffModel.getState().showFullContext;
    this.diffModel.updateState({
      showFullContext:
        current === FullContext.YES ? FullContext.NO : FullContext.YES,
    });
  }

  private updateCoverageRanges(rs: CoverageRange[]) {
    this.coverageLayerLeft.setRanges(rs.filter(r => r?.side === Side.LEFT));
    this.coverageLayerRight.setRanges(rs.filter(r => r?.side === Side.RIGHT));
  }

  private onDiffContextExpanded = (
    e: CustomEvent<DiffContextExpandedEventDetail>
  ) => {
    // Don't stop propagation. The host may listen for reporting or
    // resizing.
    this.diffModel.replaceGroup(e.detail.contextGroup, e.detail.groups);
  };

  private layersChanged() {
    const layers = [...this.layersInternal, ...this.layers];
    for (const layer of layers) {
      layer.removeListener?.(this.layerUpdateListener);
      layer.addListener?.(this.layerUpdateListener);
    }
    this.diffModel.updateState({layers});
  }

  private layersInternalInit() {
    this.layersInternal = [
      this.createTrailingWhitespaceLayer(),
      this.createIntralineLayer(),
      this.createTabIndicatorLayer(),
      this.createSpecialCharacterIndicatorLayer(),
      this.rangeLayer,
      this.coverageLayerLeft,
      this.coverageLayerRight,
    ];
    this.layersChanged();
  }

  getContentTdByLineEl(lineEl?: Element): Element | undefined {
    if (!lineEl) return undefined;
    const line = getLineNumber(lineEl);
    if (!line) return undefined;
    const side = getSideByLineEl(lineEl);
    return this.getContentTdByLine(line, side);
  }

  /**
   * When the line is hidden behind a context expander, expand it.
   *
   * @param lineNum A line number to expand. Using number here because other
   *   special case line numbers are never hidden, so it does not make sense
   *   to expand them.
   * @param side The side the line number refer to.
   */
  unhideLine(lineNum: number, side: Side) {
    assertIsDefined(this.prefs, 'prefs');
    const group = this.findGroup(side, lineNum);
    // Cannot unhide a line that is not part of the diff.
    if (!group) return;
    // If it's already visible, great!
    if (group.type !== GrDiffGroupType.CONTEXT_CONTROL) return;
    const lineRange = group.lineRange[side];
    const lineOffset = lineNum - lineRange.start_line;
    const newGroups = [];
    const groups = hideInContextControl(
      group.contextGroups,
      0,
      lineOffset - 1 - this.context
    );
    // If there is a context group, it will be the first group because we
    // start hiding from 0 offset
    if (groups[0].type === GrDiffGroupType.CONTEXT_CONTROL) {
      newGroups.push(groups.shift()!);
    }
    newGroups.push(
      ...hideInContextControl(
        groups,
        lineOffset + 1 + this.context,
        // Both ends inclusive, so difference is the offset of the last line.
        // But we need to pass the first line not to hide, which is the element
        // after.
        lineRange.end_line - lineRange.start_line + 1
      )
    );
    this.diffModel.replaceGroup(group, newGroups);
  }

  // visible for testing
  handlePreferenceError(pref: string): never {
    const message =
      `The value of the '${pref}' user preference is ` +
      'invalid. Fix in diff preferences';
    fireAlert(this, message);
    throw Error(`Invalid preference value: ${pref}`);
  }

  // visible for testing
  createIntralineLayer(): DiffLayer {
    return {
      // Take a DIV.contentText element and a line object with intraline
      // differences to highlight and apply them to the element as
      // annotations.
      annotate(contentEl: HTMLElement, _: HTMLElement, line: GrDiffLine) {
        const HL_CLASS = 'intraline';
        for (const highlight of line.highlights) {
          // The start and end indices could be the same if a highlight is
          // meant to start at the end of a line and continue onto the
          // next one. Ignore it.
          if (highlight.startIndex === highlight.endIndex) {
            continue;
          }

          // If endIndex isn't present, continue to the end of the line.
          const endIndex =
            highlight.endIndex === undefined
              ? getStringLength(line.text)
              : highlight.endIndex;

          GrAnnotationImpl.annotateElement(
            contentEl,
            highlight.startIndex,
            endIndex - highlight.startIndex,
            HL_CLASS
          );
        }
      },
    };
  }

  // visible for testing
  createTabIndicatorLayer(): DiffLayer {
    const show = () => this.prefs?.show_tabs;
    return {
      annotate(contentEl: HTMLElement, _: HTMLElement, line: GrDiffLine) {
        if (!show()) return;
        annotateSymbols(contentEl, line, '\t', 'tab-indicator');
      },
    };
  }

  private createSpecialCharacterIndicatorLayer(): DiffLayer {
    return {
      annotate(contentEl: HTMLElement, _: HTMLElement, line: GrDiffLine) {
        // Find and annotate the locations of soft hyphen (\u00AD)
        annotateSymbols(contentEl, line, '\u00AD', 'special-char-indicator');
        // Find and annotate Stateful Unicode directional controls
        annotateSymbols(
          contentEl,
          line,
          /[\u202A-\u202E\u2066-\u2069]/,
          'special-char-warning'
        );
      },
    };
  }

  // visible for testing
  createTrailingWhitespaceLayer(): DiffLayer {
    const show = () => this.prefs?.show_whitespace_errors;
    return {
      annotate(contentEl: HTMLElement, _: HTMLElement, line: GrDiffLine) {
        if (!show()) return;
        const match = line.text.match(TRAILING_WHITESPACE_PATTERN);
        if (match) {
          // Normalize string positions in case there is unicode before or
          // within the match.
          const index = getStringLength(line.text.substr(0, match.index));
          const length = getStringLength(match[0]);
          GrAnnotationImpl.annotateElement(
            contentEl,
            index,
            length,
            'trailing-whitespace'
          );
        }
      },
    };
  }

  getContentTdByLine(
    lineNumber: LineNumber,
    side?: Side
  ): HTMLTableCellElement | undefined {
    if (!side) return undefined;
    const row = this.findRow(side, lineNumber);
    return row?.getContentCell(side);
  }

  getLineElByNumber(
    lineNumber: LineNumber,
    side?: Side
  ): HTMLTableCellElement | undefined {
    if (!side) return undefined;
    const row = this.findRow(side, lineNumber);
    return row?.getLineNumberCell(side);
  }

  private findRow(side: Side, lineNumber: LineNumber): GrDiffRow | undefined {
    const group = this.findGroup(side, lineNumber);
    if (!group) return undefined;
    const section = this.findSection(group);
    if (!section) return undefined;
    return section.findRow(side, lineNumber);
  }

  private getDiffRows() {
    if (!this.diffElement) return [];
    const sections = [...(this.diffElement.diffSections ?? [])];
    return sections.map(s => s.getDiffRows()).flat();
  }

  getLineNumberRows(): HTMLTableRowElement[] {
    const rows = this.getDiffRows();
    return rows.map(r => r.getTableRow()).filter(isDefined);
  }

  getLineNumEls(side: Side): HTMLTableCellElement[] {
    const rows = this.getDiffRows();
    return rows.map(r => r.getLineNumberCell(side)).filter(isDefined);
  }

  /** This is used when layers initiate an update. */
  private requestRowUpdates(start: LineNumber, end: LineNumber, side: Side) {
    const groups = this.getGroupsByLineRange(start, end, side);
    for (const group of groups) {
      const section = this.findSection(group);
      for (const row of section?.getDiffRows() ?? []) {
        row.requestUpdate();
      }
    }
  }

  private findSection(group: GrDiffGroup): GrDiffSection | undefined {
    if (!this.diffElement) return undefined;
    const leftClass = `left-${group.startLine(Side.LEFT)}`;
    const rightClass = `right-${group.startLine(Side.RIGHT)}`;
    return (
      this.diffElement.querySelector<GrDiffSection>(
        `gr-diff-section.${leftClass}.${rightClass}`
      ) ?? undefined
    );
  }

  findGroup(side: Side, line: LineNumber) {
    return this.groups.find(group => group.containsLine(side, line));
  }

  // visible for testing
  getGroupsByLineRange(
    startLine: LineNumber,
    endLine: LineNumber,
    side: Side
  ): GrDiffGroup[] {
    const startIndex = this.groups.findIndex(group =>
      group.containsLine(side, startLine)
    );
    if (startIndex === -1) return [];
    let endIndex = this.groups.findIndex(group =>
      group.containsLine(side, endLine)
    );
    // Not all groups may have been processed yet (i.e. this.groups is still
    // incomplete). In that case let's just return *all* groups until the end
    // of the array.
    if (endIndex === -1) endIndex = this.groups.length - 1;
    // The filter preserves the legacy behavior to only return non-context
    // groups
    return this.groups
      .slice(startIndex, endIndex + 1)
      .filter(group => group.lines.length > 0);
  }
}

function getLineNumberCellWidth(prefs: DiffPreferencesInfo) {
  return prefs.font_size * 4;
}

function annotateSymbols(
  contentEl: HTMLElement,
  line: GrDiffLine,
  separator: string | RegExp,
  className: string
) {
  const split = line.text.split(separator);
  if (!split || split.length < 2) {
    return;
  }
  for (let i = 0, pos = 0; i < split.length - 1; i++) {
    // Skip forward by the length of the content
    pos += split[i].length;

    GrAnnotationImpl.annotateElement(contentEl, pos, 1, className);

    pos++;
  }
}

customElements.define('gr-diff', GrDiff);

declare global {
  interface HTMLElementTagNameMap {
    'gr-diff': GrDiff;
  }
  interface HTMLElementEventMap {
    'comment-thread-mouseenter': CustomEvent<GrDiffCommentThread>;
    'comment-thread-mouseleave': CustomEvent<GrDiffCommentThread>;
    'loading-changed': ValueChangedEvent<boolean>;
    'render-required': CustomEvent<{}>;
    /**
     * Fired when the diff begins rendering - both for full renders and for
     * partial rerenders.
     */
    'render-start': CustomEvent<{}>;
    /**
     * Fired when the diff finishes rendering text content - both for full
     * renders and for partial rerenders.
     */
    'render-content': CustomEvent<{}>;
    'diff-context-expanded': CustomEvent<DiffContextExpandedExternalDetail>;
    'diff-context-expanded-internal-new': CustomEvent<DiffContextExpandedEventDetail>;
    'content-load-needed': CustomEvent<ContentLoadNeededEventDetail>;
  }
}
