/**
 * @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, 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 {
  GrRangedCommentLayer,
  id,
} 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 {AbortStop} from '../../../api/core';
import {
  RenderPreferences,
  GrDiff as GrDiffApi,
  DisplayLine,
  DiffRangesToFocus,
  FileRangeSelection,
  LineNumber,
  ContentLoadNeededEventDetail,
  DiffContextExpandedExternalDetail,
  CopyInfoEventDetail,
  CommentRangeLayer,
} from '../../../api/diff';
import {getShadowOrDocumentSelection} 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 {GrFocusLayer} from '../gr-focus-layer/gr-focus-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';
import {getContentEditableRange} from '../../../utils/safari-selection-util';

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;

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

  // By default <gr-diff> highlights all ranges that are referenced by a
  // comment. This `highlightRange` property allows to also highlight one other
  // range explicitly.
  @property({type: Object})
  highlightRange?: CommentRangeLayer;

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

  @property({type: Object})
  diffRangesToFocus?: DiffRangesToFocus;

  // Extra message shown if files are binary to help users investigate contents.
  @property({type: String})
  binaryDiffHint = '';

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

  @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 focusLayer = new GrFocusLayer();

  private highlightLayer = 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') ||
      changedProperties.has('diffRangesToFocus') ||
      changedProperties.has('actionHoverCardText')
    ) {
      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,
          diffRangesToFocus: this.diffRangesToFocus,
        });
      }
    }
    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();
    }
    if (changedProperties.has('diffRangesToFocus')) {
      this.updateFocusRanges(this.diffRangesToFocus);
    }
    if (changedProperties.has('actionHoverCardText')) {
      if (this.actionHoverCardText) {
        this.diffModel.updateState({
          actionHoverCardText: this.actionHoverCardText,
        });
      }
    }
    if (changedProperties.has('highlightRange')) {
      this.updateHighlightLayer(this.diffModel.getState().comments);
    }
  }

  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
      .binaryDiffHint=${this.binaryDiffHint}
    ></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 = getShadowOrDocumentSelection(
      this.shadowRoot,
      getContentEditableRange()
    );
    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 = getShadowOrDocumentSelection(
      this.shadowRoot,
      getContentEditableRange()
    );
    this.highlights.handleSelectionChange(selection, true);
  };

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

  getSelectedRange(): FileRangeSelection | undefined {
    if (!this.highlights.selectedRange || !this.path) {
      return undefined;
    }
    return {
      text_range: {
        start_line: this.highlights.selectedRange.range.start_line,
        start_column: this.highlights.selectedRange.range.start_character,
        end_line: this.highlights.selectedRange.range.end_line,
        end_column: this.highlights.selectedRange.range.end_character,
      },
      file_path: this.path,
      side: this.highlights.selectedRange.side,
    };
  }

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

  isShowFullContext() {
    return this.diffModel.getState().showFullContext === FullContext.YES;
  }

  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.updateHighlightLayer(comments);
    for (const el of threadEls) {
      el.addEventListener('mouseenter', this.commentThreadEnterRedispatcher);
      el.addEventListener('mouseleave', this.commentThreadLeaveRedispatcher);
    }
  }

  /**
   * Updates the layer that highlights all ranges that belong to a comment
   * and the `this.highlightRange`.
   */
  private updateHighlightLayer(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({
        ...this.highlightRange,
        id: `hl-${id(this.highlightRange)}`,
      });
    }
    this.highlightLayer.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 updateFocusRanges(rs?: DiffRangesToFocus) {
    this.focusLayer.setRanges(rs);
  }

  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.highlightLayer,
      this.coverageLayerLeft,
      this.coverageLayerRight,
      this.focusLayer,
    ];
    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>;
    'copy-info': CustomEvent<CopyInfoEventDetail>;
  }
}
