/**
 * @license
 * Copyright 2015 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import '@polymer/iron-dropdown/iron-dropdown';
import '@polymer/iron-input/iron-input';
import '../../../styles/gr-a11y-styles';
import '../../../styles/shared-styles';
import '../../shared/gr-button/gr-button';
import '../../shared/gr-dropdown/gr-dropdown';
import '../../shared/gr-dropdown-list/gr-dropdown-list';
import '../../shared/gr-icon/gr-icon';
import '../../shared/gr-select/gr-select';
import '../../shared/revision-info/revision-info';
import '../../../embed/diff/gr-diff-cursor/gr-diff-cursor';
import '../gr-apply-fix-dialog/gr-apply-fix-dialog';
import '../gr-diff-host/gr-diff-host';
import '../../../embed/diff/gr-diff-mode-selector/gr-diff-mode-selector';
import '../gr-diff-preferences-dialog/gr-diff-preferences-dialog';
import '../gr-patch-range-select/gr-patch-range-select';
import '../../change/gr-download-dialog/gr-download-dialog';
import '../../shared/gr-overlay/gr-overlay';
import {
  GeneratedWebLink,
  GerritNav,
} from '../../core/gr-navigation/gr-navigation';
import {getAppContext} from '../../../services/app-context';
import {
  computeAllPatchSets,
  computeLatestPatchNum,
  PatchSet,
  isMergeParent,
  getParentIndex,
} from '../../../utils/patch-set-util';
import {
  addUnmodifiedFiles,
  computeDisplayPath,
  computeTruncatedPath,
  isMagicPath,
  specialFilePathCompare,
} from '../../../utils/path-list-util';
import {changeBaseURL, changeIsOpen} from '../../../utils/change-util';
import {GrDiffHost} from '../../diff/gr-diff-host/gr-diff-host';
import {
  DropdownItem,
  GrDropdownList,
} from '../../shared/gr-dropdown-list/gr-dropdown-list';
import {GrOverlay} from '../../shared/gr-overlay/gr-overlay';
import {ChangeComments} from '../../diff/gr-comment-api/gr-comment-api';
import {
  BasePatchSetNum,
  ChangeInfo,
  CommitId,
  EDIT,
  FileInfo,
  NumericChangeId,
  PARENT,
  PatchRange,
  PatchSetNum,
  PatchSetNumber,
  PreferencesInfo,
  RepoName,
  RevisionInfo,
  RevisionPatchSetNum,
  ServerInfo,
} from '../../../types/common';
import {DiffInfo, DiffPreferencesInfo} from '../../../types/diff';
import {
  CommitRange,
  EditRevisionInfo,
  FileRange,
  ParsedChangeInfo,
} from '../../../types/types';
import {FilesWebLinks} from '../gr-patch-range-select/gr-patch-range-select';
import {GrDiffCursor} from '../../../embed/diff/gr-diff-cursor/gr-diff-cursor';
import {CommentSide, DiffViewMode, Side} from '../../../constants/constants';
import {GrApplyFixDialog} from '../gr-apply-fix-dialog/gr-apply-fix-dialog';
import {RevisionInfo as RevisionInfoObj} from '../../shared/revision-info/revision-info';
import {
  CommentMap,
  getPatchRangeForCommentUrl,
  isInBaseOfPatchRange,
} from '../../../utils/comment-util';
import {AppElementDiffViewParam, AppElementParams} from '../../gr-app-types';
import {
  EventType,
  OpenFixPreviewEvent,
  ValueChangedEvent,
} from '../../../types/events';
import {fireAlert, fireEvent, fireTitleChange} from '../../../utils/event-util';
import {GerritView} from '../../../services/router/router-model';
import {assertIsDefined} from '../../../utils/common-util';
import {Key, toggleClass} from '../../../utils/dom-util';
import {CursorMoveResult} from '../../../api/core';
import {isFalse, throttleWrap, until} from '../../../utils/async-util';
import {filter, take, switchMap} from 'rxjs/operators';
import {combineLatest} from 'rxjs';
import {
  Shortcut,
  ShortcutSection,
  shortcutsServiceToken,
} from '../../../services/shortcuts/shortcuts-service';
import {LoadingStatus} from '../../../models/change/change-model';
import {DisplayLine} from '../../../api/diff';
import {GrDownloadDialog} from '../../change/gr-download-dialog/gr-download-dialog';
import {browserModelToken} from '../../../models/browser/browser-model';
import {commentsModelToken} from '../../../models/comments/comments-model';
import {changeModelToken} from '../../../models/change/change-model';
import {resolve} from '../../../models/dependency';
import {BehaviorSubject} from 'rxjs';
import {css, html, LitElement, PropertyValues} from 'lit';
import {ShortcutController} from '../../lit/shortcut-controller';
import {subscribe} from '../../lit/subscription-controller';
import {customElement, property, query, state} from 'lit/decorators';
import {configModelToken} from '../../../models/config/config-model';
import {a11yStyles} from '../../../styles/gr-a11y-styles';
import {sharedStyles} from '../../../styles/shared-styles';
import {ifDefined} from 'lit/directives/if-defined';
import {when} from 'lit/directives/when';

const LOADING_BLAME = 'Loading blame...';
const LOADED_BLAME = 'Blame loaded';

// Time in which pressing n key again after the toast navigates to next file
const NAVIGATE_TO_NEXT_FILE_TIMEOUT_MS = 5000;

// visible for testing
export interface Files {
  sortedFileList: string[];
  changeFilesByPath: {[path: string]: FileInfo};
}

interface CommentSkips {
  previous: string | null;
  next: string | null;
}
@customElement('gr-diff-view')
export class GrDiffView extends LitElement {
  /**
   * Fired when the title of the page should change.
   *
   * @event title-change
   */

  /**
   * Fired when user tries to navigate away while comments are pending save.
   *
   * @event show-alert
   */
  @query('#diffHost')
  diffHost?: GrDiffHost;

  @query('#reviewed')
  reviewed?: HTMLInputElement;

  @query('#downloadOverlay')
  downloadOverlay?: GrOverlay;

  @query('#downloadDialog')
  downloadDialog?: GrDownloadDialog;

  @query('#dropdown')
  dropdown?: GrDropdownList;

  @query('#applyFixDialog')
  applyFixDialog?: GrApplyFixDialog;

  @query('#diffPreferencesDialog')
  diffPreferencesDialog?: GrOverlay;

  /**
   * URL params passed from the router.
   * Use params getter/setter.
   */
  private _params?: AppElementParams;

  @property({type: Object})
  get params() {
    return this._params;
  }

  set params(params: AppElementParams | undefined) {
    if (this._params === params) return;
    const oldParams = this._params;
    this._params = params;
    this.paramsChanged();
    this.requestUpdate('params', oldParams);
  }

  // Private but used in tests.
  @state()
  patchRange?: PatchRange;

  // Private but used in tests.
  @state()
  commitRange?: CommitRange;

  // Private but used in tests.
  @state()
  change?: ParsedChangeInfo;

  // Private but used in tests.
  @state()
  changeComments?: ChangeComments;

  // Private but used in tests.
  @state()
  changeNum?: NumericChangeId;

  // Private but used in tests.
  @state()
  diff?: DiffInfo;

  // TODO: Move to using files-model.
  // Private but used in tests.
  @state()
  files: Files = {sortedFileList: [], changeFilesByPath: {}};

  // Private but used in tests
  // Use path getter/setter.
  _path?: string;

  get path() {
    return this._path;
  }

  set path(path: string | undefined) {
    if (this._path === path) return;
    const oldPath = this._path;
    this._path = path;
    this.pathChanged();
    this.requestUpdate('path', oldPath);
  }

  // Private but used in tests.
  @state()
  loggedIn = false;

  // Private but used in tests.
  @state()
  loading = true;

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

  @state()
  private serverConfig?: ServerInfo;

  // Private but used in tests.
  @state()
  userPrefs?: PreferencesInfo;

  @state()
  private isImageDiff?: boolean;

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

  @state()
  private filesWeblinks?: FilesWebLinks;

  // Private but used in tests.
  @state()
  commentMap?: CommentMap;

  @state()
  private commentSkips?: CommentSkips;

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

  @state()
  private isBlameLoading = false;

  @state()
  private allPatchSets?: PatchSet[] = [];

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

  // visible for testing
  reviewedFiles = new Set<string>();

  private readonly reporting = getAppContext().reportingService;

  private readonly restApiService = getAppContext().restApiService;

  // Private but used in tests.
  readonly routerModel = getAppContext().routerModel;

  // Private but used in tests.
  readonly userModel = getAppContext().userModel;

  // Private but used in tests.
  readonly getChangeModel = resolve(this, changeModelToken);

  // Private but used in tests.
  readonly getBrowserModel = resolve(this, browserModelToken);

  // Private but used in tests.
  readonly getCommentsModel = resolve(this, commentsModelToken);

  private readonly getShortcutsService = resolve(this, shortcutsServiceToken);

  private readonly getConfigModel = resolve(this, configModelToken);

  private throttledToggleFileReviewed?: (e: KeyboardEvent) => void;

  @state()
  cursor?: GrDiffCursor;

  private connected$ = new BehaviorSubject(false);

  private readonly shortcutsController = new ShortcutController(this);

  constructor() {
    super();
    this.setupKeyboardShortcuts();
    this.setupSubscriptions();
  }

  private setupKeyboardShortcuts() {
    const listen = (shortcut: Shortcut, fn: (e: KeyboardEvent) => void) => {
      this.shortcutsController.addAbstract(shortcut, fn);
    };
    listen(Shortcut.LEFT_PANE, _ => this.cursor?.moveLeft());
    listen(Shortcut.RIGHT_PANE, _ => this.cursor?.moveRight());
    listen(Shortcut.NEXT_LINE, _ => this.handleNextLine());
    listen(Shortcut.PREV_LINE, _ => this.handlePrevLine());
    listen(Shortcut.VISIBLE_LINE, _ => this.cursor?.moveToVisibleArea());
    listen(Shortcut.NEXT_FILE_WITH_COMMENTS, _ =>
      this.moveToNextFileWithComment()
    );
    listen(Shortcut.PREV_FILE_WITH_COMMENTS, _ =>
      this.moveToPreviousFileWithComment()
    );
    listen(Shortcut.NEW_COMMENT, _ => this.handleNewComment());
    listen(Shortcut.SAVE_COMMENT, _ => {});
    listen(Shortcut.NEXT_FILE, _ => this.handleNextFile());
    listen(Shortcut.PREV_FILE, _ => this.handlePrevFile());
    listen(Shortcut.NEXT_CHUNK, _ => this.handleNextChunk());
    listen(Shortcut.PREV_CHUNK, _ => this.handlePrevChunk());
    listen(Shortcut.NEXT_COMMENT_THREAD, _ => this.handleNextCommentThread());
    listen(Shortcut.PREV_COMMENT_THREAD, _ => this.handlePrevCommentThread());
    listen(Shortcut.OPEN_REPLY_DIALOG, _ => this.handleOpenReplyDialog());
    listen(Shortcut.TOGGLE_LEFT_PANE, _ => this.handleToggleLeftPane());
    listen(Shortcut.OPEN_DOWNLOAD_DIALOG, _ => this.handleOpenDownloadDialog());
    listen(Shortcut.UP_TO_CHANGE, _ => this.handleUpToChange());
    listen(Shortcut.OPEN_DIFF_PREFS, _ => this.handleCommaKey());
    listen(Shortcut.TOGGLE_DIFF_MODE, _ => this.handleToggleDiffMode());
    listen(Shortcut.TOGGLE_FILE_REVIEWED, e => {
      if (this.throttledToggleFileReviewed) {
        this.throttledToggleFileReviewed(e);
      }
    });
    listen(Shortcut.TOGGLE_ALL_DIFF_CONTEXT, _ =>
      this.handleToggleAllDiffContext()
    );
    listen(Shortcut.NEXT_UNREVIEWED_FILE, _ => this.handleNextUnreviewedFile());
    listen(Shortcut.TOGGLE_BLAME, _ => this.toggleBlame());
    listen(Shortcut.TOGGLE_HIDE_ALL_COMMENT_THREADS, _ =>
      this.handleToggleHideAllCommentThreads()
    );
    listen(Shortcut.OPEN_FILE_LIST, _ => this.handleOpenFileList());
    listen(Shortcut.DIFF_AGAINST_BASE, _ => this.handleDiffAgainstBase());
    listen(Shortcut.DIFF_AGAINST_LATEST, _ => this.handleDiffAgainstLatest());
    listen(Shortcut.DIFF_BASE_AGAINST_LEFT, _ =>
      this.handleDiffBaseAgainstLeft()
    );
    listen(Shortcut.DIFF_RIGHT_AGAINST_LATEST, _ =>
      this.handleDiffRightAgainstLatest()
    );
    listen(Shortcut.DIFF_BASE_AGAINST_LATEST, _ =>
      this.handleDiffBaseAgainstLatest()
    );
    listen(Shortcut.EXPAND_ALL_COMMENT_THREADS, _ => {}); // docOnly
    listen(Shortcut.COLLAPSE_ALL_COMMENT_THREADS, _ => {}); // docOnly
    this.shortcutsController.addGlobal({key: Key.ESC}, _ => {
      assertIsDefined(this.diffHost, 'diffHost');
      this.diffHost.displayLine = false;
    });
  }

  private setupSubscriptions() {
    subscribe(
      this,
      () => this.userModel.loggedIn$,
      loggedIn => {
        this.loggedIn = loggedIn;
      }
    );
    subscribe(
      this,
      () => this.getConfigModel().serverConfig$,
      config => {
        this.serverConfig = config;
      }
    );
    subscribe(
      this,
      () => this.getCommentsModel().changeComments$,
      changeComments => {
        this.changeComments = changeComments;
      }
    );
    subscribe(
      this,
      () => this.userModel.preferences$,
      preferences => {
        this.userPrefs = preferences;
      }
    );
    subscribe(
      this,
      () => this.userModel.diffPreferences$,
      diffPreferences => {
        this.prefs = diffPreferences;
      }
    );
    subscribe(
      this,
      () => this.getChangeModel().change$,
      change => {
        // The diff view is tied to a specific change number, so don't update
        // change to undefined.
        if (change) this.change = change;
      }
    );
    subscribe(
      this,
      () => this.getChangeModel().reviewedFiles$,
      reviewedFiles => {
        this.reviewedFiles = new Set(reviewedFiles) ?? new Set();
      }
    );
    subscribe(
      this,
      () => this.getChangeModel().diffPath$,
      path => (this.path = path)
    );

    subscribe(
      this,
      () =>
        combineLatest([
          this.getChangeModel().diffPath$,
          this.getChangeModel().reviewedFiles$,
        ]),
      ([path, files]) => {
        this.updateComplete.then(() => {
          assertIsDefined(this.reviewed, 'reviewed');
          this.reviewed.checked = !!path && !!files && files.includes(path);
        });
      }
    );

    // When user initially loads the diff view, we want to autmatically mark
    // the file as reviewed if they have it enabled. We can't observe these
    // properties since the method will be called anytime a property updates
    // but we only want to call this on the initial load.
    subscribe(
      this,
      () =>
        this.getChangeModel().diffPath$.pipe(
          filter(diffPath => !!diffPath),
          switchMap(() =>
            combineLatest([
              this.getChangeModel().patchNum$,
              this.routerModel.routerView$,
              this.userModel.diffPreferences$,
              this.getChangeModel().reviewedFiles$,
            ]).pipe(
              filter(
                ([patchNum, routerView, diffPrefs, reviewedFiles]) =>
                  !!patchNum &&
                  routerView === GerritView.DIFF &&
                  !!diffPrefs &&
                  !!reviewedFiles
              ),
              take(1)
            )
          )
        ),
      ([patchNum, _routerView, diffPrefs]) => {
        this.setReviewedStatus(patchNum!, diffPrefs);
      }
    );
    subscribe(
      this,
      () => this.getChangeModel().diffPath$,
      path => (this.path = path)
    );
  }

  static override get styles() {
    return [
      a11yStyles,
      sharedStyles,
      css`
        :host {
          display: block;
          background-color: var(--view-background-color);
        }
        .hidden {
          display: none;
        }
        gr-patch-range-select {
          display: block;
        }
        gr-diff {
          border: none;
        }
        .stickyHeader {
          background-color: var(--view-background-color);
          position: sticky;
          top: 0;
          /* TODO(dhruvsri): This is required only because of 'position:relative' in
            <gr-diff-highlight> (which could maybe be removed??). */
          z-index: 1;
          box-shadow: var(--elevation-level-1);
          /* This is just for giving the box-shadow some space. */
          margin-bottom: 2px;
        }
        header,
        .subHeader {
          align-items: center;
          display: flex;
          justify-content: space-between;
        }
        header {
          padding: var(--spacing-s) var(--spacing-xl);
          border-bottom: 1px solid var(--border-color);
        }
        .changeNumberColon {
          color: transparent;
        }
        .headerSubject {
          margin-right: var(--spacing-m);
          font-weight: var(--font-weight-bold);
        }
        .patchRangeLeft {
          align-items: center;
          display: flex;
        }
        .navLink:not([href]) {
          color: var(--deemphasized-text-color);
        }
        .navLinks {
          align-items: center;
          display: flex;
          white-space: nowrap;
        }
        .navLink {
          padding: 0 var(--spacing-xs);
        }
        .reviewed {
          display: inline-block;
          margin: 0 var(--spacing-xs);
          vertical-align: top;
          position: relative;
          top: 8px;
        }
        .jumpToFileContainer {
          display: inline-block;
          word-break: break-all;
        }
        .mobile {
          display: none;
        }
        gr-button {
          padding: var(--spacing-s) 0;
          text-decoration: none;
        }
        .loading {
          color: var(--deemphasized-text-color);
          font-family: var(--header-font-family);
          font-size: var(--font-size-h1);
          font-weight: var(--font-weight-h1);
          line-height: var(--line-height-h1);
          height: 100%;
          padding: var(--spacing-l);
          text-align: center;
        }
        .subHeader {
          background-color: var(--background-color-secondary);
          flex-wrap: wrap;
          padding: 0 var(--spacing-l);
        }
        .prefsButton {
          text-align: right;
        }
        .editMode .hideOnEdit {
          display: none;
        }
        .blameLoader,
        .fileNum {
          display: none;
        }
        .blameLoader.show,
        .fileNum.show,
        .download,
        .preferences,
        .rightControls {
          align-items: center;
          display: flex;
        }
        .diffModeSelector,
        .editButton {
          align-items: center;
          display: flex;
        }
        .diffModeSelector span,
        .editButton span {
          margin-right: var(--spacing-xs);
        }
        .diffModeSelector.hide,
        .separator.hide {
          display: none;
        }
        .editButtona a {
          text-decoration: none;
        }
        @media screen and (max-width: 50em) {
          header {
            padding: var(--spacing-s) var(--spacing-l);
          }
          .dash {
            display: none;
          }
          .desktop {
            display: none;
          }
          .fileNav {
            align-items: flex-start;
            display: flex;
            margin: 0 var(--spacing-xs);
          }
          .fullFileName {
            display: block;
            font-style: italic;
            min-width: 50%;
            padding: 0 var(--spacing-xxs);
            text-align: center;
            width: 100%;
            word-wrap: break-word;
          }
          .reviewed {
            vertical-align: -1px;
          }
          .mobileNavLink {
            color: var(--primary-text-color);
            font-family: var(--header-font-family);
            font-size: var(--font-size-h2);
            font-weight: var(--font-weight-h2);
            line-height: var(--line-height-h2);
            text-decoration: none;
          }
          .mobileNavLink:not([href]) {
            color: var(--deemphasized-text-color);
          }
          .jumpToFileContainer {
            display: block;
            width: 100%;
            word-break: break-all;
          }
          /* prettier formatter removes semi-colons after css mixins. */
          /* prettier-ignore */
          gr-dropdown-list {
            width: 100%;
            --gr-select-style-width: 100%;
            --gr-select-style-display: block;
            --native-select-style-width: 100%;
          }
        }
        :host(.hideComments) {
          --gr-comment-thread-display: none;
        }
      `,
    ];
  }

  override connectedCallback() {
    super.connectedCallback();
    this.connected$.next(true);
    this.throttledToggleFileReviewed = throttleWrap(_ =>
      this.handleToggleFileReviewed()
    );
    this.addEventListener('open-fix-preview', e => this.onOpenFixPreview(e));
    this.cursor = new GrDiffCursor();
  }

  override disconnectedCallback() {
    this.cursor?.dispose();
    this.connected$.next(false);
    super.disconnectedCallback();
  }

  protected override willUpdate(changedProperties: PropertyValues) {
    super.willUpdate(changedProperties);
    if (changedProperties.has('change')) {
      this.allPatchSets = computeAllPatchSets(this.change);
    }
    if (
      changedProperties.has('commentMap') ||
      changedProperties.has('files') ||
      changedProperties.has('path')
    ) {
      this.commentSkips = this.computeCommentSkips(
        this.commentMap,
        this.files?.sortedFileList,
        this.path
      );
    }

    if (
      changedProperties.has('changeNum') ||
      changedProperties.has('changeComments') ||
      changedProperties.has('patchRange')
    ) {
      this.fetchFiles();
    }
  }

  private reInitCursor() {
    assertIsDefined(this.diffHost, 'diffHost');
    this.cursor?.replaceDiffs([this.diffHost]);
    this.cursor?.reInitCursor();
  }

  protected override updated(changedProperties: PropertyValues): void {
    super.updated(changedProperties);
    if (
      changedProperties.has('changeComments') ||
      changedProperties.has('path') ||
      changedProperties.has('patchRange') ||
      changedProperties.has('files')
    ) {
      if (this.changeComments && this.path && this.patchRange) {
        assertIsDefined(this.diffHost, 'diffHost');
        const file = this.files?.changeFilesByPath
          ? this.files.changeFilesByPath[this.path]
          : undefined;
        this.diffHost.updateComplete.then(() => {
          assertIsDefined(this.path);
          assertIsDefined(this.patchRange);
          assertIsDefined(this.diffHost);
          assertIsDefined(this.changeComments);
          this.diffHost.threads = this.changeComments.getThreadsBySideForFile(
            {path: this.path, basePath: file?.old_path},
            this.patchRange
          );
        });
      }
    }
  }

  override render() {
    const file = this.getFileRange();
    return html`
      ${this.renderStickyHeader()}
      <div class="loading" ?hidden=${!this.loading}>Loading...</div>
      <h2 class="assistive-tech-only">Diff view</h2>
      <gr-diff-host
        id="diffHost"
        ?hidden=${this.loading}
        .changeNum=${this.changeNum}
        .change=${this.change}
        .commitRange=${this.commitRange}
        .patchRange=${this.patchRange}
        .file=${file}
        .path=${this.path}
        .projectName=${this.change?.project}
        @is-blame-loaded-changed=${this.onIsBlameLoadedChanged}
        @comment-anchor-tap=${this.onLineSelected}
        @line-selected=${this.onLineSelected}
        @diff-changed=${this.onDiffChanged}
        @edit-weblinks-changed=${this.onEditWeblinksChanged}
        @files-weblinks-changed=${this.onFilesWeblinksChanged}
        @is-image-diff-changed=${this.onIsImageDiffChanged}
        @render=${this.reInitCursor}
      >
      </gr-diff-host>
      ${this.renderDialogs()}
    `;
  }

  private renderStickyHeader() {
    return html` <div
      class="stickyHeader ${this.computeEditMode() ? 'editMode' : ''}"
    >
      <h1 class="assistive-tech-only">
        Diff of ${this.path ? computeTruncatedPath(this.path) : ''}
      </h1>
      <header>${this.renderHeader()}</header>
      <div class="subHeader">
        ${this.renderPatchRangeLeft()} ${this.renderRightControls()}
      </div>
      <div class="fileNav mobile">
        <a class="mobileNavLink" href=${ifDefined(this.computeNavLinkURL(-1))}
          >&lt;</a
        >
        <div class="fullFileName mobile">${computeDisplayPath(this.path)}</div>
        <a class="mobileNavLink" href=${ifDefined(this.computeNavLinkURL(1))}
          >&gt;</a
        >
      </div>
    </div>`;
  }

  private renderHeader() {
    const formattedFiles = this.formatFilesForDropdown();
    const fileNum = this.computeFileNum(formattedFiles);
    const fileNumClass = this.computeFileNumClass(fileNum, formattedFiles);
    return html` <div>
        <a href=${this.getChangePath()}>${this.changeNum}</a
        ><span class="changeNumberColon">:</span>
        <span class="headerSubject">${this.change?.subject}</span>
        <input
          id="reviewed"
          class="reviewed hideOnEdit"
          type="checkbox"
          ?hidden=${!this.loggedIn}
          title="Toggle reviewed status of file"
          aria-label="file reviewed"
          @change=${this.handleReviewedChange}
        />
        <div class="jumpToFileContainer">
          <gr-dropdown-list
            id="dropdown"
            .value=${this.path}
            .items=${formattedFiles}
            show-copy-for-trigger-text
            @value-change=${this.handleFileChange}
          ></gr-dropdown-list>
        </div>
      </div>
      <div class="navLinks desktop">
        <span class="fileNum ${ifDefined(fileNumClass)}">
          File ${fileNum} of ${formattedFiles.length}
          <span class="separator"></span>
        </span>
        <a
          class="navLink"
          title=${this.createTitle(
            Shortcut.PREV_FILE,
            ShortcutSection.NAVIGATION
          )}
          href=${ifDefined(this.computeNavLinkURL(-1))}
          >Prev</a
        >
        <span class="separator"></span>
        <a
          class="navLink"
          title=${this.createTitle(
            Shortcut.UP_TO_CHANGE,
            ShortcutSection.NAVIGATION
          )}
          href=${this.getChangePath()}
          >Up</a
        >
        <span class="separator"></span>
        <a
          class="navLink"
          title=${this.createTitle(
            Shortcut.NEXT_FILE,
            ShortcutSection.NAVIGATION
          )}
          href=${ifDefined(this.computeNavLinkURL(1))}
          >Next</a
        >
      </div>`;
  }

  private renderPatchRangeLeft() {
    const revisionInfo = this.change
      ? new RevisionInfoObj(this.change)
      : undefined;
    return html` <div class="patchRangeLeft">
      <gr-patch-range-select
        id="rangeSelect"
        .changeNum=${this.changeNum}
        .patchNum=${this.patchRange?.patchNum}
        .basePatchNum=${this.patchRange?.basePatchNum}
        .filesWeblinks=${this.filesWeblinks}
        .availablePatches=${this.allPatchSets}
        .revisions=${this.change?.revisions}
        .revisionInfo=${revisionInfo}
        @patch-range-change=${this.handlePatchChange}
      >
      </gr-patch-range-select>
      <span class="download desktop">
        <span class="separator"></span>
        <gr-dropdown
          link=""
          down-arrow=""
          .items=${this.computeDownloadDropdownLinks()}
          horizontal-align="left"
        >
          <span class="downloadTitle"> Download </span>
        </gr-dropdown>
      </span>
    </div>`;
  }

  private renderRightControls() {
    const blameLoaderClass =
      !isMagicPath(this.path) && !this.isImageDiff ? 'show' : '';
    const blameToggleLabel =
      this.isBlameLoaded && !this.isBlameLoading ? 'Hide blame' : 'Show blame';
    const diffModeSelectorClass = !this.diff || this.diff.binary ? 'hide' : '';
    return html` <div class="rightControls">
      <span class="blameLoader ${blameLoaderClass}">
        <gr-button
          link=""
          id="toggleBlame"
          title=${this.createTitle(
            Shortcut.TOGGLE_BLAME,
            ShortcutSection.DIFFS
          )}
          ?disabled=${this.isBlameLoading}
          @click=${this.toggleBlame}
          >${blameToggleLabel}</gr-button
        >
      </span>
      ${when(
        this.computeCanEdit(),
        () => html`
          <span class="separator"></span>
          <span class="editButton">
            <gr-button
              link=""
              title="Edit current file"
              @click=${this.goToEditFile}
              >edit</gr-button
            >
          </span>
        `
      )}
      ${when(
        this.computeShowEditLinks(),
        () => html`
          <span class="separator"></span>
          ${this.editWeblinks!.map(
            weblink => html`
              <a target="_blank" href=${ifDefined(weblink.url)}
                >${weblink.name}</a
              >
            `
          )}
        `
      )}
      <span class="separator"></span>
      <div class="diffModeSelector ${diffModeSelectorClass}">
        <span>Diff view:</span>
        <gr-diff-mode-selector
          id="modeSelect"
          .saveOnChange=${this.loggedIn}
          show-tooltip-below
        ></gr-diff-mode-selector>
      </div>
      ${when(
        this.loggedIn && this.prefs,
        () => html`
          <span id="diffPrefsContainer">
            <span class="preferences desktop">
              <gr-tooltip-content
                has-tooltip=""
                position-below=""
                title="Diff preferences"
              >
                <gr-button
                  link=""
                  class="prefsButton"
                  @click=${(e: Event) => this.handlePrefsTap(e)}
                  ><gr-icon icon="settings" filled></gr-icon
                ></gr-button>
              </gr-tooltip-content>
            </span>
          </span>
        `
      )}
      <gr-endpoint-decorator name="annotation-toggler">
        <span hidden="" id="annotation-span">
          <label for="annotation-checkbox" id="annotation-label"></label>
          <iron-input>
            <input
              is="iron-input"
              type="checkbox"
              id="annotation-checkbox"
              disabled=""
            />
          </iron-input>
        </span>
      </gr-endpoint-decorator>
    </div>`;
  }

  private renderDialogs() {
    return html` <gr-apply-fix-dialog
        id="applyFixDialog"
        .change=${this.change}
        .changeNum=${this.changeNum}
      >
      </gr-apply-fix-dialog>
      <gr-diff-preferences-dialog
        id="diffPreferencesDialog"
        @reload-diff-preference=${this.handleReloadingDiffPreference}
      >
      </gr-diff-preferences-dialog>
      <gr-overlay id="downloadOverlay">
        <gr-download-dialog
          id="downloadDialog"
          .change=${this.change}
          .patchNum=${this.patchRange?.patchNum}
          .config=${this.serverConfig?.download}
          @close=${this.handleDownloadDialogClose}
        ></gr-download-dialog>
      </gr-overlay>`;
  }

  /**
   * Set initial review status of the file.
   * automatically mark the file as reviewed if manual review is not set.
   */
  setReviewedStatus(
    patchNum: RevisionPatchSetNum,
    diffPrefs: DiffPreferencesInfo
  ) {
    if (!this.loggedIn) return;
    if (!diffPrefs.manual_review) {
      this.setReviewed(true, patchNum);
    }
  }

  private getFileRange() {
    if (!this.files || !this.path) return;
    const fileInfo = this.files.changeFilesByPath[this.path];
    const fileRange: FileRange = {path: this.path};
    if (fileInfo && fileInfo.old_path) {
      fileRange.basePath = fileInfo.old_path;
    }
    return fileRange;
  }

  // Private but used in tests.
  fetchFiles() {
    if (!this.changeNum || !this.patchRange || !this.changeComments) {
      return Promise.resolve();
    }

    if (!this.patchRange.patchNum) {
      return Promise.resolve();
    }

    return this.restApiService
      .getChangeFiles(this.changeNum, this.patchRange)
      .then(changeFiles => {
        if (!changeFiles) return;
        const commentedPaths = this.changeComments!.getPaths(this.patchRange);
        const files = {...changeFiles};
        addUnmodifiedFiles(files, commentedPaths);
        this.files = {
          sortedFileList: Object.keys(files).sort(specialFilePathCompare),
          changeFilesByPath: files,
        };
      });
  }

  private handleReviewedChange(e: Event) {
    const input = e.target as HTMLInputElement;
    this.setReviewed(input.checked ?? false);
  }

  // Private but used in tests.
  setReviewed(
    reviewed: boolean,
    patchNum: RevisionPatchSetNum | undefined = this.patchRange?.patchNum
  ) {
    if (this.computeEditMode()) return;
    if (!patchNum || !this.path || !this.changeNum) return;
    // if file is already reviewed then do not make a saveReview request
    if (this.reviewedFiles.has(this.path) && reviewed) return;
    this.getChangeModel().setReviewedFilesStatus(
      this.changeNum,
      patchNum,
      this.path,
      reviewed
    );
  }

  // Private but used in tests.
  handleToggleFileReviewed() {
    assertIsDefined(this.reviewed);
    this.setReviewed(!this.reviewed.checked);
  }

  private handlePrevLine() {
    assertIsDefined(this.diffHost, 'diffHost');
    this.diffHost.displayLine = true;
    this.cursor?.moveUp();
  }

  private onOpenFixPreview(e: OpenFixPreviewEvent) {
    assertIsDefined(this.applyFixDialog, 'applyFixDialog');
    this.applyFixDialog.open(e);
  }

  private onIsBlameLoadedChanged(e: ValueChangedEvent<boolean>) {
    this.isBlameLoaded = e.detail.value;
  }

  private onDiffChanged(e: ValueChangedEvent<DiffInfo>) {
    this.diff = e.detail.value;
  }

  private onEditWeblinksChanged(
    e: ValueChangedEvent<GeneratedWebLink[] | undefined>
  ) {
    this.editWeblinks = e.detail.value;
  }

  private onFilesWeblinksChanged(
    e: ValueChangedEvent<FilesWebLinks | undefined>
  ) {
    this.filesWeblinks = e.detail.value;
  }

  private onIsImageDiffChanged(e: ValueChangedEvent<boolean>) {
    this.isImageDiff = e.detail.value;
  }

  private handleNextLine() {
    assertIsDefined(this.diffHost, 'diffHost');
    this.diffHost.displayLine = true;
    this.cursor?.moveDown();
  }

  // Private but used in tests.
  moveToPreviousFileWithComment() {
    if (!this.commentSkips) return;
    if (!this.change) return;
    if (!this.patchRange?.patchNum) return;

    // If there is no previous diff with comments, then return to the change
    // view.
    if (!this.commentSkips.previous) {
      this.navToChangeView();
      return;
    }

    GerritNav.navigateToDiff(
      this.change,
      this.commentSkips.previous,
      this.patchRange.patchNum,
      this.patchRange.basePatchNum
    );
  }

  // Private but used in tests.
  moveToNextFileWithComment() {
    if (!this.commentSkips) return;
    if (!this.change) return;
    if (!this.patchRange?.patchNum) return;

    // If there is no next diff with comments, then return to the change view.
    if (!this.commentSkips.next) {
      this.navToChangeView();
      return;
    }

    GerritNav.navigateToDiff(
      this.change,
      this.commentSkips.next,
      this.patchRange.patchNum,
      this.patchRange.basePatchNum
    );
  }

  private handleNewComment() {
    this.classList.remove('hideComments');
    this.cursor?.createCommentInPlace();
  }

  private handlePrevFile() {
    if (!this.path) return;
    if (!this.files?.sortedFileList) return;
    this.navToFile(this.files.sortedFileList, -1);
  }

  private handleNextFile() {
    if (!this.path) return;
    if (!this.files?.sortedFileList) return;
    this.navToFile(this.files.sortedFileList, 1);
  }

  private handleNextChunk() {
    const result = this.cursor?.moveToNextChunk();
    if (result === CursorMoveResult.CLIPPED && this.cursor?.isAtEnd()) {
      this.showToastAndNavigateFile('next', 'n');
    }
  }

  private handleNextCommentThread() {
    const result = this.cursor?.moveToNextCommentThread();
    if (result === CursorMoveResult.CLIPPED) {
      this.navigateToNextFileWithCommentThread();
    }
  }

  private lastDisplayedNavigateToFileToast: Map<string, number> = new Map();

  private showToastAndNavigateFile(direction: string, shortcut: string) {
    /*
     * If user presses p/n on the first/last diff chunk, show a toast informing
     * user that pressing it again will navigate them to previous/next
     * unreviewedfile if click happens within the time limit
     */
    if (
      this.lastDisplayedNavigateToFileToast.get(direction) &&
      Date.now() - this.lastDisplayedNavigateToFileToast.get(direction)! <=
        NAVIGATE_TO_NEXT_FILE_TIMEOUT_MS
    ) {
      // reset for next file
      this.lastDisplayedNavigateToFileToast.delete(direction);
      this.navigateToUnreviewedFile(direction);
    } else {
      this.lastDisplayedNavigateToFileToast.set(direction, Date.now());
      fireAlert(
        this,
        `Press ${shortcut} again to navigate to ${direction} unreviewed file`
      );
    }
  }

  private navigateToUnreviewedFile(direction: string) {
    if (!this.path) return;
    if (!this.files?.sortedFileList) return;
    if (!this.reviewedFiles) return;
    // Ensure that the currently viewed file always appears in unreviewedFiles
    // so we resolve the right "next" file.
    const unreviewedFiles = this.files.sortedFileList.filter(
      file => file === this.path || !this.reviewedFiles.has(file)
    );

    this.navToFile(unreviewedFiles, direction === 'next' ? 1 : -1);
  }

  private handlePrevChunk() {
    this.cursor?.moveToPreviousChunk();
    if (this.cursor?.isAtStart()) {
      this.showToastAndNavigateFile('previous', 'p');
    }
  }

  private handlePrevCommentThread() {
    this.cursor?.moveToPreviousCommentThread();
  }

  // Similar to gr-change-view.handleOpenReplyDialog
  private handleOpenReplyDialog() {
    if (!this.loggedIn) {
      fireEvent(this, 'show-auth-required');
      return;
    }
    this.navToChangeView(true);
  }

  private handleToggleLeftPane() {
    assertIsDefined(this.diffHost, 'diffHost');
    this.diffHost.toggleLeftDiff();
  }

  private handleOpenDownloadDialog() {
    assertIsDefined(this.downloadOverlay, 'downloadOverlay');
    this.downloadOverlay.open().then(() => {
      assertIsDefined(this.downloadOverlay, 'downloadOverlay');
      assertIsDefined(this.downloadDialog, 'downloadOverlay');
      this.downloadOverlay.setFocusStops(this.downloadDialog.getFocusStops());
      this.downloadDialog.focus();
    });
  }

  private handleDownloadDialogClose() {
    assertIsDefined(this.downloadOverlay, 'downloadOverlay');
    this.downloadOverlay.close();
  }

  private handleUpToChange() {
    this.navToChangeView();
  }

  private handleCommaKey() {
    if (!this.loggedIn) return;
    assertIsDefined(this.diffPreferencesDialog, 'diffPreferencesDialog');
    this.diffPreferencesDialog.open();
  }

  // Private but used in tests.
  handleToggleDiffMode() {
    if (!this.userPrefs) return;
    if (this.userPrefs.diff_view === DiffViewMode.SIDE_BY_SIDE) {
      this.userModel.updatePreferences({diff_view: DiffViewMode.UNIFIED});
    } else {
      this.userModel.updatePreferences({
        diff_view: DiffViewMode.SIDE_BY_SIDE,
      });
    }
  }

  // Private but used in tests.
  navToChangeView(openReplyDialog = false) {
    if (!this.changeNum || !this.patchRange?.patchNum) {
      return;
    }
    this.navigateToChange(
      this.change,
      this.patchRange,
      this.change && this.change.revisions,
      openReplyDialog
    );
  }

  // Private but used in tests.
  navToFile(
    fileList: string[],
    direction: -1 | 1,
    navigateToFirstComment?: boolean
  ) {
    const newPath = this.getNavLinkPath(fileList, direction);
    if (!newPath) return;
    if (!this.change) return;
    if (!this.patchRange) return;

    if (newPath.up) {
      this.navigateToChange(
        this.change,
        this.patchRange,
        this.change && this.change.revisions
      );
      return;
    }

    if (!newPath.path) return;
    let lineNum;
    if (navigateToFirstComment)
      lineNum = this.changeComments?.getCommentsForPath(
        newPath.path,
        this.patchRange
      )?.[0].line;
    GerritNav.navigateToDiff(
      this.change,
      newPath.path,
      this.patchRange.patchNum,
      this.patchRange.basePatchNum,
      lineNum
    );
  }

  /**
   * @param direction Either 1 (next file) or -1 (prev file).
   * @return The next URL when proceeding in the specified
   * direction.
   */
  private computeNavLinkURL(direction?: -1 | 1) {
    if (!this.change) return;
    if (!this.path) return;
    if (!this.files?.sortedFileList) return;
    if (!direction) return;

    const newPath = this.getNavLinkPath(this.files.sortedFileList, direction);
    if (!newPath) {
      return;
    }

    if (newPath.up) {
      return this.getChangePath();
    }
    return this.getDiffUrl(this.change, this.patchRange, newPath.path);
  }

  private goToEditFile() {
    if (!this.change) return;
    if (!this.path) return;
    if (!this.patchRange) return;

    // TODO(taoalpha): add a shortcut for editing
    const cursorAddress = this.cursor?.getAddress();
    const editUrl = GerritNav.getEditUrlForDiff(
      this.change,
      this.path,
      this.patchRange.patchNum,
      cursorAddress?.number
    );
    GerritNav.navigateToRelativeUrl(editUrl);
  }

  /**
   * Gives an object representing the target of navigating either left or
   * right through the change. The resulting object will have one of the
   * following forms:
   * * {path: "<target file path>"} - When another file path should be the
   * result of the navigation.
   * * {up: true} - When the result of navigating should go back to the
   * change view.
   * * null - When no navigation is possible for the given direction.
   *
   * @param path The path of the current file being shown.
   * @param fileList The list of files in this change and
   * patch range.
   * @param direction Either 1 (next file) or -1 (prev file).
   */
  private getNavLinkPath(fileList: string[], direction: -1 | 1) {
    if (!this.path || !fileList || fileList.length === 0) {
      return null;
    }

    let idx = fileList.indexOf(this.path);
    if (idx === -1) {
      const file = direction > 0 ? fileList[0] : fileList[fileList.length - 1];
      return {path: file};
    }

    idx += direction;
    // Redirect to the change view if opt_noUp isn’t truthy and idx falls
    // outside the bounds of [0, fileList.length).
    if (idx < 0 || idx > fileList.length - 1) {
      return {up: true};
    }

    return {path: fileList[idx]};
  }

  // Private but used in tests.
  initLineOfInterestAndCursor(leftSide: boolean) {
    assertIsDefined(this.diffHost, 'diffHost');
    this.diffHost.lineOfInterest = this.getLineOfInterest(leftSide);
    this.initCursor(leftSide);
  }

  // Private but used in tests.
  displayDiffBaseAgainstLeftToast() {
    if (!this.patchRange) return;
    fireAlert(
      this,
      `Patchset ${this.patchRange.basePatchNum} vs ` +
        `${this.patchRange.patchNum} selected. Press v + \u2190 to view ` +
        `Base vs ${this.patchRange.basePatchNum}`
    );
  }

  private displayDiffAgainstLatestToast(latestPatchNum?: PatchSetNum) {
    if (!this.patchRange) return;
    const leftPatchset =
      this.patchRange.basePatchNum === PARENT
        ? 'Base'
        : `Patchset ${this.patchRange.basePatchNum}`;
    fireAlert(
      this,
      `${leftPatchset} vs
            ${this.patchRange.patchNum} selected\n. Press v + \u2191 to view
            ${leftPatchset} vs Patchset ${latestPatchNum}`
    );
  }

  private displayToasts() {
    if (!this.patchRange) return;
    if (this.patchRange.basePatchNum !== PARENT) {
      this.displayDiffBaseAgainstLeftToast();
      return;
    }
    const latestPatchNum = computeLatestPatchNum(this.allPatchSets);
    if (this.patchRange.patchNum !== latestPatchNum) {
      this.displayDiffAgainstLatestToast(latestPatchNum);
      return;
    }
  }

  private initCommitRange() {
    let commit: CommitId | undefined;
    let baseCommit: CommitId | undefined;
    if (!this.change) return;
    if (!this.patchRange || !this.patchRange.patchNum) return;
    const revisions = this.change.revisions ?? {};
    for (const [commitSha, revision] of Object.entries(revisions)) {
      const patchNum = revision._number;
      if (patchNum === this.patchRange.patchNum) {
        commit = commitSha as CommitId;
        const commitObj = revision.commit;
        const parents = commitObj?.parents || [];
        if (this.patchRange.basePatchNum === PARENT && parents.length) {
          baseCommit = parents[parents.length - 1].commit;
        }
      } else if (patchNum === this.patchRange.basePatchNum) {
        baseCommit = commitSha as CommitId;
      }
    }
    this.commitRange = commit && baseCommit ? {commit, baseCommit} : undefined;
  }

  private updateUrlToDiffUrl(lineNum?: number, leftSide?: boolean) {
    if (!this.change) return;
    if (!this.patchRange) return;
    if (!this.changeNum) return;
    if (!this.path) return;
    const url = GerritNav.getUrlForDiffById(
      this.changeNum,
      this.change.project,
      this.path,
      this.patchRange.patchNum,
      this.patchRange.basePatchNum,
      lineNum,
      leftSide
    );
    history.replaceState(null, '', url);
  }

  // Private but used in tests.
  initPatchRange() {
    let leftSide = false;
    if (!this.change) return;
    if (this.params?.view !== GerritView.DIFF) return;
    if (this.params?.commentId) {
      const comment = this.changeComments?.findCommentById(
        this.params.commentId
      );
      if (!comment) {
        fireAlert(this, 'comment not found');
        GerritNav.navigateToChange(this.change);
        return;
      }
      this.getChangeModel().updatePath(comment.path);

      const latestPatchNum = computeLatestPatchNum(this.allPatchSets);
      if (!latestPatchNum) throw new Error('Missing allPatchSets');
      this.patchRange = getPatchRangeForCommentUrl(comment, latestPatchNum);
      leftSide = isInBaseOfPatchRange(comment, this.patchRange);

      this.focusLineNum = comment.line;
    } else {
      if (this.params.path) {
        this.getChangeModel().updatePath(this.params.path);
      }
      if (this.params.patchNum) {
        this.patchRange = {
          patchNum: this.params.patchNum,
          basePatchNum: this.params.basePatchNum || PARENT,
        };
      }
      if (this.params.lineNum) {
        this.focusLineNum = this.params.lineNum;
        leftSide = !!this.params.leftSide;
      }
    }
    assertIsDefined(this.patchRange, 'patchRange');
    this.initLineOfInterestAndCursor(leftSide);

    if (this.params?.commentId) {
      // url is of type /comment/{commentId} which isn't meaningful
      this.updateUrlToDiffUrl(this.focusLineNum, leftSide);
    }

    this.commentMap = this.getPaths();
  }

  // Private but used in tests.
  isFileUnchanged(diff?: DiffInfo) {
    if (!diff || !diff.content) return false;
    return !diff.content.some(
      content =>
        (content.a && !content.common) || (content.b && !content.common)
    );
  }

  private isSameDiffLoaded(value: AppElementDiffViewParam) {
    return (
      this.patchRange?.basePatchNum === value.basePatchNum &&
      this.patchRange?.patchNum === value.patchNum &&
      this.path === value.path
    );
  }

  private async untilModelLoaded() {
    // NOTE: Wait until this page is connected before determining whether the
    // model is loaded.  This can happen when params are changed when setting up
    // this view. It's unclear whether this issue is related to Polymer
    // specifically.
    if (!this.isConnected) {
      await until(this.connected$, connected => connected);
    }
    await until(
      this.getChangeModel().changeLoadingStatus$,
      status => status === LoadingStatus.LOADED
    );
  }

  // Private but used in tests.
  paramsChanged() {
    if (this.params?.view !== GerritView.DIFF) {
      return;
    }

    const params = this.params;

    // The diff view is kept in the background once created. If the user
    // scrolls in the change page, the scrolling is reflected in the diff view
    // as well, which means the diff is scrolled to a random position based
    // on how much the change view was scrolled.
    // Hence, reset the scroll position here.
    document.documentElement.scrollTop = 0;

    // Everything in the diff view is tied to the change. It seems better to
    // force the re-creation of the diff view when the change number changes.
    const changeChanged = this.changeNum !== params.changeNum;
    if (this.changeNum !== undefined && changeChanged) {
      fireEvent(this, EventType.RECREATE_DIFF_VIEW);
      return;
    } else if (this.changeNum !== undefined && this.isSameDiffLoaded(params)) {
      // changeNum has not changed, so check if there are changes in patchRange
      // path. If no changes then we can simply render the view as is.
      this.reporting.reportInteraction('diff-view-re-rendered');
      // Make sure to re-initialize the cursor because this is typically
      // done on the 'render' event which doesn't fire in this path as
      // rerendering is avoided.
      this.reInitCursor();
      this.diffHost?.initLayers();
      return;
    }

    this.files = {sortedFileList: [], changeFilesByPath: {}};
    if (this.isConnected) {
      this.getChangeModel().updatePath(undefined);
    }
    this.patchRange = undefined;
    this.commitRange = undefined;
    this.focusLineNum = undefined;

    if (params.changeNum && params.project) {
      this.restApiService.setInProjectLookup(params.changeNum, params.project);
    }

    this.changeNum = params.changeNum;
    this.classList.remove('hideComments');

    // When navigating away from the page, there is a possibility that the
    // patch number is no longer a part of the URL (say when navigating to
    // the top-level change info view) and therefore undefined in `params`.
    // If route is of type /comment/<commentId>/ then no patchNum is present
    if (!params.patchNum && !params.commentLink) {
      this.reporting.error(
        new Error(`Invalid diff view URL, no patchNum found: ${this.params}`)
      );
      return;
    }

    const promises: Promise<unknown>[] = [];
    if (!this.change) {
      promises.push(this.untilModelLoaded());
    }
    promises.push(this.waitUntilCommentsLoaded());

    if (this.diffHost) {
      this.diffHost.cancel();
      this.diffHost.clearDiffContent();
    }
    this.loading = true;
    return Promise.all(promises)
      .then(() => {
        this.loading = false;
        this.initPatchRange();
        this.initCommitRange();
        return this.updateComplete.then(() => this.diffHost!.reload(true));
      })
      .then(() => {
        this.reporting.diffViewDisplayed();
      })
      .then(() => {
        const fileUnchanged = this.isFileUnchanged(this.diff);
        if (fileUnchanged && params.commentLink) {
          assertIsDefined(this.change, 'change');
          assertIsDefined(this.path, 'path');
          assertIsDefined(this.patchRange, 'patchRange');

          if (this.patchRange.basePatchNum === PARENT) {
            // file is unchanged between Base vs X
            // hence should not show diff between Base vs Base
            return;
          }

          fireAlert(
            this,
            `File is unchanged between Patchset
                  ${this.patchRange.basePatchNum} and
                  ${this.patchRange.patchNum}. Showing diff of Base vs
                  ${this.patchRange.basePatchNum}`
          );
          GerritNav.navigateToDiff(
            this.change,
            this.path,
            this.patchRange.basePatchNum as RevisionPatchSetNum,
            PARENT,
            this.focusLineNum
          );
          return;
        }
        if (params.commentLink) {
          this.displayToasts();
        }
        // If the blame was loaded for a previous file and user navigates to
        // another file, then we load the blame for this file too
        if (this.isBlameLoaded) this.loadBlame();
      });
  }

  private async waitUntilCommentsLoaded() {
    await until(this.connected$, c => c);
    await until(this.getCommentsModel().commentsLoading$, isFalse);
  }

  /**
   * If the params specify a diff address then configure the diff cursor.
   * Private but used in tests.
   */
  initCursor(leftSide: boolean) {
    if (this.focusLineNum === undefined) {
      return;
    }
    if (!this.cursor) return;
    if (leftSide) {
      this.cursor.side = Side.LEFT;
    } else {
      this.cursor.side = Side.RIGHT;
    }
    this.cursor.initialLineNumber = this.focusLineNum;
  }

  // Private but used in tests.
  getLineOfInterest(leftSide: boolean): DisplayLine | undefined {
    // If there is a line number specified, pass it along to the diff so that
    // it will not get collapsed.
    if (!this.focusLineNum) {
      return undefined;
    }

    return {
      lineNum: this.focusLineNum,
      side: leftSide ? Side.LEFT : Side.RIGHT,
    };
  }

  private pathChanged() {
    if (this.path) {
      fireTitleChange(this, computeTruncatedPath(this.path));
    }
  }

  private getDiffUrl(
    change?: ChangeInfo | ParsedChangeInfo,
    patchRange?: PatchRange,
    path?: string
  ) {
    if (!change || !patchRange || !path) return '';
    return GerritNav.getUrlForDiff(
      change,
      path,
      patchRange.patchNum,
      patchRange.basePatchNum
    );
  }

  /**
   * When the latest patch of the change is selected (and there is no base
   * patch) then the patch range need not appear in the URL. Return a patch
   * range object with undefined values when a range is not needed.
   */
  private getChangeUrlRange(
    patchRange?: PatchRange,
    revisions?: {[revisionId: string]: RevisionInfo | EditRevisionInfo}
  ) {
    let patchNum = undefined;
    let basePatchNum = undefined;
    let latestPatchNum = -1;
    for (const rev of Object.values(revisions || {})) {
      if (typeof rev._number === 'number') {
        latestPatchNum = Math.max(latestPatchNum, rev._number);
      }
    }
    if (!patchRange) return {patchNum, basePatchNum};
    if (
      patchRange.basePatchNum !== PARENT ||
      patchRange.patchNum !== latestPatchNum
    ) {
      patchNum = patchRange.patchNum;
      basePatchNum = patchRange.basePatchNum;
    }
    return {patchNum, basePatchNum};
  }

  private getChangePath() {
    if (!this.change) return '';
    if (!this.patchRange) return '';

    const range = this.getChangeUrlRange(
      this.patchRange,
      this.change.revisions
    );
    return GerritNav.getUrlForChange(this.change, {
      patchNum: range.patchNum,
      basePatchNum: range.basePatchNum,
    });
  }

  // Private but used in tests.
  navigateToChange(
    change?: ChangeInfo | ParsedChangeInfo,
    patchRange?: PatchRange,
    revisions?: {[revisionId: string]: RevisionInfo | EditRevisionInfo},
    openReplyDialog?: boolean
  ) {
    if (!change) return;
    const range = this.getChangeUrlRange(patchRange, revisions);
    GerritNav.navigateToChange(change, {
      patchNum: range.patchNum,
      basePatchNum: range.basePatchNum,
      openReplyDialog: !!openReplyDialog,
    });
  }

  // Private but used in tests
  formatFilesForDropdown(): DropdownItem[] {
    if (!this.files) return [];
    if (!this.patchRange) return [];
    if (!this.changeComments) return [];

    const dropdownContent: DropdownItem[] = [];
    for (const path of this.files.sortedFileList) {
      dropdownContent.push({
        text: computeDisplayPath(path),
        mobileText: computeTruncatedPath(path),
        value: path,
        bottomText: this.changeComments.computeCommentsString(
          this.patchRange,
          path,
          this.files.changeFilesByPath[path],
          /* includeUnmodified= */ true
        ),
        file: {...this.files.changeFilesByPath[path], __path: path},
      });
    }
    return dropdownContent;
  }

  // Private but used in tests.
  handleFileChange(e: CustomEvent) {
    if (!this.change) return;
    if (!this.patchRange) return;

    // This is when it gets set initially.
    const path = e.detail.value;
    if (path === this.path) {
      return;
    }

    GerritNav.navigateToDiff(
      this.change,
      path,
      this.patchRange.patchNum,
      this.patchRange.basePatchNum
    );
  }

  // Private but used in tests.
  handlePatchChange(e: CustomEvent) {
    if (!this.change) return;
    if (!this.path) return;
    if (!this.patchRange) return;

    const {basePatchNum, patchNum} = e.detail;
    if (
      basePatchNum === this.patchRange.basePatchNum &&
      patchNum === this.patchRange.patchNum
    ) {
      return;
    }
    GerritNav.navigateToDiff(this.change, this.path, patchNum, basePatchNum);
  }

  // Private but used in tests.
  handlePrefsTap(e: Event) {
    e.preventDefault();
    assertIsDefined(this.diffPreferencesDialog, 'diffPreferencesDialog');
    this.diffPreferencesDialog.open();
  }

  // Private but used in tests.
  onLineSelected(e: CustomEvent) {
    // for on-comment-anchor-tap side can be PARENT/REVISIONS
    // for on-line-selected side can be left/right
    this.updateUrlToDiffUrl(
      e.detail.number,
      e.detail.side === Side.LEFT || e.detail.side === CommentSide.PARENT
    );
  }

  // Private but used in tests.
  computeDownloadDropdownLinks() {
    if (!this.change?.project) return [];
    if (!this.changeNum) return [];
    if (!this.patchRange?.patchNum) return [];
    if (!this.path) return [];

    const links = [
      {
        url: this.computeDownloadPatchLink(
          this.change.project,
          this.changeNum,
          this.patchRange,
          this.path
        ),
        name: 'Patch',
      },
    ];

    if (this.diff && this.diff.meta_a) {
      let leftPath = this.path;
      if (this.diff.change_type === 'RENAMED') {
        leftPath = this.diff.meta_a.name;
      }
      links.push({
        url: this.computeDownloadFileLink(
          this.change.project,
          this.changeNum,
          this.patchRange,
          leftPath,
          true
        ),
        name: 'Left Content',
      });
    }

    if (this.diff && this.diff.meta_b) {
      links.push({
        url: this.computeDownloadFileLink(
          this.change.project,
          this.changeNum,
          this.patchRange,
          this.path,
          false
        ),
        name: 'Right Content',
      });
    }

    return links;
  }

  // Private but used in tests.
  computeDownloadFileLink(
    project: RepoName,
    changeNum: NumericChangeId,
    patchRange: PatchRange,
    path: string,
    isBase?: boolean
  ) {
    let patchNum = patchRange.patchNum;
    let parent: number | undefined = undefined;

    if (isBase) {
      if (isMergeParent(patchRange.basePatchNum)) {
        parent = getParentIndex(patchRange.basePatchNum);
      } else if (patchRange.basePatchNum === PARENT) {
        parent = 1;
      } else {
        patchNum = patchRange.basePatchNum as PatchSetNumber;
      }
    }
    let url =
      changeBaseURL(project, changeNum, patchNum) +
      `/files/${encodeURIComponent(path)}/download`;
    if (parent) url += `?parent=${parent}`;

    return url;
  }

  // Private but used in tests.
  computeDownloadPatchLink(
    project: RepoName,
    changeNum: NumericChangeId,
    patchRange: PatchRange,
    path: string
  ) {
    let url = changeBaseURL(project, changeNum, patchRange.patchNum);
    url += '/patch?zip&path=' + encodeURIComponent(path);
    return url;
  }

  // Private but used in tests.
  getPaths(): CommentMap {
    if (!this.changeComments) return {};
    return this.changeComments.getPaths(this.patchRange);
  }

  // Private but used in tests.
  computeCommentSkips(
    commentMap?: CommentMap,
    fileList?: string[],
    path?: string
  ): CommentSkips | undefined {
    if (!commentMap) return undefined;
    if (!fileList) return undefined;
    if (!path) return undefined;

    const skips: CommentSkips = {previous: null, next: null};
    if (!fileList.length) {
      return skips;
    }
    const pathIndex = fileList.indexOf(path);

    // Scan backward for the previous file.
    for (let i = pathIndex - 1; i >= 0; i--) {
      if (commentMap[fileList[i]]) {
        skips.previous = fileList[i];
        break;
      }
    }

    // Scan forward for the next file.
    for (let i = pathIndex + 1; i < fileList.length; i++) {
      if (commentMap[fileList[i]]) {
        skips.next = fileList[i];
        break;
      }
    }

    return skips;
  }

  // Private but used in tests.
  computeEditMode() {
    return this.patchRange?.patchNum === EDIT;
  }

  // Private but used in tests.
  loadBlame() {
    this.isBlameLoading = true;
    fireAlert(this, LOADING_BLAME);
    assertIsDefined(this.diffHost, 'diffHost');
    this.diffHost
      .loadBlame()
      .then(() => {
        this.isBlameLoading = false;
        fireAlert(this, LOADED_BLAME);
      })
      .catch(() => {
        this.isBlameLoading = false;
      });
  }

  /**
   * Load and display blame information if it has not already been loaded.
   * Otherwise hide it.
   */
  private toggleBlame() {
    assertIsDefined(this.diffHost, 'diffHost');
    if (this.isBlameLoaded) {
      this.diffHost.clearBlame();
      return;
    }
    this.loadBlame();
  }

  private handleToggleHideAllCommentThreads() {
    toggleClass(this, 'hideComments');
  }

  private handleOpenFileList() {
    assertIsDefined(this.dropdown, 'dropdown');
    this.dropdown.open();
  }

  // Private but used in tests.
  handleDiffAgainstBase() {
    if (!this.change) return;
    if (!this.path) return;
    if (!this.patchRange) return;

    if (this.patchRange.basePatchNum === PARENT) {
      fireAlert(this, 'Base is already selected.');
      return;
    }
    GerritNav.navigateToDiff(this.change, this.path, this.patchRange.patchNum);
  }

  // Private but used in tests.
  handleDiffBaseAgainstLeft() {
    if (!this.change) return;
    if (!this.path) return;
    if (!this.patchRange) return;

    if (this.patchRange.basePatchNum === PARENT) {
      fireAlert(this, 'Left is already base.');
      return;
    }
    GerritNav.navigateToDiff(
      this.change,
      this.path,
      this.patchRange.basePatchNum as RevisionPatchSetNum,
      PARENT,
      this.params?.view === GerritView.DIFF && this.params?.commentLink
        ? this.focusLineNum
        : undefined
    );
  }

  // Private but used in tests.
  handleDiffAgainstLatest() {
    if (!this.change) return;
    if (!this.path) return;
    if (!this.patchRange) return;

    const latestPatchNum = computeLatestPatchNum(this.allPatchSets);
    if (this.patchRange.patchNum === latestPatchNum) {
      fireAlert(this, 'Latest is already selected.');
      return;
    }

    GerritNav.navigateToDiff(
      this.change,
      this.path,
      latestPatchNum,
      this.patchRange.basePatchNum
    );
  }

  // Private but used in tests.
  handleDiffRightAgainstLatest() {
    if (!this.change) return;
    if (!this.path) return;
    if (!this.patchRange) return;

    const latestPatchNum = computeLatestPatchNum(this.allPatchSets);
    if (this.patchRange.patchNum === latestPatchNum) {
      fireAlert(this, 'Right is already latest.');
      return;
    }
    GerritNav.navigateToDiff(
      this.change,
      this.path,
      latestPatchNum,
      this.patchRange.patchNum as BasePatchSetNum
    );
  }

  // Private but used in tests.
  handleDiffBaseAgainstLatest() {
    if (!this.change) return;
    if (!this.path) return;
    if (!this.patchRange) return;

    const latestPatchNum = computeLatestPatchNum(this.allPatchSets);
    if (
      this.patchRange.patchNum === latestPatchNum &&
      this.patchRange.basePatchNum === PARENT
    ) {
      fireAlert(this, 'Already diffing base against latest.');
      return;
    }
    GerritNav.navigateToDiff(this.change, this.path, latestPatchNum);
  }

  // Private but used in tests.
  computeFileNum(files: DropdownItem[]) {
    if (!this.path || !files) return undefined;

    return files.findIndex(({value}) => value === this.path) + 1;
  }

  // Private but used in tests.
  computeFileNumClass(fileNum?: number, files?: DropdownItem[]) {
    if (files && fileNum && fileNum > 0) {
      return 'show';
    }
    return '';
  }

  private handleToggleAllDiffContext() {
    assertIsDefined(this.diffHost, 'diffHost');
    this.diffHost.toggleAllContext();
  }

  private handleNextUnreviewedFile() {
    this.setReviewed(true);
    this.navigateToUnreviewedFile('next');
  }

  private navigateToNextFileWithCommentThread() {
    if (!this.path) return;
    if (!this.files?.sortedFileList) return;
    if (!this.patchRange) return;
    if (!this.change) return;
    const hasComment = (path: string) =>
      this.changeComments?.getCommentsForPath(path, this.patchRange!)?.length ??
      0 > 0;
    const filesWithComments = this.files.sortedFileList.filter(
      file => file === this.path || hasComment(file)
    );
    this.navToFile(filesWithComments, 1, true);
  }

  private handleReloadingDiffPreference() {
    this.userModel.getDiffPreferences();
  }

  private computeCanEdit() {
    return (
      !!this.change &&
      !!this.loggedIn &&
      changeIsOpen(this.change) &&
      !this.computeShowEditLinks()
    );
  }

  private computeShowEditLinks() {
    return !!this.editWeblinks && this.editWeblinks.length > 0;
  }

  createTitle(shortcutName: Shortcut, section: ShortcutSection) {
    return this.getShortcutsService().createTitle(shortcutName, section);
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'gr-diff-view': GrDiffView;
  }
}
