/**
 * @license
 * Copyright 2016 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
/* NB: Order is important, because of namespaced classes. */

import {GrEtagDecorator} from '../../elements/shared/gr-rest-api-interface/gr-etag-decorator';
import {GrReviewerUpdatesParser} from '../../elements/shared/gr-rest-api-interface/gr-reviewer-updates-parser';
import {parseDate} from '../../utils/date-util';
import {getParentIndex, isMergeParent} from '../../utils/patch-set-util';
import {listChangesOptionsToHex} from '../../utils/change-util';
import {assertNever, hasOwnProperty} from '../../utils/common-util';
import {AuthService} from '../gr-auth/gr-auth';
import {
  AccountCapabilityInfo,
  AccountDetailInfo,
  AccountExternalIdInfo,
  AccountId,
  AccountInfo,
  AccountStateInfo,
  ActionNameToActionInfoMap,
  AuthTokenInfo,
  Base64File,
  Base64FileContent,
  Base64ImageFile,
  BasePatchSetNum,
  BlameInfo,
  BranchInfo,
  BranchInput,
  BranchName,
  CapabilityInfoMap,
  ChangeId,
  ChangeInfo,
  ChangeMessageId,
  ChangeViewChangeInfo,
  CommentInfo,
  CommentInput,
  CommitId,
  CommitInfo,
  ConfigInfo,
  ConfigInput,
  ContributorAgreementInfo,
  ContributorAgreementInput,
  DashboardId,
  DashboardInfo,
  DeleteDraftCommentsInput,
  DiffPreferenceInput,
  DocResult,
  DraftInfo,
  EDIT,
  EditInfo,
  EditPreferencesInfo,
  EmailAddress,
  EmailInfo,
  FileNameToFileInfoMap,
  FilePathToDiffInfoMap,
  GitRef,
  GpgKeyId,
  GpgKeyInfo,
  GpgKeysInput,
  GroupAuditEventInfo,
  GroupId,
  GroupInfo,
  GroupInput,
  GroupName,
  GroupNameToGroupInfoMap,
  GroupOptionsInput,
  Hashtag,
  HashtagsInput,
  ImagesForDiff,
  IncludedInInfo,
  ListChangesOption,
  MergeableInfo,
  NameToProjectInfoMap,
  NumericChangeId,
  PARENT,
  ParsedJSON,
  PatchRange,
  PatchSetNum,
  PluginInfo,
  PreferencesInfo,
  PreferencesInput,
  ProjectAccessInfo,
  ProjectAccessInput,
  ProjectInfo,
  ProjectInfoWithName,
  ProjectInput,
  ProjectWatchInfo,
  RelatedChangesInfo,
  RepoAccessInfoMap,
  RepoName,
  RequestPayload,
  ReviewInput,
  ReviewResult,
  RevisionId,
  ServerInfo,
  SshKeyInfo,
  SubmitRequirementInfo,
  SubmittedTogetherInfo,
  SuggestedReviewerInfo,
  TagInfo,
  TagInput,
  TopMenuEntryInfo,
  UrlEncodedCommentId,
  ValidationOptionsInfo,
} from '../../types/common';
import {
  DiffInfo,
  DiffPreferencesInfo,
  IgnoreWhitespaceType,
} from '../../types/diff';
import {
  GetDiffCommentsOutput,
  RestApiService,
  SubmittabilityInfo,
} from './gr-rest-api';
import {
  CommentSide,
  createDefaultDiffPrefs,
  createDefaultEditPrefs,
  createDefaultPreferences,
  HttpMethod,
  ReviewerState,
} from '../../constants/constants';
import {firePageError, fireServerError} from '../../utils/event-util';
import {Finalizable, ParsedChangeInfo} from '../../types/types';
import {ErrorCallback} from '../../api/rest';
import {addDraftProp} from '../../utils/comment-util';
import {BaseScheduler, Scheduler} from '../scheduler/scheduler';
import {MaxInFlightScheduler} from '../scheduler/max-in-flight-scheduler';
import {escapeAndWrapSearchOperatorValue} from '../../utils/string-util';
import {RetryScheduler} from '../scheduler/retry-scheduler';
import {
  BatchLabelInput,
  BatchSubmitRequirementInput,
  DeleteLabelInput,
  FileInfo,
  FixReplacementInfo,
  FlowActionInfo,
  FlowInfo,
  FlowInput,
  LabelDefinitionInfo,
  LabelDefinitionInput,
  SubmitRequirementInput,
} from '../../api/rest-api';
import {IsFlowsEnabledInfo} from '../../api/rest-api';
import {
  FetchParams,
  FetchPromisesCache,
  FetchRequest,
  getFetchOptions,
  GrRestApiHelper,
  parsePrefixedJSON,
  readJSONResponsePayload,
  SiteBasedCache,
  throwingErrorCallback,
} from '../../elements/shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper';

const MAX_PROJECT_RESULTS = 25;

const Requests = {
  SEND_DIFF_DRAFT: 'sendDiffDraft',
};

const CREATE_DRAFT_UNEXPECTED_STATUS_MESSAGE =
  'Saving draft resulted in HTTP 200 (OK) but expected HTTP 201 (Created)';
const HEADER_REPORTING_BLOCK_REGEX = /^set-cookie$/i;

const ANONYMIZED_CHANGE_BASE_URL = '/changes/*~*';
const ANONYMIZED_REVISION_BASE_URL =
  ANONYMIZED_CHANGE_BASE_URL + '/revisions/*';

let siteBasedCache = new SiteBasedCache(); // Shared across instances.
// Shared across instances. Note: fetchPromisesCache only matches on URL and params,
// not request bodies, hence it does not safely support POST requests with payloads.
let fetchPromisesCache = new FetchPromisesCache();
let pendingRequest: {[promiseName: string]: Array<Promise<unknown>>} = {}; // Shared across instances.
let grEtagDecorator = new GrEtagDecorator(); // Shared across instances.
// TODO: consider changing this to Map()
let projectLookup: {[changeNum: string]: Promise<RepoName> | undefined} = {}; // Shared across instances.
// Shared across instances. Specifically allocated for fix previews because FetchPromisesCache
// doesn't reflect POST request bodies in its keys, and fix previews are currently the only POST requests
// that require deduplication across Lit components.
let fixPreviewCache = new Map<
  string,
  Promise<FilePathToDiffInfoMap | undefined>
>();

function suppress404s(res?: Response | null) {
  if (!res || res.status === 404) return;
  // This is the default error handling behavior of the rest-api-helper.
  fireServerError(res);
}

interface QueryChangesParams {
  [paramName: string]: string | undefined | number | string[];
  O?: string; // options
  S: number; // start
  n?: number; // changes per page
  q?: string | string[]; // query/queries
}

interface QueryAccountsParams {
  [paramName: string]: string | undefined | null | number;
  q: string;
  n?: number;
  o?: string;
}

interface QueryGroupsParams {
  [paramName: string]: string | undefined | null | number;
  s: string;
  n?: number;
  p?: string;
}

interface QuerySuggestedReviewersParams {
  [paramName: string]: string | undefined | null | number;
  n: number;
  q?: string;
  'reviewer-state': ReviewerState;
}

interface GetDiffParams {
  [paramName: string]: string | undefined | null | number | boolean;
  intraline?: boolean | null;
  whitespace?: IgnoreWhitespaceType;
  parent?: number;
  base?: PatchSetNum;
}

export function testOnlyResetGrRestApiSharedObjects(authService: AuthService) {
  siteBasedCache = new SiteBasedCache();
  fetchPromisesCache = new FetchPromisesCache();
  pendingRequest = {};
  grEtagDecorator = new GrEtagDecorator();
  projectLookup = {};
  fixPreviewCache = new Map();
  authService.clearCache();
}

function createReadScheduler() {
  return new RetryScheduler<Response>(
    new MaxInFlightScheduler<Response>(new BaseScheduler<Response>(), 10),
    3 /* maxRetry */,
    50 /* backoffIntervalMs */
  );
}

function createWriteScheduler() {
  return new RetryScheduler<Response>(
    new MaxInFlightScheduler<Response>(new BaseScheduler<Response>(), 5),
    3 /* maxRetry */,
    50 /* backoffIntervalMs */
  );
}

function createSerializingScheduler() {
  return new MaxInFlightScheduler<Response>(new BaseScheduler<Response>(), 1);
}

export class GrRestApiServiceImpl implements RestApiService, Finalizable {
  readonly _cache = siteBasedCache; // Shared across instances.

  readonly _sharedFetchPromises = fetchPromisesCache; // Shared across instances.

  readonly _pendingRequests = pendingRequest; // Shared across instances.

  readonly _etags = grEtagDecorator; // Shared across instances.

  // readonly, but set in tests.
  _projectLookup = projectLookup; // Shared across instances.

  // The value is set in created, before any other actions
  // Private, but used in tests.
  readonly _restApiHelper: GrRestApiHelper;

  // Used to serialize requests for certain RPCs
  readonly _serialScheduler: Scheduler<Response>;

  constructor(private readonly authService: AuthService) {
    const readScheduler = createReadScheduler();
    const writeScheduler = createWriteScheduler();
    this._restApiHelper = new GrRestApiHelper(
      this._cache,
      this.authService,
      this._sharedFetchPromises,
      readScheduler,
      writeScheduler
    );
    this._serialScheduler = createSerializingScheduler();
  }

  finalize() {}

  getConfig(
    noCache?: boolean,
    requestOrigin?: string
  ): Promise<ServerInfo | undefined> {
    if (!noCache) {
      return this._restApiHelper.fetchCacheJSON({
        fetchOptions: getFetchOptions({
          requestOrigin,
        }),
        url: '/config/server/info',
        reportUrlAsIs: true,
      }) as Promise<ServerInfo | undefined>;
    }

    return this._restApiHelper.fetchJSON({
      fetchOptions: getFetchOptions({
        requestOrigin,
      }),
      url: '/config/server/info',
      reportUrlAsIs: true,
    }) as Promise<ServerInfo | undefined>;
  }

  getValidationOptions(
    changeNum: NumericChangeId
  ): Promise<ValidationOptionsInfo | undefined> {
    return this._restApiHelper.fetchJSON({
      url: `/changes/${changeNum}/validation-options`,
      reportUrlAsIs: true,
    }) as Promise<ValidationOptionsInfo | undefined>;
  }

  getRepo(
    repo: RepoName,
    errFn?: ErrorCallback
  ): Promise<ProjectInfo | undefined> {
    return this._restApiHelper.fetchCacheJSON({
      url: '/projects/' + encodeURIComponent(repo),
      errFn,
      anonymizedUrl: '/projects/*',
    }) as Promise<ProjectInfo | undefined>;
  }

  getProjectConfig(
    repo: RepoName,
    errFn?: ErrorCallback
  ): Promise<ConfigInfo | undefined> {
    return this._restApiHelper.fetchCacheJSON({
      url: '/projects/' + encodeURIComponent(repo) + '/config',
      errFn,
      anonymizedUrl: '/projects/*/config',
    }) as Promise<ConfigInfo | undefined>;
  }

  getRepoAccess(repo: RepoName): Promise<RepoAccessInfoMap | undefined> {
    return this._restApiHelper.fetchCacheJSON({
      url: '/access/?project=' + encodeURIComponent(repo),
      anonymizedUrl: '/access/?project=*',
    }) as Promise<RepoAccessInfoMap | undefined>;
  }

  getRepoDashboards(
    repo: RepoName,
    errFn?: ErrorCallback
  ): Promise<DashboardInfo[] | undefined> {
    return this._restApiHelper.fetchCacheJSON({
      url: `/projects/${encodeURIComponent(repo)}/dashboards?inherited`,
      errFn,
      anonymizedUrl: '/projects/*/dashboards?inherited',
    }) as Promise<DashboardInfo[] | undefined>;
  }

  saveRepoConfig(repo: RepoName, config: ConfigInput): Promise<Response> {
    const url = `/projects/${encodeURIComponent(repo)}/config`;
    this._cache.delete(url);
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: config,
      }),
      url,
      anonymizedUrl: '/projects/*/config',
      reportServerError: true,
    });
  }

  saveRepoConfigForReview(
    repo: RepoName,
    config: ConfigInput
  ): Promise<ChangeInfo | undefined> {
    const url = `/projects/${encodeURIComponent(repo)}/config:review`;
    return this._restApiHelper.fetchJSON({
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: config,
      }),
      url,
      anonymizedUrl: '/projects/*/config',
      reportServerError: true,
    }) as unknown as Promise<ChangeInfo | undefined>;
  }

  runRepoGC(repo: RepoName): Promise<Response> {
    const encodeName = encodeURIComponent(repo);
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.POST,
        body: '',
      }),
      url: `/projects/${encodeName}/gc`,
      anonymizedUrl: '/projects/*/gc',
      reportServerError: true,
    });
  }

  createRepo(config: ProjectInput & {name: RepoName}): Promise<Response> {
    const encodeName = encodeURIComponent(config.name);
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: config,
      }),
      url: `/projects/${encodeName}`,
      anonymizedUrl: '/projects/*',
      reportServerError: true,
    });
  }

  createGroup(config: GroupInput): Promise<Response> {
    if (!config.name) {
      throw new Error('Group name is required');
    }
    const encodeName = encodeURIComponent(config.name);
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: config,
      }),
      url: `/groups/${encodeName}`,
      anonymizedUrl: '/groups/*',
      reportServerError: true,
    });
  }

  getGroupConfig(
    group: GroupId | GroupName,
    errFn?: ErrorCallback
  ): Promise<GroupInfo | undefined> {
    return this._restApiHelper.fetchJSON({
      url: `/groups/${encodeURIComponent(group)}/detail`,
      errFn,
      anonymizedUrl: '/groups/*/detail',
    }) as Promise<GroupInfo | undefined>;
  }

  deleteRepoBranches(repo: RepoName, ref: GitRef): Promise<Response> {
    const encodeName = encodeURIComponent(repo);
    const encodeRef = encodeURIComponent(ref);
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.DELETE,
        body: '',
      }),
      url: `/projects/${encodeName}/branches/${encodeRef}`,
      anonymizedUrl: '/projects/*/branches/*',
      reportServerError: true,
    });
  }

  deleteRepoTags(repo: RepoName, ref: GitRef): Promise<Response> {
    const encodeName = encodeURIComponent(repo);
    const encodeRef = encodeURIComponent(ref);
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.DELETE,
        body: '',
      }),
      url: `/projects/${encodeName}/tags/${encodeRef}`,
      anonymizedUrl: '/projects/*/tags/*',
      reportServerError: true,
    });
  }

  createRepoBranch(
    name: RepoName,
    branch: BranchName,
    revision: BranchInput
  ): Promise<Response> {
    const encodeName = encodeURIComponent(name);
    const encodeBranch = encodeURIComponent(branch);
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: revision,
      }),
      url: `/projects/${encodeName}/branches/${encodeBranch}`,
      anonymizedUrl: '/projects/*/branches/*',
      reportServerError: true,
    });
  }

  createRepoTag(
    name: RepoName,
    tag: string,
    revision: TagInput
  ): Promise<Response> {
    const encodeName = encodeURIComponent(name);
    const encodeTag = encodeURIComponent(tag);
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: revision,
      }),
      url: `/projects/${encodeName}/tags/${encodeTag}`,
      anonymizedUrl: '/projects/*/tags/*',
      reportServerError: true,
    });
  }

  getIsGroupOwner(groupName?: GroupName): Promise<boolean> {
    if (!groupName) return Promise.resolve(false);
    const encodeName = encodeURIComponent(groupName);
    const req = {
      url: `/groups/?owned&g=${encodeName}`,
      anonymizedUrl: '/groups/owned&g=*',
    };
    return this._restApiHelper
      .fetchCacheJSON(req)
      .then(configs => hasOwnProperty(configs, groupName));
  }

  getGroupMembers(groupName: GroupId | GroupName): Promise<AccountInfo[]> {
    const encodeName = encodeURIComponent(groupName);
    return this._restApiHelper.fetchJSON({
      url: `/groups/${encodeName}/members/`,
      anonymizedUrl: '/groups/*/members',
    }) as unknown as Promise<AccountInfo[]>;
  }

  getIncludedGroup(
    groupName: GroupId | GroupName
  ): Promise<GroupInfo[] | undefined> {
    return this._restApiHelper.fetchJSON({
      url: `/groups/${encodeURIComponent(groupName)}/groups/`,
      anonymizedUrl: '/groups/*/groups',
    }) as Promise<GroupInfo[] | undefined>;
  }

  saveGroupName(groupId: GroupId | GroupName, name: string): Promise<Response> {
    const encodeId = encodeURIComponent(groupId);
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: {name},
      }),
      url: `/groups/${encodeId}/name`,
      anonymizedUrl: '/groups/*/name',
      reportServerError: true,
    });
  }

  saveGroupOwner(
    groupId: GroupId | GroupName,
    ownerId: string
  ): Promise<Response> {
    const encodeId = encodeURIComponent(groupId);
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: {owner: ownerId},
      }),
      url: `/groups/${encodeId}/owner`,
      anonymizedUrl: '/groups/*/owner',
      reportServerError: true,
    });
  }

  saveGroupDescription(
    groupId: GroupId | GroupName,
    description: string
  ): Promise<Response> {
    const encodeId = encodeURIComponent(groupId);
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: {description},
      }),
      url: `/groups/${encodeId}/description`,
      anonymizedUrl: '/groups/*/description',
      reportServerError: true,
    });
  }

  saveGroupOptions(
    groupId: GroupId | GroupName,
    options: GroupOptionsInput
  ): Promise<Response> {
    const encodeId = encodeURIComponent(groupId);
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: options,
      }),
      url: `/groups/${encodeId}/options`,
      anonymizedUrl: '/groups/*/options',
      reportServerError: true,
    });
  }

  deleteGroup(groupName: GroupName): Promise<Response> {
    const encodeName = encodeURIComponent(groupName);
    return this._restApiHelper.fetch({
      fetchOptions: {
        method: HttpMethod.DELETE,
      },
      url: `/groups/${encodeName}`,
      anonymizedUrl: '/groups/*',
    });
  }

  getGroupAuditLog(
    group: GroupId,
    errFn?: ErrorCallback
  ): Promise<GroupAuditEventInfo[] | undefined> {
    return this._restApiHelper.fetchCacheJSON({
      url: `/groups/${group}/log.audit`,
      errFn,
      anonymizedUrl: '/groups/*/log.audit',
    }) as Promise<GroupAuditEventInfo[] | undefined>;
  }

  saveGroupMember(
    groupName: GroupId | GroupName,
    groupMember: AccountId
  ): Promise<AccountInfo | undefined> {
    const encodeName = encodeURIComponent(groupName);
    const encodeMember = encodeURIComponent(`${groupMember}`);
    return this._restApiHelper.fetchJSON({
      fetchOptions: {
        method: HttpMethod.PUT,
      },
      url: `/groups/${encodeName}/members/${encodeMember}`,
      anonymizedUrl: '/groups/*/members/*',
    }) as unknown as Promise<AccountInfo | undefined>;
  }

  saveIncludedGroup(
    groupName: GroupId | GroupName,
    includedGroup: GroupId,
    errFn?: ErrorCallback
  ): Promise<GroupInfo | undefined> {
    const encodeName = encodeURIComponent(groupName);
    const encodeIncludedGroup = encodeURIComponent(includedGroup);
    const req = {
      fetchOptions: {
        method: HttpMethod.PUT,
      },
      url: `/groups/${encodeName}/groups/${encodeIncludedGroup}`,
      errFn,
      anonymizedUrl: '/groups/*/groups/*',
    };
    return this._restApiHelper.fetchJSON(req) as unknown as Promise<
      GroupInfo | undefined
    >;
  }

  deleteGroupMember(
    groupName: GroupId | GroupName,
    groupMember: AccountId
  ): Promise<Response> {
    const encodeName = encodeURIComponent(groupName);
    const encodeMember = encodeURIComponent(`${groupMember}`);
    return this._restApiHelper.fetch({
      fetchOptions: {
        method: HttpMethod.DELETE,
      },
      url: `/groups/${encodeName}/members/${encodeMember}`,
      anonymizedUrl: '/groups/*/members/*',
      reportServerError: true,
    });
  }

  deleteIncludedGroup(
    groupName: GroupId,
    includedGroup: GroupId | GroupName
  ): Promise<Response> {
    const encodeName = encodeURIComponent(groupName);
    const encodeIncludedGroup = encodeURIComponent(includedGroup);
    return this._restApiHelper.fetch({
      fetchOptions: {
        method: HttpMethod.DELETE,
      },
      url: `/groups/${encodeName}/groups/${encodeIncludedGroup}`,
      anonymizedUrl: '/groups/*/groups/*',
      reportServerError: true,
    });
  }

  getVersion(requestOrigin?: string): Promise<string | undefined> {
    return this._restApiHelper.fetchCacheJSON({
      fetchOptions: getFetchOptions({
        requestOrigin,
      }),
      url: '/config/server/version',
      reportUrlAsIs: true,
    }) as Promise<string | undefined>;
  }

  getDiffPreferences(): Promise<DiffPreferencesInfo | undefined> {
    return this.getLoggedIn().then(loggedIn => {
      if (loggedIn) {
        return this._restApiHelper.fetchCacheJSON({
          url: '/accounts/self/preferences.diff',
          reportUrlAsIs: true,
        }) as Promise<DiffPreferencesInfo | undefined>;
      }
      return Promise.resolve(createDefaultDiffPrefs());
    });
  }

  getEditPreferences(): Promise<EditPreferencesInfo | undefined> {
    return this.getLoggedIn().then(loggedIn => {
      if (loggedIn) {
        return this._restApiHelper.fetchCacheJSON({
          url: '/accounts/self/preferences.edit',
          reportUrlAsIs: true,
        }) as Promise<EditPreferencesInfo | undefined>;
      }
      return Promise.resolve(createDefaultEditPrefs());
    });
  }

  savePreferences(
    prefs: PreferencesInput
  ): Promise<PreferencesInfo | undefined> {
    // Invalidate the cache.
    this._cache.delete('/accounts/self/preferences');

    // Note (Issue 5142): normalize the download scheme with lower case before
    // saving.
    if (prefs.download_scheme) {
      prefs.download_scheme = prefs.download_scheme.toLowerCase();
    }

    return this._restApiHelper.fetchJSON({
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: prefs,
      }),
      url: '/accounts/self/preferences',
      reportUrlAsIs: true,
    }) as unknown as Promise<PreferencesInfo | undefined>;
  }

  saveDiffPreferences(prefs: DiffPreferenceInput): Promise<Response> {
    // Invalidate the cache.
    this._cache.delete('/accounts/self/preferences.diff');
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: prefs,
      }),
      url: '/accounts/self/preferences.diff',
      reportUrlAsIs: true,
      reportServerError: true,
    });
  }

  saveEditPreferences(prefs: EditPreferencesInfo): Promise<Response> {
    // Invalidate the cache.
    this._cache.delete('/accounts/self/preferences.edit');
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: prefs,
      }),
      url: '/accounts/self/preferences.edit',
      reportUrlAsIs: true,
      reportServerError: true,
    });
  }

  getAccount(requestOrigin?: string): Promise<AccountDetailInfo | undefined> {
    return this._restApiHelper.fetchCacheJSON({
      fetchOptions: getFetchOptions({
        requestOrigin,
      }),
      url: '/accounts/self/detail',
      reportUrlAsIs: true,
      errFn: resp => {
        if (!resp || resp.status === 403) {
          this._cache.delete('/accounts/self/detail');
        }
      },
    }) as Promise<AccountDetailInfo | undefined>;
  }

  getAvatarChangeUrl() {
    return this._restApiHelper.fetchCacheJSON({
      url: '/accounts/self/avatar.change.url',
      reportUrlAsIs: true,
      errFn: resp => {
        if (!resp || resp.status === 403) {
          this._cache.delete('/accounts/self/avatar.change.url');
        }
      },
    }) as Promise<string | undefined>;
  }

  getExternalIds() {
    return this._restApiHelper.fetchJSON({
      url: '/accounts/self/external.ids',
      reportUrlAsIs: true,
    }) as Promise<AccountExternalIdInfo[] | undefined>;
  }

  deleteAccount(): Promise<Response> {
    return this._restApiHelper.fetch({
      fetchOptions: {
        method: HttpMethod.DELETE,
      },
      url: '/accounts/self',
      reportUrlAsIs: true,
      reportServerError: true,
    });
  }

  deleteAccountIdentity(id: string[]): Promise<Response> {
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.POST,
        body: id,
      }),
      url: '/accounts/self/external.ids:delete',
      reportUrlAsIs: true,
      reportServerError: true,
    });
  }

  getAccountDetails(
    userId: AccountId | EmailAddress,
    errFn?: ErrorCallback
  ): Promise<AccountDetailInfo | undefined> {
    return this._restApiHelper.fetchCacheJSON({
      url: `/accounts/${encodeURIComponent(userId)}/detail`,
      anonymizedUrl: '/accounts/*/detail',
      errFn,
    }) as Promise<AccountDetailInfo | undefined>;
  }

  async getAccountEmails() {
    const isloggedIn = await this.getLoggedIn();
    if (isloggedIn) {
      return this._restApiHelper.fetchCacheJSON({
        url: '/accounts/self/emails',
        reportUrlAsIs: true,
      }) as Promise<EmailInfo[] | undefined>;
    } else return;
  }

  getAccountEmailsFor(email: string, errFn?: ErrorCallback) {
    return this.getLoggedIn()
      .then(isLoggedIn => {
        if (isLoggedIn) {
          return this.getAccountCapabilities();
        } else {
          return undefined;
        }
      })
      .then((capabilities: AccountCapabilityInfo | undefined) => {
        if (capabilities && capabilities.viewSecondaryEmails) {
          return this._restApiHelper.fetchCacheJSON({
            url: '/accounts/' + email + '/emails',
            reportUrlAsIs: true,
            errFn,
          }) as Promise<EmailInfo[] | undefined>;
        }
        return undefined;
      });
  }

  addAccountEmail(email: string): Promise<Response> {
    return this._restApiHelper.fetch({
      fetchOptions: {
        method: HttpMethod.PUT,
      },
      url: '/accounts/self/emails/' + encodeURIComponent(email),
      anonymizedUrl: '/account/self/emails/*',
      reportServerError: true,
    });
  }

  deleteAccountEmail(email: string): Promise<Response> {
    return this._restApiHelper.fetch({
      fetchOptions: {
        method: HttpMethod.DELETE,
      },
      url: '/accounts/self/emails/' + encodeURIComponent(email),
      anonymizedUrl: '/accounts/self/email/*',
      reportServerError: true,
    });
  }

  async setPreferredAccountEmail(email: string): Promise<void> {
    await this._restApiHelper.fetch({
      fetchOptions: {
        method: HttpMethod.PUT,
      },
      url: `/accounts/self/emails/${encodeURIComponent(email)}/preferred`,
      anonymizedUrl: '/accounts/self/emails/*/preferred',
      reportServerError: true,
    });
    // If result of getAccountEmails is in cache, update it in the cache
    // so we don't have to invalidate it.
    const cachedEmails = this._cache.get(
      '/accounts/self/emails'
    ) as unknown as EmailInfo[];
    if (cachedEmails) {
      const emails = cachedEmails.map(entry => {
        if (entry.email === email) {
          return {email: entry.email, preferred: true};
        } else {
          return {email: entry.email, preferred: false};
        }
      });
      this._cache.set('/accounts/self/emails', emails as unknown as ParsedJSON);
    }
  }

  async setAvatarAccountEmail(email: string): Promise<void> {
    await this._restApiHelper.fetch({
      fetchOptions: {
        method: HttpMethod.PUT,
      },
      url: `/accounts/self/emails/${encodeURIComponent(email)}/avatar`,
      anonymizedUrl: '/accounts/self/emails/*/avatar',
      reportServerError: true,
    });
    // If result of getAccountEmails is in cache, update it in the cache
    // so we don't have to invalidate it.
    const cachedEmails = this._cache.get(
      '/accounts/self/emails'
    ) as unknown as EmailInfo[];
    if (cachedEmails) {
      const emails = cachedEmails.map(entry => {
        if (entry.email === email) {
          return {...entry, avatar: true};
        } else {
          return {...entry, avatar: false};
        }
      });
      this._cache.set('/accounts/self/emails', emails as unknown as ParsedJSON);
    }
  }

  _updateCachedAccount(obj: Partial<AccountDetailInfo>): void {
    // If result of getAccount is in cache, update it in the cache
    // so we don't have to invalidate it.
    const cachedAccount = this._cache.get('/accounts/self/detail');
    if (cachedAccount) {
      // Replace object in cache with new object to force UI updates.
      this._cache.set('/accounts/self/detail', {
        ...cachedAccount,
        ...obj,
      });
    }
  }

  async setAccountName(name: string): Promise<void> {
    const response = await this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: {name},
      }),
      url: '/accounts/self/name',
      reportUrlAsIs: true,
      reportServerError: true,
    });
    if (!response.ok) {
      return;
    }
    let newName = undefined;
    // If the name was deleted server returns 204
    if (response.status !== 204) {
      newName = (await readJSONResponsePayload(response))
        .parsed as unknown as string;
    }
    this._updateCachedAccount({name: newName});
  }

  async setAccountUsername(username: string): Promise<void> {
    const response = await this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: {username},
      }),
      url: '/accounts/self/username',
      reportUrlAsIs: true,
    });
    if (!response.ok) {
      return;
    }
    let newName = undefined;
    // If the name was deleted server returns 204
    if (response.status !== 204) {
      newName = (await readJSONResponsePayload(response))
        .parsed as unknown as string;
    }
    this._updateCachedAccount({username: newName});
  }

  async setAccountDisplayName(displayName: string): Promise<void> {
    const response = await this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: {display_name: displayName},
      }),
      url: '/accounts/self/displayname',
      reportUrlAsIs: true,
      reportServerError: true,
    });
    if (!response.ok) {
      return;
    }
    let newName = undefined;
    // If the name was deleted server returns 204
    if (response.status !== 204) {
      newName = (await readJSONResponsePayload(response))
        .parsed as unknown as string;
    }
    this._updateCachedAccount({display_name: newName});
  }

  async setAccountStatus(status: string): Promise<void> {
    const response = await this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: {status},
      }),
      url: '/accounts/self/status',
      reportUrlAsIs: true,
    });
    if (!response.ok) {
      return;
    }
    let newStatus = undefined;
    // If the status was deleted server returns 204
    if (response.status !== 204) {
      newStatus = (await readJSONResponsePayload(response))
        .parsed as unknown as string;
    }
    this._updateCachedAccount({status: newStatus});
  }

  getAccountStatus(userId: AccountId) {
    return this._restApiHelper.fetchJSON({
      url: `/accounts/${encodeURIComponent(userId)}/status`,
      anonymizedUrl: '/accounts/*/status',
    }) as Promise<string | undefined>;
  }

  getAccountGroups() {
    return this._restApiHelper.fetchJSON({
      url: '/accounts/self/groups',
      reportUrlAsIs: true,
    }) as Promise<GroupInfo[] | undefined>;
  }

  getAccountAgreements() {
    return this._restApiHelper.fetchJSON({
      url: '/accounts/self/agreements',
      reportUrlAsIs: true,
    }) as Promise<ContributorAgreementInfo[] | undefined>;
  }

  saveAccountAgreement(name: ContributorAgreementInput): Promise<Response> {
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: name,
      }),
      url: '/accounts/self/agreements',
      reportUrlAsIs: true,
      reportServerError: true,
    });
  }

  getAccountCapabilities(
    params?: string[]
  ): Promise<AccountCapabilityInfo | undefined> {
    let queryString = '';
    if (params) {
      queryString =
        '?q=' + params.map(param => encodeURIComponent(param)).join('&q=');
    }
    return this._restApiHelper.fetchCacheJSON({
      url: '/accounts/self/capabilities' + queryString,
      anonymizedUrl: '/accounts/self/capabilities?q=*',
    }) as Promise<AccountCapabilityInfo | undefined>;
  }

  getLoggedIn() {
    return this.authService.authCheck();
  }

  getIsAdmin() {
    return this.getLoggedIn()
      .then(isLoggedIn => {
        if (isLoggedIn) {
          return this.getAccountCapabilities();
        } else {
          return;
        }
      })
      .then(
        (capabilities: AccountCapabilityInfo | undefined) =>
          capabilities && capabilities.administrateServer
      );
  }

  getDefaultPreferences(): Promise<PreferencesInfo | undefined> {
    return this._restApiHelper.fetchCacheJSON({
      url: '/config/server/preferences',
      reportUrlAsIs: true,
    }) as Promise<PreferencesInfo | undefined>;
  }

  getPreferences(): Promise<PreferencesInfo | undefined> {
    return this.getLoggedIn().then(loggedIn => {
      if (loggedIn) {
        const req = {url: '/accounts/self/preferences', reportUrlAsIs: true};
        return this._restApiHelper.fetchCacheJSON(req).then(res => {
          if (!res) {
            return res;
          }
          const prefInfo = res as unknown as PreferencesInfo;
          return prefInfo;
        });
      }
      return createDefaultPreferences();
    });
  }

  getAccountState(): Promise<AccountStateInfo | undefined> {
    return this._restApiHelper.fetchJSON({
      url: '/accounts/self/state',
      reportUrlAsIs: true,
    }) as Promise<AccountStateInfo | undefined>;
  }

  getWatchedProjects() {
    return this._restApiHelper.fetchCacheJSON({
      url: '/accounts/self/watched.projects',
      reportUrlAsIs: true,
    }) as unknown as Promise<ProjectWatchInfo[] | undefined>;
  }

  saveWatchedProjects(
    projects: ProjectWatchInfo[]
  ): Promise<ProjectWatchInfo[] | undefined> {
    return this._restApiHelper.fetchJSON({
      fetchOptions: getFetchOptions({
        method: HttpMethod.POST,
        body: projects,
      }),
      url: '/accounts/self/watched.projects',
      reportUrlAsIs: true,
    }) as unknown as Promise<ProjectWatchInfo[] | undefined>;
  }

  deleteWatchedProjects(projects: ProjectWatchInfo[]): Promise<Response> {
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.POST,
        body: projects,
      }),
      url: '/accounts/self/watched.projects:delete',
      reportUrlAsIs: true,
      reportServerError: true,
    });
  }

  /**
   * Construct the uri to get list of changes.
   *
   * If options is undefined then default options (see getListChangesOptionsHex) is
   * used.
   */
  getRequestForGetChanges(
    changesPerPage?: number,
    query?: string[] | string,
    offset?: 'n,z' | number,
    options?: string
  ) {
    options = options || this.getListChangesOptionsHex();
    if (offset === 'n,z') {
      offset = 0;
    }
    const params: QueryChangesParams = {
      O: options,
      S: offset || 0,
    };
    if (changesPerPage) {
      params.n = changesPerPage;
    }
    if (query && query.length > 0) {
      params.q = query;
    }
    const request = {
      url: '/changes/',
      params: {...params, 'allow-incomplete-results': true},
      reportUrlAsIs: true,
    };
    return request;
  }

  /**
   * Runs multiple parallel requests and call `getChanges()` for each query.
   */
  async getChangesForDashboard(
    changesPerPage?: number,
    queries?: string[],
    offset?: 'n,z' | number,
    options?: string
  ): Promise<ChangeInfo[][] | undefined> {
    if (!queries) {
      return undefined;
    }
    const requestPromises = queries.map(query =>
      this.getChanges(changesPerPage, query, offset, options)
    );
    return Promise.all(requestPromises).then(results => {
      if (results.includes(undefined)) return undefined;
      return results as ChangeInfo[][];
    });
  }

  /**
   * Fetches changes that match the query.
   *
   * If options is undefined then default options (see getListChangesOptionsHex) is
   * used.
   */
  getChanges(
    changesPerPage?: number,
    query?: string,
    offset?: 'n,z' | number,
    options?: string,
    errFn?: ErrorCallback
  ): Promise<ChangeInfo[] | undefined> {
    const request = this.getRequestForGetChanges(
      changesPerPage,
      query,
      offset,
      options
    );

    return Promise.resolve(
      this._restApiHelper.fetchJSON(
        {
          ...request,
          errFn,
        },
        true
      ) as Promise<ChangeInfo[] | undefined>
    ).then(response => {
      if (!response) {
        return;
      }
      const iterateOverChanges = (arr: ChangeInfo[]) => {
        for (const change of arr) {
          this._maybeInsertInLookup(change);
        }
      };
      iterateOverChanges(response);
      return response;
    });
  }

  async getDetailedChangesWithActions(
    changeNums: NumericChangeId[],
    needsSubmitRequirements = false
  ) {
    const options = [
      ListChangesOption.CHANGE_ACTIONS,
      ListChangesOption.CURRENT_REVISION,
      ListChangesOption.DETAILED_LABELS,
    ].concat(
      needsSubmitRequirements ? [ListChangesOption.SUBMIT_REQUIREMENTS] : []
    );
    const query = changeNums.map(num => `change:${num}`).join(' OR ');
    const changeDetails = await this.getChanges(
      undefined,
      query,
      undefined,
      listChangesOptionsToHex(...options)
    );
    return changeDetails;
  }

  /**
   * Inserts a change into _projectLookup iff it has a valid structure.
   */
  _maybeInsertInLookup(change: ChangeInfo): void {
    if (change?.project && change._number) {
      this.addRepoNameToCache(change._number, change.project);
    }
  }

  getChangeActionURL(
    changeNum: NumericChangeId,
    revisionId: RevisionId | undefined,
    endpoint: string
  ): Promise<string> {
    return this._changeBaseURL(changeNum, revisionId).then(
      url => url + endpoint
    );
  }

  async getChangeDetail(
    changeNum?: NumericChangeId,
    errFn?: ErrorCallback
  ): Promise<ParsedChangeInfo | undefined> {
    if (!changeNum) return;
    const optionsHex = await this.getChangeOptionsHex();

    return this._getChangeDetail(changeNum, optionsHex, errFn).then(detail =>
      // detail has ChangeViewChangeInfo type because the optionsHex always
      // includes ALL_REVISIONS flag.
      GrReviewerUpdatesParser.parse(detail as ChangeViewChangeInfo | undefined)
    );
  }

  async getAllRevisionFiles(
    changeNum?: NumericChangeId
  ): Promise<
    {[revisionId: string]: {[filename: string]: FileInfo}} | undefined
  > {
    if (!changeNum) return;
    const optionsHex = listChangesOptionsToHex(
      ListChangesOption.ALL_REVISIONS,
      ListChangesOption.ALL_FILES,
      ListChangesOption.SKIP_DIFFSTAT
    );

    const change = await this.getChange(changeNum, undefined, optionsHex);
    if (!change?.revisions) {
      return undefined;
    }
    const result: {[revisionId: string]: {[filename: string]: FileInfo}} = {};
    for (const revId in change.revisions) {
      if (!change.revisions[revId]?.files) {
        continue;
      }
      result[revId] = change.revisions[revId].files!;
    }
    return result;
  }

  private getListChangesOptionsHex() {
    if (
      window.DEFAULT_DETAIL_HEXES &&
      window.DEFAULT_DETAIL_HEXES.dashboardPage
    ) {
      return window.DEFAULT_DETAIL_HEXES.dashboardPage;
    }
    const options = [
      ListChangesOption.LABELS,
      ListChangesOption.DETAILED_ACCOUNTS,
      ListChangesOption.SUBMIT_REQUIREMENTS,
      ListChangesOption.STAR,
    ];

    return listChangesOptionsToHex(...options);
  }

  async getChangeOptionsHex(): Promise<string> {
    if (window.DEFAULT_DETAIL_HEXES && window.DEFAULT_DETAIL_HEXES.changePage) {
      return window.DEFAULT_DETAIL_HEXES.changePage;
    }
    // Kept as a fallback in case DEFAULT_DETAIL_HEXES is not set in index file
    // (e.g PolyGerritIndexHtml.soy)
    // We expect that DEFAULT_DETAIL_HEXES is always set and we are
    // using same hex as preloaded queries
    return listChangesOptionsToHex(...(await this.getChangeOptions()));
  }

  async getChangeOptions(): Promise<number[]> {
    const config = await this.getConfig(false);

    // This list MUST be kept in sync with
    // ChangeIT#changeDetailsDoesNotRequireIndex and IndexPreloadingUtil#CHANGE_DETAIL_OPTIONS
    const options = [
      ListChangesOption.ALL_COMMITS,
      ListChangesOption.ALL_REVISIONS,
      ListChangesOption.CHANGE_ACTIONS,
      ListChangesOption.DETAILED_ACCOUNTS,
      ListChangesOption.DETAILED_LABELS,
      ListChangesOption.DOWNLOAD_COMMANDS,
      ListChangesOption.MESSAGES,
      ListChangesOption.REVIEWER_UPDATES,
      ListChangesOption.WEB_LINKS,
      ListChangesOption.SKIP_DIFFSTAT,
      ListChangesOption.PARENTS,
    ];
    if (config?.receive?.enable_signed_push) {
      options.push(ListChangesOption.PUSH_CERTIFICATES);
    }
    return options;
  }

  /**
   * @param optionsHex list changes options in hex
   */
  _getChangeDetail(
    changeNum: NumericChangeId,
    optionsHex: string,
    errFn?: ErrorCallback
  ): Promise<ChangeInfo | undefined> {
    return this.getChangeActionURL(changeNum, undefined, '/detail').then(
      url => {
        const params: FetchParams = {O: optionsHex};
        const urlWithParams = this._restApiHelper.urlWithParams(url, params);
        const req: FetchRequest = {
          url,
          errFn,
          params,
          fetchOptions: this._etags.getOptions(urlWithParams),
          anonymizedUrl: '/changes/*~*/detail?O=' + optionsHex,
        };
        return this._restApiHelper.fetch(req).then(response => {
          if (response?.status === 304) {
            return parsePrefixedJSON(
              // urlWithParams already cached
              this._etags.getCachedPayload(urlWithParams)!
            ) as unknown as ChangeInfo;
          }

          if (response && !response.ok) {
            if (errFn) {
              errFn.call(null, response);
            } else {
              fireServerError(response, req);
            }
            return undefined;
          }

          if (!response) {
            return Promise.resolve(undefined);
          }

          return readJSONResponsePayload(response)
            .then(payload => {
              this._etags.collect(urlWithParams, response, payload.raw);
              this._maybeInsertInLookup(
                payload.parsed as unknown as ChangeInfo
              );

              return payload.parsed as unknown as ChangeInfo;
            })
            .catch(() => undefined);
        });
      }
    );
  }

  async getSubmittabilityInfo(
    changeNum: NumericChangeId
  ): Promise<SubmittabilityInfo | undefined> {
    const optionsHex = listChangesOptionsToHex(
      ListChangesOption.SUBMITTABLE,
      ListChangesOption.SUBMIT_REQUIREMENTS,
      ListChangesOption.SKIP_DIFFSTAT
    );
    const change = await this.getChange(
      changeNum,
      /* errFn=*/ undefined,
      optionsHex
    );
    if (!change || change.submit_requirements === undefined) {
      return undefined;
    }
    return {
      changeNum,
      submittable: !!change.submittable,
      submitRequirements: change.submit_requirements,
    };
  }

  async getChangeCommitInfo(
    changeNum: NumericChangeId,
    patchNum: PatchSetNum
  ): Promise<CommitInfo | undefined> {
    const url = await this._changeBaseURL(changeNum, patchNum);
    return this._restApiHelper.fetchJSON({
      url: `${url}/commit?links`,
      anonymizedUrl: `${ANONYMIZED_REVISION_BASE_URL}/commit?links`,
      errFn: suppress404s,
    }) as Promise<CommitInfo | undefined>;
  }

  async getChangeFiles(
    changeNum: NumericChangeId,
    patchRange: PatchRange
  ): Promise<FileNameToFileInfoMap | undefined> {
    let params = undefined;
    if (isMergeParent(patchRange.basePatchNum)) {
      params = {parent: getParentIndex(patchRange.basePatchNum)};
    } else if (patchRange.basePatchNum !== PARENT) {
      params = {base: patchRange.basePatchNum};
    }
    const url = await this._changeBaseURL(changeNum, patchRange.patchNum);
    return this._restApiHelper.fetchJSON({
      url: `${url}/files`,
      params,
      anonymizedUrl: `${ANONYMIZED_REVISION_BASE_URL}/files`,
    }) as Promise<FileNameToFileInfoMap | undefined>;
  }

  async getChangeEditFiles(
    changeNum: NumericChangeId,
    patchRange: PatchRange
  ): Promise<{files: FileNameToFileInfoMap} | undefined> {
    const changeUrl = await this._changeBaseURL(changeNum);
    let url = `${changeUrl}/edit?list`;
    let anonymizedUrl = `${changeUrl}/edit?list`;
    if (patchRange.basePatchNum !== PARENT) {
      url += '&base=' + encodeURIComponent(`${patchRange.basePatchNum}`);
      anonymizedUrl += '&base=*';
    }

    const response = await this._restApiHelper.fetch({url, anonymizedUrl});
    if (!response.ok || response.status === 204) {
      return undefined;
    }
    return (await readJSONResponsePayload(response)).parsed as unknown as
      | {files: FileNameToFileInfoMap}
      | undefined;
  }

  async queryChangeFiles(
    changeNum: NumericChangeId,
    patchNum: PatchSetNum,
    query: string,
    errFn?: ErrorCallback
  ): Promise<string[] | undefined> {
    const url = await this._changeBaseURL(changeNum, patchNum);
    return this._restApiHelper.fetchJSON({
      url: `${url}/files?q=${encodeURIComponent(query)}`,
      anonymizedUrl: `${ANONYMIZED_REVISION_BASE_URL}/files?q=*`,
      errFn,
    }) as Promise<string[] | undefined>;
  }

  getChangeOrEditFiles(
    changeNum: NumericChangeId,
    patchRange: PatchRange
  ): Promise<FileNameToFileInfoMap | undefined> {
    if (patchRange.patchNum === EDIT) {
      return this.getChangeEditFiles(changeNum, patchRange).then(
        res => res && res.files
      );
    }
    return this.getChangeFiles(changeNum, patchRange);
  }

  async getChangeRevisionActions(
    changeNum: NumericChangeId,
    patchNum: PatchSetNum
  ): Promise<ActionNameToActionInfoMap | undefined> {
    const url = await this._changeBaseURL(changeNum, patchNum);
    return this._restApiHelper.fetchJSON({
      url: `${url}/actions`,
      anonymizedUrl: `${ANONYMIZED_REVISION_BASE_URL}/actions`,
    }) as Promise<ActionNameToActionInfoMap | undefined>;
  }

  getChangeSuggestedReviewers(
    changeNum: NumericChangeId,
    inputVal?: string,
    errFn?: ErrorCallback
  ) {
    return this.getChangeSuggestedGroup(
      ReviewerState.REVIEWER,
      changeNum,
      inputVal,
      errFn
    );
  }

  getChangeSuggestedCCs(
    changeNum: NumericChangeId,
    inputVal?: string,
    errFn?: ErrorCallback
  ) {
    return this.getChangeSuggestedGroup(
      ReviewerState.CC,
      changeNum,
      inputVal,
      errFn
    );
  }

  private async getChangeSuggestedGroup(
    reviewerState: ReviewerState,
    changeNum: NumericChangeId,
    inputVal?: string, // If undefined, then default suggestions are returned
    errFn?: ErrorCallback
  ): Promise<SuggestedReviewerInfo[] | undefined> {
    // More suggestions may obscure content underneath in the reply dialog,
    // see issue 10793.
    const params: QuerySuggestedReviewersParams = {
      n: 6,
      'reviewer-state': reviewerState,
    };
    if (inputVal) {
      params.q = inputVal;
    }
    const url = await this._changeBaseURL(changeNum);
    return this._restApiHelper.fetchJSON({
      url: `${url}/suggest_reviewers`,
      params,
      anonymizedUrl: `${ANONYMIZED_CHANGE_BASE_URL}/suggest_reviewers`,
      errFn,
    }) as Promise<SuggestedReviewerInfo[] | undefined>;
  }

  async getChangeIncludedIn(
    changeNum: NumericChangeId
  ): Promise<IncludedInInfo | undefined> {
    const url = await this._changeBaseURL(changeNum);
    return this._restApiHelper.fetchJSON({
      url: `${url}/in`,
      anonymizedUrl: `${url}/in`,
    }) as Promise<IncludedInInfo | undefined>;
  }

  _computeFilter(filter: string) {
    if (filter?.startsWith('^')) {
      filter = '&r=' + encodeURIComponent(filter);
    } else if (filter) {
      filter = '&m=' + encodeURIComponent(filter);
    } else {
      filter = '';
    }
    return filter;
  }

  _getGroupsUrl(filter: string, groupsPerPage: number, offset?: number) {
    offset = offset || 0;

    return (
      `/groups/?n=${groupsPerPage + 1}&S=${offset}` +
      this._computeFilter(filter)
    );
  }

  _getReposUrl(
    filter: string | undefined,
    reposPerPage: number,
    offset?: number
  ): [boolean, string] {
    const defaultFilter = '';
    offset = offset || 0;
    filter ??= defaultFilter;
    const encodedFilter = encodeURIComponent(filter);

    if (filter.includes(':')) {
      // If the filter includes a semicolon, the user is using a more complex
      // query so we trust them and don't do any magic under the hood.
      return [
        true,
        `/projects/?n=${reposPerPage + 1}&S=${offset}` +
          `&query=${encodedFilter}`,
      ];
    }

    return [
      false,
      `/projects/?n=${reposPerPage + 1}&S=${offset}` + `&d=&m=${encodedFilter}`,
    ];
  }

  invalidateGroupsCache() {
    this._restApiHelper.invalidateFetchPromisesPrefix('/groups/?');
  }

  invalidateReposCache() {
    this._restApiHelper.invalidateFetchPromisesPrefix('/projects/?');
  }

  invalidateAccountsCache() {
    this._restApiHelper.invalidateFetchPromisesPrefix('/accounts/');
  }

  invalidateAccountsDetailCache() {
    this._restApiHelper.invalidateFetchPromisesPrefix('/accounts/self/detail');
  }

  invalidateAccountsEmailCache() {
    this._restApiHelper.invalidateFetchPromisesPrefix('/accounts/self/emails');
  }

  getGroups(filter: string, groupsPerPage: number, offset?: number) {
    const url = this._getGroupsUrl(filter, groupsPerPage, offset);

    return this._restApiHelper.fetchCacheJSON({
      url,
      anonymizedUrl: '/groups/?*',
    }) as Promise<GroupNameToGroupInfoMap | undefined>;
  }

  async getRepos(
    filter: string | undefined,
    reposPerPage: number,
    offset?: number,
    errFn?: ErrorCallback,
    requestOrigin?: string
  ): Promise<ProjectInfoWithName[] | undefined> {
    const [isQuery, url] = this._getReposUrl(filter, reposPerPage, offset);
    // If the request is a query then return the response directly as the result
    // will already be the expected array. If it is not a query, transform the
    // map to an array.
    if (isQuery) {
      return this._restApiHelper.fetchCacheJSON({
        fetchOptions: getFetchOptions({
          requestOrigin,
        }),
        url,
        anonymizedUrl: '/projects/?*',
        errFn,
      }) as Promise<ProjectInfoWithName[] | undefined>;
    } else {
      const result = await (this._restApiHelper.fetchCacheJSON({
        fetchOptions: getFetchOptions({
          requestOrigin,
        }),
        url,
        anonymizedUrl: '/projects/?*',
        errFn,
      }) as Promise<NameToProjectInfoMap | undefined>);
      if (result === undefined) return [];
      return Object.entries(result).map(([name, project]) => {
        return {
          ...project,
          name: name as RepoName,
        };
      });
    }
  }

  setRepoHead(repo: RepoName, ref: GitRef) {
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: {ref},
      }),
      url: `/projects/${encodeURIComponent(repo)}/HEAD`,
      anonymizedUrl: '/projects/*/HEAD',
      reportServerError: true,
    });
  }

  getRepoBranches(
    filter: string,
    repo: RepoName,
    reposBranchesPerPage: number,
    offset?: number,
    errFn?: ErrorCallback
  ): Promise<BranchInfo[] | undefined> {
    offset = offset || 0;
    const count = reposBranchesPerPage + 1;
    filter = this._computeFilter(filter);
    const encodedRepo = encodeURIComponent(repo);
    const url = `/projects/${encodedRepo}/branches?n=${count}&S=${offset}${filter}`;
    return this._restApiHelper.fetchJSON({
      url,
      errFn,
      anonymizedUrl: '/projects/*/branches?*',
    }) as Promise<BranchInfo[] | undefined>;
  }

  getRepoTags(
    filter: string,
    repo: RepoName,
    reposTagsPerPage: number,
    offset?: number,
    errFn?: ErrorCallback
  ) {
    offset = offset || 0;
    const encodedRepo = encodeURIComponent(repo);
    const n = reposTagsPerPage + 1;
    const encodedFilter = this._computeFilter(filter);
    const url =
      `/projects/${encodedRepo}/tags` + `?n=${n}&S=${offset}` + encodedFilter;
    return this._restApiHelper.fetchJSON({
      url,
      errFn,
      anonymizedUrl: '/projects/*/tags',
    }) as unknown as Promise<TagInfo[]>;
  }

  getPlugins(
    filter: string,
    pluginsPerPage: number,
    offset?: number,
    errFn?: ErrorCallback
  ): Promise<{[pluginName: string]: PluginInfo} | undefined> {
    offset = offset || 0;
    const encodedFilter = this._computeFilter(filter);
    const n = pluginsPerPage + 1;
    const url = `/plugins/?all&n=${n}&S=${offset}${encodedFilter}`;
    return this._restApiHelper.fetchJSON({
      url,
      errFn,
      anonymizedUrl: '/plugins/?all',
    });
  }

  getRepoSubmitRequirements(
    repoName: RepoName,
    errFn?: ErrorCallback
  ): Promise<SubmitRequirementInfo[] | undefined> {
    return this._restApiHelper.fetchJSON({
      url: `/projects/${encodeURIComponent(repoName)}/submit_requirements`,
      errFn,
      anonymizedUrl: '/projects/*/submit_requirements',
    }) as Promise<SubmitRequirementInfo[] | undefined>;
  }

  createSubmitRequirement(
    repoName: RepoName,
    input: SubmitRequirementInput,
    errFn?: ErrorCallback
  ): Promise<SubmitRequirementInfo | undefined> {
    return this._restApiHelper.fetchJSON({
      url: `/projects/${encodeURIComponent(
        repoName
      )}/submit_requirements/${encodeURIComponent(input.name)}`,
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: input,
      }),
      errFn,
      anonymizedUrl: '/projects/*/submit_requirements/*',
    }) as Promise<SubmitRequirementInfo | undefined>;
  }

  updateSubmitRequirement(
    repoName: RepoName,
    submitRequirementName: string,
    input: SubmitRequirementInput,
    errFn?: ErrorCallback
  ): Promise<SubmitRequirementInfo | undefined> {
    return this._restApiHelper.fetchJSON({
      url: `/projects/${encodeURIComponent(
        repoName
      )}/submit_requirements/${encodeURIComponent(submitRequirementName)}`,
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: input,
      }),
      errFn,
      anonymizedUrl: '/projects/*/submit_requirements/*',
    }) as Promise<SubmitRequirementInfo | undefined>;
  }

  deleteSubmitRequirement(
    repoName: RepoName,
    submitRequirementName: string,
    errFn?: ErrorCallback
  ): Promise<Response> {
    return this._restApiHelper.fetch({
      fetchOptions: {method: HttpMethod.DELETE},
      url: `/projects/${encodeURIComponent(
        repoName
      )}/submit_requirements/${encodeURIComponent(submitRequirementName)}`,
      errFn,
      anonymizedUrl: '/projects/*/submit_requirements/*',
      reportServerError: true,
    });
  }

  saveRepoSubmitRequirementsForReview(
    repoName: RepoName,
    input: BatchSubmitRequirementInput,
    errFn?: ErrorCallback
  ): Promise<ChangeInfo | undefined> {
    return this._restApiHelper.fetchJSON({
      url: `/projects/${encodeURIComponent(
        repoName
      )}/submit_requirements:review`,
      fetchOptions: getFetchOptions({
        method: HttpMethod.POST,
        body: input,
      }),
      errFn,
      anonymizedUrl: '/projects/*/submit_requirements:review',
    }) as Promise<ChangeInfo | undefined>;
  }

  getRepoLabels(
    repoName: RepoName,
    errFn?: ErrorCallback
  ): Promise<LabelDefinitionInfo[] | undefined> {
    const params: {[key: string]: string} = {};
    return this._restApiHelper.fetchJSON({
      url: `/projects/${encodeURIComponent(repoName)}/labels/`,
      params,
      errFn,
      anonymizedUrl: '/projects/*/labels/',
    }) as Promise<LabelDefinitionInfo[] | undefined>;
  }

  getRepoLabel(
    repoName: RepoName,
    labelName: string,
    errFn?: ErrorCallback
  ): Promise<LabelDefinitionInfo | undefined> {
    return this._restApiHelper.fetchJSON({
      url: `/projects/${encodeURIComponent(
        repoName
      )}/labels/${encodeURIComponent(labelName)}`,
      errFn,
      anonymizedUrl: '/projects/*/labels/*',
    }) as Promise<LabelDefinitionInfo | undefined>;
  }

  createRepoLabel(
    repoName: RepoName,
    labelName: string,
    input: LabelDefinitionInput,
    errFn?: ErrorCallback
  ): Promise<LabelDefinitionInfo | undefined> {
    return this._restApiHelper.fetchJSON({
      url: `/projects/${encodeURIComponent(
        repoName
      )}/labels/${encodeURIComponent(labelName)}`,
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: input,
      }),
      errFn,
      anonymizedUrl: '/projects/*/labels/*',
    }) as Promise<LabelDefinitionInfo | undefined>;
  }

  saveRepoLabelsForReview(
    repoName: RepoName,
    input: BatchLabelInput,
    errFn?: ErrorCallback
  ): Promise<ChangeInfo | undefined> {
    return this._restApiHelper.fetchJSON({
      url: `/projects/${encodeURIComponent(repoName)}/labels:review`,
      fetchOptions: getFetchOptions({
        method: HttpMethod.POST,
        body: input,
      }),
      errFn,
      anonymizedUrl: '/projects/*/labels:review',
    }) as Promise<ChangeInfo | undefined>;
  }

  updateRepoLabel(
    repoName: RepoName,
    labelName: string,
    input: LabelDefinitionInput,
    errFn?: ErrorCallback
  ): Promise<LabelDefinitionInfo | undefined> {
    return this._restApiHelper.fetchJSON({
      url: `/projects/${encodeURIComponent(
        repoName
      )}/labels/${encodeURIComponent(labelName)}`,
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: input,
      }),
      errFn,
      anonymizedUrl: '/projects/*/labels/*',
    }) as Promise<LabelDefinitionInfo | undefined>;
  }

  deleteRepoLabel(
    repoName: RepoName,
    labelName: string,
    input?: DeleteLabelInput,
    errFn?: ErrorCallback
  ): Promise<Response> {
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.DELETE,
        body: input,
      }),
      url: `/projects/${encodeURIComponent(
        repoName
      )}/labels/${encodeURIComponent(labelName)}`,
      errFn,
      anonymizedUrl: '/projects/*/labels/*',
      reportServerError: true,
    });
  }

  getRepoAccessRights(
    repoName: RepoName,
    errFn?: ErrorCallback
  ): Promise<ProjectAccessInfo | undefined> {
    return this._restApiHelper.fetchJSON({
      url: `/projects/${encodeURIComponent(repoName)}/access`,
      errFn,
      anonymizedUrl: '/projects/*/access',
    }) as Promise<ProjectAccessInfo | undefined>;
  }

  setRepoAccessRights(
    repoName: RepoName,
    repoInfo: ProjectAccessInput
  ): Promise<Response> {
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.POST,
        body: repoInfo,
      }),
      url: `/projects/${encodeURIComponent(repoName)}/access`,
      anonymizedUrl: '/projects/*/access',
      reportServerError: true,
    });
  }

  setRepoAccessRightsForReview(
    projectName: RepoName,
    projectInfo: ProjectAccessInput
  ): Promise<ChangeInfo | undefined> {
    return this._restApiHelper.fetchJSON({
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: projectInfo,
      }),
      url: `/projects/${encodeURIComponent(projectName)}/access:review`,
      anonymizedUrl: '/projects/*/access:review',
    }) as unknown as Promise<ChangeInfo | undefined>;
  }

  getSuggestedGroups(
    inputVal: string,
    project?: RepoName,
    n?: number,
    errFn?: ErrorCallback
  ): Promise<GroupNameToGroupInfoMap | undefined> {
    const params: QueryGroupsParams = {s: inputVal};
    if (n) {
      params.n = n;
    }
    if (project) {
      params.p = project;
    }
    return this._restApiHelper.fetchJSON({
      url: '/groups/',
      params,
      reportUrlAsIs: true,
      errFn,
    }) as Promise<GroupNameToGroupInfoMap | undefined>;
  }

  getSuggestedRepos(
    inputVal: string,
    n?: number,
    errFn?: ErrorCallback
  ): Promise<NameToProjectInfoMap | undefined> {
    const params = {
      m: inputVal,
      n: MAX_PROJECT_RESULTS,
      type: 'ALL',
    };
    if (n) {
      params.n = n;
    }
    return this._restApiHelper.fetchJSON({
      url: '/projects/',
      params,
      reportUrlAsIs: true,
      errFn,
    });
  }

  async queryAccounts(
    inputVal: string,
    n?: number,
    canSee?: NumericChangeId,
    filterActive?: boolean,
    errFn?: ErrorCallback
  ): Promise<AccountInfo[] | undefined> {
    const params: QueryAccountsParams = {o: 'DETAILS', q: ''};
    const queryParams = [];
    inputVal = inputVal?.trim() ?? '';
    if (inputVal.length > 0) {
      // Wrap in quotes so that reserved keywords do not throw an error such
      // as typing "and"
      // Espace quotes in user input since we are wrapping input in quotes
      // explicitly
      queryParams.push(`${escapeAndWrapSearchOperatorValue(inputVal)}`);
    }
    if (canSee) {
      const project = await this.getRepoName(canSee);
      queryParams.push(`cansee:${project}~${canSee}`);
    }
    if (filterActive) {
      queryParams.push('is:active');
    }
    params.q = queryParams.join(' and ');
    if (!params.q) return Promise.resolve([]);
    if (n) {
      params.n = n;
    }
    return this._restApiHelper.fetchJSON({
      url: '/accounts/',
      params,
      anonymizedUrl: '/accounts/?n=*',
      errFn,
    }) as Promise<AccountInfo[] | undefined>;
  }

  getAccountSuggestions(inputVal: string): Promise<AccountInfo[] | undefined> {
    const params: QueryAccountsParams = {suggest: undefined, q: ''};
    inputVal = inputVal?.trim() ?? '';
    if (inputVal.length > 0) {
      params.q = inputVal;
    }
    if (!params.q) return Promise.resolve([]);
    return this._restApiHelper.fetchJSON({
      url: '/accounts/',
      params,
    }) as Promise<AccountInfo[] | undefined>;
  }

  addChangeReviewer(
    changeNum: NumericChangeId,
    reviewerID: AccountId | EmailAddress | GroupId
  ) {
    return this._sendChangeReviewerRequest(
      HttpMethod.POST,
      changeNum,
      reviewerID
    );
  }

  removeChangeReviewer(
    changeNum: NumericChangeId,
    reviewerID: AccountId | EmailAddress | GroupId
  ) {
    return this._sendChangeReviewerRequest(
      HttpMethod.DELETE,
      changeNum,
      reviewerID
    );
  }

  _sendChangeReviewerRequest(
    method: HttpMethod.POST | HttpMethod.DELETE,
    changeNum: NumericChangeId,
    reviewerID: AccountId | EmailAddress | GroupId
  ) {
    return this.getChangeActionURL(changeNum, undefined, '/reviewers').then(
      url => {
        let body;
        switch (method) {
          case HttpMethod.POST:
            body = {reviewer: reviewerID};
            break;
          case HttpMethod.DELETE:
            url += '/' + encodeURIComponent(reviewerID);
            break;
          default:
            assertNever(method, `Unsupported HTTP method: ${method}`);
        }

        return this._restApiHelper.fetch({
          fetchOptions: getFetchOptions({method, body}),
          url,
          reportServerError: true,
        });
      }
    );
  }

  async getRelatedChanges(
    changeNum: NumericChangeId,
    patchNum: PatchSetNum
  ): Promise<RelatedChangesInfo | undefined> {
    const options = '?o=SUBMITTABLE';
    const url = await this._changeBaseURL(changeNum, patchNum);
    return this._restApiHelper.fetchJSON({
      url: `${url}/related${options}`,
      anonymizedUrl: `${ANONYMIZED_REVISION_BASE_URL}/related${options}`,
    }) as Promise<RelatedChangesInfo | undefined>;
  }

  async getChangesSubmittedTogether(
    changeNum: NumericChangeId,
    options: string[] = ['NON_VISIBLE_CHANGES']
  ): Promise<SubmittedTogetherInfo | undefined> {
    const url = await this._changeBaseURL(changeNum);
    const endpoint = `/submitted_together?o=${options.join('&o=')}`;
    return this._restApiHelper.fetchJSON({
      url: `${url}${endpoint}`,
      anonymizedUrl: `${ANONYMIZED_CHANGE_BASE_URL}${endpoint}`,
    }) as Promise<SubmittedTogetherInfo | undefined>;
  }

  async getChangeConflicts(
    changeNum: NumericChangeId
  ): Promise<ChangeInfo[] | undefined> {
    const config = await this.getConfig(false);
    if (!config?.change?.conflicts_predicate_enabled) {
      return [];
    }
    const options = listChangesOptionsToHex(
      ListChangesOption.CURRENT_REVISION,
      ListChangesOption.CURRENT_COMMIT,
      ListChangesOption.SUBMITTABLE,
      ListChangesOption.SKIP_DIFFSTAT
    );
    const params = {
      O: options,
      q: `status:open conflicts:${changeNum}`,
    };
    return this._restApiHelper.fetchJSON({
      url: '/changes/',
      params,
      anonymizedUrl: '/changes/conflicts:*',
    }) as Promise<ChangeInfo[] | undefined>;
  }

  getChangeCherryPicks(
    repo: RepoName,
    changeID: ChangeId,
    branch: BranchName
  ): Promise<ChangeInfo[] | undefined> {
    const options = listChangesOptionsToHex(
      ListChangesOption.CURRENT_REVISION,
      ListChangesOption.CURRENT_COMMIT,
      ListChangesOption.SKIP_DIFFSTAT
    );
    const query = [
      `project:${repo}`,
      `change:${changeID}`,
      `-branch:${branch}`,
      '-is:abandoned',
    ].join(' ');
    const params = {
      O: options,
      q: query,
    };
    return this._restApiHelper.fetchJSON({
      url: '/changes/',
      params,
      anonymizedUrl: '/changes/change:*',
    }) as Promise<ChangeInfo[] | undefined>;
  }

  getChangesWithSameTopic(
    topic: string,
    options?: {
      openChangesOnly?: boolean;
      changeToExclude?: NumericChangeId;
    }
  ): Promise<ChangeInfo[] | undefined> {
    const requestOptions = listChangesOptionsToHex(
      ListChangesOption.LABELS,
      ListChangesOption.CURRENT_REVISION,
      ListChangesOption.CURRENT_COMMIT,
      ListChangesOption.DETAILED_LABELS,
      ListChangesOption.SUBMITTABLE,
      ListChangesOption.SKIP_DIFFSTAT
    );
    const queryTerms = [`topic:${escapeAndWrapSearchOperatorValue(topic)}`];
    if (options?.openChangesOnly) {
      queryTerms.push('status:open');
    }
    if (options?.changeToExclude !== undefined) {
      queryTerms.push(`-change:${options.changeToExclude}`);
    }
    const params = {
      O: requestOptions,
      q: queryTerms.join(' '),
    };
    return this._restApiHelper.fetchJSON({
      url: '/changes/',
      params,
      anonymizedUrl: '/changes/topic:*',
    }) as Promise<ChangeInfo[] | undefined>;
  }

  getChangesWithSimilarTopic(
    topic: string,
    errFn?: ErrorCallback
  ): Promise<ChangeInfo[] | undefined> {
    const query = `intopic:${escapeAndWrapSearchOperatorValue(topic)}`;
    return this._restApiHelper.fetchJSON({
      url: '/changes/',
      params: {q: query},
      anonymizedUrl: '/changes/intopic:*',
      errFn,
    }) as Promise<ChangeInfo[] | undefined>;
  }

  getChangesWithSimilarHashtag(
    hashtag: string,
    errFn?: ErrorCallback
  ): Promise<ChangeInfo[] | undefined> {
    const query = `inhashtag:${escapeAndWrapSearchOperatorValue(hashtag)}`;
    return this._restApiHelper.fetchJSON({
      url: '/changes/',
      params: {q: query},
      anonymizedUrl: '/changes/inhashtag:*',
      errFn,
    }) as Promise<ChangeInfo[] | undefined>;
  }

  async getReviewedFiles(
    changeNum: NumericChangeId,
    patchNum: PatchSetNum
  ): Promise<string[] | undefined> {
    const url = await this._changeBaseURL(changeNum, patchNum);
    return this._restApiHelper.fetchJSON({
      url: `${url}/files?reviewed`,
      anonymizedUrl: `${ANONYMIZED_REVISION_BASE_URL}/files?reviewed`,
    }) as Promise<string[] | undefined>;
  }

  async saveFileReviewed(
    changeNum: NumericChangeId,
    patchNum: PatchSetNum,
    path: string,
    reviewed: boolean
  ): Promise<Response> {
    const url = await this._changeBaseURL(changeNum, patchNum);
    return this._restApiHelper.fetch({
      fetchOptions: {method: reviewed ? HttpMethod.PUT : HttpMethod.DELETE},
      url: `${url}/files/${encodeURIComponent(path)}/reviewed`,
      anonymizedUrl: `${ANONYMIZED_REVISION_BASE_URL}/files/*/reviewed`,
      reportServerError: true,
    });
  }

  getSaveReviewChangeOptions(): string[] {
    const options = [
      'CHANGE_ACTIONS',
      'DETAILED_LABELS',
      'DETAILED_ACCOUNTS',
      'MESSAGES',
      'REVIEWER_UPDATES',
      'SKIP_DIFFSTAT',
    ];
    return options;
  }

  async saveChangeReview(
    changeNum: NumericChangeId,
    patchNum: PatchSetNum,
    review: ReviewInput,
    errFn?: ErrorCallback,
    fetchDetail?: boolean
  ): Promise<ReviewResult | undefined> {
    if (fetchDetail) {
      review.response_format_options = this.getSaveReviewChangeOptions();
    }
    const promises: [Promise<void>, Promise<string>] = [
      this.awaitPendingDiffDrafts(),
      this.getChangeActionURL(changeNum, patchNum, '/review'),
    ];
    return Promise.all(promises).then(([, url]) =>
      this._restApiHelper.fetchJSON({
        fetchOptions: getFetchOptions({
          method: HttpMethod.POST,
          body: review,
        }),
        url,
        errFn,
        isHighPriority: true,
      })
    ) as unknown as Promise<ReviewResult | undefined>;
  }

  async getChangeEdit(
    changeNum?: NumericChangeId
  ): Promise<EditInfo | undefined> {
    if (!changeNum) return undefined;
    const params = {'download-commands': true};
    const loggedIn = await this.getLoggedIn();
    if (!loggedIn) {
      return undefined;
    }
    const url = await this._changeBaseURL(changeNum);
    const response = await this._restApiHelper.fetch({
      url: `${url}/edit/`,
      params,
      anonymizedUrl: `${ANONYMIZED_CHANGE_BASE_URL}/edit/`,
    });
    // If there is no edit patchset 204 is returned.
    if (!response.ok || response.status === 204) {
      return undefined;
    }
    return (await readJSONResponsePayload(response))
      .parsed as unknown as EditInfo;
  }

  createChange(
    repo: RepoName,
    branch: BranchName,
    subject: string,
    topic?: string,
    isPrivate?: boolean,
    workInProgress?: boolean,
    baseChange?: ChangeId,
    baseCommit?: string
  ): Promise<ChangeInfo | undefined> {
    return this._restApiHelper.fetchJSON({
      fetchOptions: getFetchOptions({
        method: HttpMethod.POST,
        body: {
          project: repo,
          branch,
          subject,
          topic,
          is_private: isPrivate,
          work_in_progress: workInProgress,
          base_change: baseChange,
          base_commit: baseCommit,
        },
      }),
      url: '/changes/',
      reportUrlAsIs: true,
    }) as unknown as Promise<ChangeInfo | undefined>;
  }

  getFileContent(
    changeNum: NumericChangeId,
    path: string,
    patchNum: PatchSetNum
  ): Promise<Response | Base64FileContent | undefined> {
    // 404s indicate the file does not exist yet in the revision, so suppress
    // them.
    const promise =
      patchNum === EDIT
        ? this._getFileInChangeEdit(changeNum, path)
        : this._getFileInRevision(changeNum, path, patchNum, suppress404s);

    return promise.then(res => {
      // A 204 is returned if the file is empty so we have
      // to return early.
      if (!res.ok || res.status === 204) {
        return res;
      }

      // The file type (used for syntax highlighting) is identified in the
      // X-FYI-Content-Type header of the response.
      const type = res.headers.get('X-FYI-Content-Type');
      return readJSONResponsePayload(res).then(content => {
        const strContent = content.parsed as unknown as string | null;
        return {content: strContent, type, ok: true};
      });
    });
  }

  /**
   * Gets a file in a specific change and revision.
   */
  async _getFileInRevision(
    changeNum: NumericChangeId,
    path: string,
    patchNum: PatchSetNum,
    errFn?: ErrorCallback
  ): Promise<Response> {
    const url = await this._changeBaseURL(changeNum, patchNum);
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        headers: {Accept: 'application/json'},
      }),
      url: `${url}/files/${encodeURIComponent(path)}/content`,
      errFn,
      anonymizedUrl: `${ANONYMIZED_REVISION_BASE_URL}/files/*/content`,
      reportServerError: true,
    });
  }

  /**
   * Gets a file in a change edit.
   */
  async _getFileInChangeEdit(
    changeNum: NumericChangeId,
    path: string
  ): Promise<Response> {
    const url = await this._changeBaseURL(changeNum);
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        headers: {Accept: 'application/json'},
      }),
      url: `${url}/edit/${encodeURIComponent(path)}`,
      anonymizedUrl: `${ANONYMIZED_CHANGE_BASE_URL}/edit/*`,
      reportServerError: true,
    });
  }

  async rebaseChangeEdit(changeNum: NumericChangeId): Promise<Response> {
    const url = await this._changeBaseURL(changeNum);
    return this._restApiHelper.fetch({
      fetchOptions: {method: HttpMethod.POST},
      url: `${url}/edit:rebase`,
      anonymizedUrl: `${ANONYMIZED_CHANGE_BASE_URL}/edit:rebase`,
      reportServerError: true,
    });
  }

  async deleteChangeEdit(changeNum: NumericChangeId): Promise<Response> {
    const url = await this._changeBaseURL(changeNum);
    return this._restApiHelper.fetch({
      fetchOptions: {method: HttpMethod.DELETE},
      url: `${url}/edit`,
      anonymizedUrl: `${ANONYMIZED_CHANGE_BASE_URL}/edit`,
      reportServerError: true,
    });
  }

  async restoreFileInChangeEdit(
    changeNum: NumericChangeId,
    restore_path: string
  ): Promise<Response> {
    const url = await this._changeBaseURL(changeNum);
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.POST,
        body: {restore_path},
      }),
      url: `${url}/edit`,
      anonymizedUrl: `${ANONYMIZED_CHANGE_BASE_URL}/edit`,
      reportServerError: true,
    });
  }

  async renameFileInChangeEdit(
    changeNum: NumericChangeId,
    old_path: string,
    new_path: string
  ): Promise<Response> {
    const url = await this._changeBaseURL(changeNum);
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.POST,
        body: {old_path, new_path},
      }),
      url: `${url}/edit`,
      anonymizedUrl: `${ANONYMIZED_CHANGE_BASE_URL}/edit`,
      reportServerError: true,
    });
  }

  async deleteFileInChangeEdit(
    changeNum: NumericChangeId,
    path: string
  ): Promise<Response> {
    const url = await this._changeBaseURL(changeNum);
    return this._restApiHelper.fetch({
      fetchOptions: {method: HttpMethod.DELETE},
      url: `${url}/edit/${encodeURIComponent(path)}`,
      anonymizedUrl: `${ANONYMIZED_CHANGE_BASE_URL}/edit/*`,
      reportServerError: true,
    });
  }

  async saveChangeEdit(
    changeNum: NumericChangeId,
    path: string,
    contents: string
  ): Promise<Response> {
    const url = await this._changeBaseURL(changeNum);
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: contents,
        contentType: 'text/plain',
      }),
      url: `${url}/edit/${encodeURIComponent(path)}`,
      anonymizedUrl: `${ANONYMIZED_CHANGE_BASE_URL}/edit/*`,
      reportServerError: true,
    });
  }

  async saveFileUploadChangeEdit(
    changeNum: NumericChangeId,
    path: string,
    content: string
  ): Promise<Response> {
    const url = await this._changeBaseURL(changeNum);
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: {binary_content: content},
      }),
      url: `${url}/edit/${encodeURIComponent(path)}`,
      anonymizedUrl: `${ANONYMIZED_CHANGE_BASE_URL}/edit/*`,
      reportServerError: true,
    });
  }

  async getFixPreview(
    changeNum: NumericChangeId,
    patchNum: PatchSetNum,
    fixReplacementInfos: FixReplacementInfo[]
  ): Promise<FilePathToDiffInfoMap | undefined> {
    const key = `${changeNum}-${patchNum}-${JSON.stringify(
      fixReplacementInfos
    )}`;
    if (fixPreviewCache.has(key)) {
      return fixPreviewCache.get(key);
    }

    const promise = (async () => {
      try {
        const url = await this._changeBaseURL(changeNum, patchNum);
        const response = (await this._restApiHelper.fetchJSON({
          fetchOptions: getFetchOptions({
            method: HttpMethod.POST,
            body: {fix_replacement_infos: fixReplacementInfos},
          }),
          url: `${url}/fix:preview`,
          anonymizedUrl: `${ANONYMIZED_REVISION_BASE_URL}/fix:preview`,
        })) as FilePathToDiffInfoMap | undefined;

        if (response === undefined) {
          fixPreviewCache.delete(key);
        }
        return response;
      } catch (err) {
        fixPreviewCache.delete(key);
        throw err;
      }
    })();

    fixPreviewCache.set(key, promise);
    return promise;
  }

  async applyFixSuggestion(
    changeNum: NumericChangeId,
    fixPatchNum: PatchSetNum,
    fixReplacementInfos: FixReplacementInfo[],
    targetPatchNum?: PatchSetNum,
    errFn?: ErrorCallback
  ): Promise<Response> {
    const url = await this._changeBaseURL(
      changeNum,
      targetPatchNum ?? fixPatchNum
    );
    const body: {
      fix_replacement_infos: FixReplacementInfo[];
      original_patchset_for_fix?: PatchSetNum;
    } = {
      fix_replacement_infos: fixReplacementInfos,
    };
    if (targetPatchNum !== undefined && targetPatchNum !== fixPatchNum) {
      body.original_patchset_for_fix = fixPatchNum;
    }
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.POST,
        headers: {Accept: 'application/json'},
        body,
      }),
      url: `${url}/fix:apply`,
      anonymizedUrl: `${ANONYMIZED_REVISION_BASE_URL}/fix:apply`,
      errFn,
      reportServerError: true,
    });
  }

  async publishChangeEdit(changeNum: NumericChangeId) {
    const url = await this._changeBaseURL(changeNum);
    return this._restApiHelper.fetch({
      fetchOptions: {method: HttpMethod.POST},
      url: `${url}/edit:publish`,
      anonymizedUrl: `${ANONYMIZED_CHANGE_BASE_URL}/edit:publish`,
      reportServerError: true,
    });
  }

  async putChangeCommitMessage(
    changeNum: NumericChangeId,
    message: string,
    committerEmail: string | null
  ) {
    const url = await this._changeBaseURL(changeNum);
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: {message, committer_email: committerEmail},
      }),
      url: `${url}/message`,
      anonymizedUrl: `${ANONYMIZED_CHANGE_BASE_URL}/message`,
      reportServerError: true,
    });
  }

  async updateIdentityInChangeEdit(
    changeNum: NumericChangeId,
    name: string,
    email: string,
    type: string
  ) {
    const url = await this._changeBaseURL(changeNum);
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: {name, email, type},
      }),
      url: `${url}/edit:identity`,
      anonymizedUrl: `${ANONYMIZED_CHANGE_BASE_URL}/edit:identity`,
      reportServerError: true,
    });
  }

  async deleteChangeCommitMessage(
    changeNum: NumericChangeId,
    messageId: ChangeMessageId
  ) {
    const url = await this._changeBaseURL(changeNum);
    return this._restApiHelper.fetch({
      fetchOptions: {method: HttpMethod.DELETE},
      url: `${url}/messages/${messageId}`,
      anonymizedUrl: `${ANONYMIZED_CHANGE_BASE_URL}/messages/${messageId}`,
      reportServerError: true,
    });
  }

  saveChangeStarred(
    changeNum: NumericChangeId,
    starred: boolean
  ): Promise<Response> {
    // Some servers may require the project name to be provided
    // alongside the change number, so resolve the project name
    // first.
    return this.getRepoName(changeNum).then(project => {
      const encodedRepoName = encodeURIComponent(project) + '~';
      const url = `/accounts/self/starred.changes/${encodedRepoName}${changeNum}`;
      return this._serialScheduler.schedule(() =>
        this._restApiHelper.fetch({
          fetchOptions: {method: starred ? HttpMethod.PUT : HttpMethod.DELETE},
          url,
          anonymizedUrl: '/accounts/self/starred.changes/*',
        })
      );
    });
  }

  /**
   * Wrapper around _restApiHelper.fetch used by GrPluginRestApi
   *
   * @param body passed as null sometimes
   * and also apparently a number. TODO (beckysiegel) remove need for
   * number at least.
   */
  send(
    method: HttpMethod,
    url: string,
    body?: RequestPayload,
    errFn?: ErrorCallback,
    contentType?: string,
    requestOrigin?: string
  ): Promise<Response | undefined> {
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method,
        body,
        contentType,
        requestOrigin,
      }),
      url,
      errFn,
      reportServerError: true,
    });
  }

  async getDiff(
    changeNum: NumericChangeId,
    basePatchNum: PatchSetNum,
    patchNum: PatchSetNum,
    path: string,
    whitespace?: IgnoreWhitespaceType,
    errFn?: ErrorCallback
  ): Promise<DiffInfo | undefined> {
    const params: GetDiffParams = {
      intraline: null,
      whitespace: whitespace || 'IGNORE_NONE',
    };
    if (isMergeParent(basePatchNum)) {
      params.parent = getParentIndex(basePatchNum);
    } else if (basePatchNum !== PARENT) {
      params.base = basePatchNum;
    }

    const url = await this._changeBaseURL(changeNum, patchNum);
    return this._restApiHelper.fetchJSON({
      // Invalidate the cache if this is the edit patch to make sure we always
      // get latest.
      fetchOptions: getFetchOptions({
        headers: patchNum === EDIT ? {'Cache-Control': 'no-cache'} : undefined,
      }),
      url: `${url}/files/${encodeURIComponent(path)}/diff`,
      params,
      errFn,
      anonymizedUrl: `${ANONYMIZED_REVISION_BASE_URL}'/files/*/diff`,
    }) as Promise<DiffInfo | undefined>;
  }

  getDiffComments(
    changeNum: NumericChangeId
  ): Promise<{[path: string]: CommentInfo[]} | undefined>;

  getDiffComments(
    changeNum: NumericChangeId,
    basePatchNum: BasePatchSetNum,
    patchNum: PatchSetNum,
    path: string
  ): Promise<GetDiffCommentsOutput>;

  getDiffComments(
    changeNum: NumericChangeId,
    basePatchNum?: BasePatchSetNum,
    patchNum?: PatchSetNum,
    path?: string
  ) {
    if (!basePatchNum && !patchNum && !path) {
      return this._getDiffComments(changeNum, '/comments', {
        'enable-context': true,
        'context-padding': 3,
      });
    }
    return this._getDiffComments(
      changeNum,
      '/comments',
      {'enable-context': true, 'context-padding': 3},
      basePatchNum,
      patchNum,
      path
    );
  }

  async getDiffDrafts(
    changeNum: NumericChangeId
  ): Promise<{[path: string]: DraftInfo[]} | undefined> {
    const loggedIn = await this.getLoggedIn();
    if (!loggedIn) return {};
    const comments = await this._getDiffComments(changeNum, '/drafts', {
      'enable-context': true,
      'context-padding': 3,
    });
    return addDraftProp(comments);
  }

  _setRange(comments: CommentInfo[], comment: CommentInfo) {
    if (comment.in_reply_to && !comment.range) {
      for (let i = 0; i < comments.length; i++) {
        if (comments[i].id === comment.in_reply_to) {
          comment.range = comments[i].range;
          break;
        }
      }
    }
    return comment;
  }

  _setRanges(comments?: CommentInfo[]) {
    comments = comments || [];
    comments.sort(
      (a, b) => parseDate(a.updated).valueOf() - parseDate(b.updated).valueOf()
    );
    for (const comment of comments) {
      this._setRange(comments, comment);
    }
    return comments;
  }

  _getDiffComments(
    changeNum: NumericChangeId,
    endpoint: '/comments' | '/drafts',
    params?: FetchParams
  ): Promise<{[path: string]: CommentInfo[]} | undefined>;

  _getDiffComments(
    changeNum: NumericChangeId,
    endpoint: '/comments' | '/drafts',
    params?: FetchParams,
    basePatchNum?: BasePatchSetNum,
    patchNum?: PatchSetNum,
    path?: string
  ): Promise<GetDiffCommentsOutput>;

  /**
   * Fetches the comments for a given patchNum.
   * Helper function to make promises more legible.
   */
  _getDiffComments(
    changeNum: NumericChangeId,
    endpoint: string,
    params?: FetchParams,
    basePatchNum?: BasePatchSetNum,
    patchNum?: PatchSetNum,
    path?: string
  ): Promise<
    GetDiffCommentsOutput | {[path: string]: CommentInfo[]} | undefined
  > {
    // We don't want to add accept header, since preloading of comments is
    // working only without accept header.
    const noAcceptHeader = true;
    const fetchComments = (patchNum?: PatchSetNum) =>
      this._changeBaseURL(changeNum, patchNum).then(url =>
        this._restApiHelper.fetchJSON(
          {
            url: `${url}${endpoint}`,
            anonymizedUrl: `${ANONYMIZED_REVISION_BASE_URL}${endpoint}`,
            params,
          },
          noAcceptHeader
        )
      ) as Promise<{[path: string]: CommentInfo[]} | undefined>;

    if (!basePatchNum && !patchNum && !path) {
      return fetchComments();
    }
    function onlyParent(c: CommentInfo) {
      return c.side === CommentSide.PARENT;
    }
    function withoutParent(c: CommentInfo) {
      return c.side !== CommentSide.PARENT;
    }
    function setPath(c: CommentInfo) {
      c.path = path;
    }

    const promises = [];
    let comments: CommentInfo[];
    let baseComments: CommentInfo[];
    let fetchPromise;
    fetchPromise = fetchComments(patchNum).then(response => {
      comments = (response && path && response[path]) || [];
      // Sort comments by date so that parent ranges can be propagated
      // in a single pass.
      comments = this._setRanges(comments);

      if (basePatchNum === PARENT) {
        baseComments = comments.filter(onlyParent);
        baseComments.forEach(setPath);
      }
      comments = comments.filter(withoutParent);

      comments.forEach(setPath);
    });
    promises.push(fetchPromise);

    if (basePatchNum !== PARENT) {
      fetchPromise = fetchComments(basePatchNum).then(response => {
        baseComments = ((response && path && response[path]) || []).filter(
          withoutParent
        );
        baseComments = this._setRanges(baseComments);
        baseComments.forEach(setPath);
      });
      promises.push(fetchPromise);
    }

    return Promise.all(promises).then(() =>
      Promise.resolve({
        baseComments,
        comments,
      })
    );
  }

  async getPortedComments(
    changeNum: NumericChangeId,
    revision: RevisionId
  ): Promise<{[path: string]: CommentInfo[]} | undefined> {
    // maintaining a custom error function so that errors do not surface in UI
    const errFn: ErrorCallback = (response?: Response | null) => {
      if (response)
        console.info(`Fetching ported comments failed, ${response.status}`);
    };
    const url = await this._changeBaseURL(changeNum, revision);
    return this._restApiHelper.fetchJSON({
      url: `${url}/ported_comments/`,
      errFn,
    });
  }

  async getPortedDrafts(
    changeNum: NumericChangeId,
    revision: RevisionId
  ): Promise<{[path: string]: DraftInfo[]} | undefined> {
    // maintaining a custom error function so that errors do not surface in UI
    const errFn: ErrorCallback = (response?: Response | null) => {
      if (response)
        console.info(`Fetching ported drafts failed, ${response.status}`);
    };
    const loggedIn = await this.getLoggedIn();
    if (!loggedIn) return {};
    const url = await this._changeBaseURL(changeNum, revision);
    const comments = (await this._restApiHelper.fetchJSON({
      url: `${url}/ported_drafts/`,
      errFn,
    })) as {[path: string]: CommentInfo[]} | undefined;
    return addDraftProp(comments);
  }

  saveDiffDraft(
    changeNum: NumericChangeId,
    patchNum: PatchSetNum,
    draft: CommentInput
  ) {
    return this._sendDiffDraftRequest(
      HttpMethod.PUT,
      changeNum,
      patchNum,
      draft
    );
  }

  deleteDiffDraft(
    changeNum: NumericChangeId,
    patchNum: PatchSetNum,
    draft: {id: UrlEncodedCommentId}
  ) {
    return this._sendDiffDraftRequest(
      HttpMethod.DELETE,
      changeNum,
      patchNum,
      draft
    );
  }

  hasPendingDiffDrafts(): number {
    const promises = this._pendingRequests[Requests.SEND_DIFF_DRAFT];
    return promises && promises.length;
  }

  awaitPendingDiffDrafts(): Promise<void> {
    return Promise.all(
      this._pendingRequests[Requests.SEND_DIFF_DRAFT] || []
    ).then(() => {
      this._pendingRequests[Requests.SEND_DIFF_DRAFT] = [];
    });
  }

  _sendDiffDraftRequest(
    method: HttpMethod.PUT,
    changeNum: NumericChangeId,
    patchNum: PatchSetNum,
    draft: CommentInput
  ): Promise<Response>;

  _sendDiffDraftRequest(
    method: HttpMethod.GET | HttpMethod.DELETE,
    changeNum: NumericChangeId,
    patchNum: PatchSetNum,
    draft: {id?: UrlEncodedCommentId}
  ): Promise<Response>;

  _sendDiffDraftRequest(
    method: HttpMethod,
    changeNum: NumericChangeId,
    patchNum: PatchSetNum,
    draft: CommentInput | {id: UrlEncodedCommentId}
  ): Promise<Response> {
    const isCreate = !draft.id && method === HttpMethod.PUT;
    let endpoint = '/drafts';
    let anonymizedEndpoint = endpoint;
    if (draft.id) {
      endpoint += `/${draft.id}`;
      anonymizedEndpoint += '/*';
    }

    if (!this._pendingRequests[Requests.SEND_DIFF_DRAFT]) {
      this._pendingRequests[Requests.SEND_DIFF_DRAFT] = [];
    }

    const fetchOptions =
      method === HttpMethod.PUT
        ? getFetchOptions({method, body: draft})
        : {method};

    const promise = this._changeBaseURL(changeNum, patchNum).then(url =>
      this._restApiHelper.fetch({
        fetchOptions,
        url: `${url}${endpoint}`,
        anonymizedUrl: `${ANONYMIZED_REVISION_BASE_URL}${anonymizedEndpoint}`,
        reportServerError: true,
      })
    );

    this._pendingRequests[Requests.SEND_DIFF_DRAFT].push(promise);

    if (isCreate) {
      return this._failForCreate200(promise);
    }

    return promise;
  }

  getCommitInfo(
    repo: RepoName,
    commit: CommitId
  ): Promise<CommitInfo | undefined> {
    return this._restApiHelper.fetchJSON({
      url:
        '/projects/' +
        encodeURIComponent(repo) +
        '/commits/' +
        encodeURIComponent(commit),
      anonymizedUrl: '/projects/*/commits/*',
    }) as Promise<CommitInfo | undefined>;
  }

  _fetchB64File(url: string): Promise<Base64File> {
    return this._restApiHelper.fetch({url}).then(response => {
      if (!response.ok) {
        return Promise.reject(new Error(response.statusText));
      }
      const type = response.headers.get('X-FYI-Content-Type');
      return response.text().then(text => {
        return {body: text, type};
      });
    });
  }

  getB64FileContents(
    changeId: NumericChangeId,
    patchNum: RevisionId,
    path: string,
    parentIndex?: number
  ) {
    const parent =
      typeof parentIndex === 'number' ? `?parent=${parentIndex}` : '';
    return this._changeBaseURL(changeId, patchNum).then(url => {
      url = `${url}/files/${encodeURIComponent(path)}/content${parent}`;
      return this._fetchB64File(url);
    });
  }

  getImagesForDiff(
    changeNum: NumericChangeId,
    diff: DiffInfo,
    patchRange: PatchRange
  ): Promise<ImagesForDiff> {
    let promiseA;
    let promiseB;

    if (diff.meta_a?.content_type.startsWith('image/')) {
      if (patchRange.basePatchNum === PARENT) {
        // Note: we only attempt to get the image from the first parent.
        promiseA = this.getB64FileContents(
          changeNum,
          patchRange.patchNum,
          diff.meta_a.name,
          1
        );
      } else {
        promiseA = this.getB64FileContents(
          changeNum,
          patchRange.basePatchNum,
          diff.meta_a.name
        );
      }
    } else {
      promiseA = Promise.resolve(null);
    }

    if (diff.meta_b?.content_type.startsWith('image/')) {
      promiseB = this.getB64FileContents(
        changeNum,
        patchRange.patchNum,
        diff.meta_b.name
      );
    } else {
      promiseB = Promise.resolve(null);
    }

    return Promise.all([promiseA, promiseB]).then(results => {
      // Sometimes the server doesn't send back the content type.
      const baseImage: Base64ImageFile | null =
        results[0] && diff.meta_a
          ? {
              ...results[0],
              _expectedType: diff.meta_a.content_type,
              _name: diff.meta_a.name,
            }
          : null;
      const revisionImage: Base64ImageFile | null =
        results[1] && diff.meta_b
          ? {
              ...results[1],
              _expectedType: diff.meta_b.content_type,
              _name: diff.meta_b.name,
            }
          : null;
      const imagesForDiff: ImagesForDiff = {baseImage, revisionImage};
      return imagesForDiff;
    });
  }

  _changeBaseURL(
    changeNum: NumericChangeId,
    revisionId?: RevisionId
  ): Promise<string> {
    return this.getRepoName(changeNum).then(project => {
      let url = `/changes/${encodeURIComponent(project)}~${changeNum}`;
      if (revisionId) {
        url += `/revisions/${revisionId}`;
      }
      return url;
    });
  }

  async addToAttentionSet(
    changeNum: NumericChangeId,
    user: AccountId | undefined | null,
    reason: string
  ): Promise<Response> {
    const url = await this._changeBaseURL(changeNum);
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.POST,
        body: {user, reason},
      }),
      url: `${url}/attention`,
      anonymizedUrl: `${ANONYMIZED_CHANGE_BASE_URL}/attention`,
      reportServerError: true,
    });
  }

  async removeFromAttentionSet(
    changeNum: NumericChangeId,
    user: AccountId,
    reason: string
  ): Promise<Response> {
    const url = await this._changeBaseURL(changeNum);
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.DELETE,
        body: {reason},
      }),
      url: `${url}/attention/${user}`,
      anonymizedUrl: `${ANONYMIZED_CHANGE_BASE_URL}/attention/*`,
      reportServerError: true,
    });
  }

  async setChangeTopic(
    changeNum: NumericChangeId,
    topic?: string,
    errFn?: ErrorCallback
  ): Promise<string | undefined> {
    const url = await this._changeBaseURL(changeNum);
    const response = await this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: {topic},
      }),
      url: `${url}/topic`,
      anonymizedUrl: `${ANONYMIZED_CHANGE_BASE_URL}/topic`,
      errFn,
    });
    if (!response.ok) {
      return undefined;
    }
    if (response.status === 204) {
      return '';
    }
    return (await readJSONResponsePayload(response))
      .parsed as unknown as string;
  }

  removeChangeTopic(
    changeNum: NumericChangeId,
    errFn?: ErrorCallback
  ): Promise<string | undefined> {
    return this.setChangeTopic(changeNum, '', errFn);
  }

  async setChangeHashtag(
    changeNum: NumericChangeId,
    hashtag: HashtagsInput,
    errFn?: ErrorCallback
  ): Promise<Hashtag[] | undefined> {
    const url = await this._changeBaseURL(changeNum);
    return this._restApiHelper.fetchJSON({
      fetchOptions: getFetchOptions({
        method: HttpMethod.POST,
        body: hashtag,
      }),
      url: `${url}/hashtags`,
      anonymizedUrl: `${ANONYMIZED_CHANGE_BASE_URL}/hashtags`,
      errFn,
    }) as unknown as Promise<Hashtag[] | undefined>;
  }

  getAccountAuthTokens(): Promise<AuthTokenInfo[] | undefined> {
    const errFn: ErrorCallback = (response?: Response | null, _err?: Error) => {
      if (!response || response.status === 405 || response.status === 404) {
        return;
      }
      fireServerError(response, req);
    };
    const req = {
      url: '/accounts/self/tokens',
      reportUrlAsIs: true,
      reportServerError: true,
      errFn,
    };
    return this._restApiHelper.fetchJSON(req) as Promise<
      AuthTokenInfo[] | undefined
    >;
  }

  deleteAccountAuthToken(tokenId: string): Promise<Response> {
    return this._restApiHelper.fetch({
      fetchOptions: {method: HttpMethod.DELETE},
      url: `/accounts/self/tokens/${tokenId}`,
      reportUrlAsIs: true,
      reportServerError: true,
    });
  }

  generateAccountAuthToken(
    tokenId: string,
    lifetime: string
  ): Promise<AuthTokenInfo | undefined> {
    return this._restApiHelper.fetchJSON({
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: {id: tokenId, lifetime},
      }),
      url: `/accounts/self/tokens/${tokenId}`,
      reportUrlAsIs: true,
    }) as Promise<unknown> as Promise<AuthTokenInfo>;
  }

  getAccountSSHKeys() {
    return this._restApiHelper.fetchCacheJSON({
      url: '/accounts/self/sshkeys',
      reportUrlAsIs: true,
    }) as Promise<unknown> as Promise<SshKeyInfo[] | undefined>;
  }

  addAccountSSHKey(key: string): Promise<SshKeyInfo> {
    // By passing throwingErrorCallback we guarantee that response is not-null.
    return this._restApiHelper.fetchJSON({
      fetchOptions: getFetchOptions({
        method: HttpMethod.POST,
        body: key,
        contentType: 'text/plain',
      }),
      url: '/accounts/self/sshkeys',
      reportUrlAsIs: true,
      errFn: throwingErrorCallback,
    }) as Promise<unknown> as Promise<SshKeyInfo>;
  }

  deleteAccountSSHKey(id: string): Promise<Response> {
    return this._restApiHelper.fetch({
      fetchOptions: {method: HttpMethod.DELETE},
      url: '/accounts/self/sshkeys/' + id,
      anonymizedUrl: '/accounts/self/sshkeys/*',
      reportServerError: true,
    });
  }

  getAccountGPGKeys() {
    return this._restApiHelper.fetchJSON({
      url: '/accounts/self/gpgkeys',
      reportUrlAsIs: true,
    }) as Promise<unknown> as Promise<Record<string, GpgKeyInfo>>;
  }

  addAccountGPGKey(key: GpgKeysInput): Promise<Record<string, GpgKeyInfo>> {
    // By passing throwingErrorCallback we guarantee that response is not-null.
    return this._restApiHelper.fetchJSON({
      fetchOptions: getFetchOptions({
        method: HttpMethod.POST,
        body: key,
      }),
      url: '/accounts/self/gpgkeys',
      reportUrlAsIs: true,
      errFn: throwingErrorCallback,
    }) as Promise<unknown> as Promise<Record<string, GpgKeyInfo>>;
  }

  deleteAccountGPGKey(id: GpgKeyId) {
    return this._restApiHelper.fetch({
      fetchOptions: {method: HttpMethod.DELETE},
      url: `/accounts/self/gpgkeys/${id}`,
      anonymizedUrl: '/accounts/self/gpgkeys/*',
      reportServerError: true,
    });
  }

  async deleteVote(
    changeNum: NumericChangeId,
    account: AccountId,
    label: string
  ): Promise<Response> {
    const url = await this._changeBaseURL(changeNum);
    return this._restApiHelper.fetch({
      fetchOptions: {method: HttpMethod.DELETE},
      url: `${url}/reviewers/${account}/votes/${encodeURIComponent(label)}`,
      anonymizedUrl: `${ANONYMIZED_CHANGE_BASE_URL}/reviewers/*/votes/*`,
      reportServerError: true,
    });
  }

  async setDescription(
    changeNum: NumericChangeId,
    patchNum: PatchSetNum,
    desc: string
  ): Promise<Response> {
    const url = await this._changeBaseURL(changeNum, patchNum);
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: {description: desc},
      }),
      url: `${url}/description`,
      anonymizedUrl: `${ANONYMIZED_REVISION_BASE_URL}/description`,
      reportServerError: true,
    });
  }

  async confirmEmail(token: string): Promise<string | null> {
    const response = await this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.PUT,
        body: {token},
      }),
      url: '/config/server/email.confirm',
      reportUrlAsIs: true,
      reportServerError: true,
    });
    if (response?.status === 204) {
      return 'Email confirmed successfully.';
    }
    return null;
  }

  getCapabilities(
    errFn?: ErrorCallback
  ): Promise<CapabilityInfoMap | undefined> {
    return this._restApiHelper.fetchJSON({
      url: '/config/server/capabilities',
      errFn,
      reportUrlAsIs: true,
    }) as Promise<CapabilityInfoMap | undefined>;
  }

  getTopMenus(): Promise<TopMenuEntryInfo[] | undefined> {
    return this._restApiHelper.fetchCacheJSON({
      url: '/config/server/top-menus',
      reportUrlAsIs: true,
    }) as Promise<TopMenuEntryInfo[] | undefined>;
  }

  probePath(path: string) {
    return fetch(new Request(path, {method: HttpMethod.HEAD})).then(
      response => response.ok
    );
  }

  async startWorkInProgress(
    changeNum: NumericChangeId,
    message?: string
  ): Promise<string | undefined> {
    const url = await this._changeBaseURL(changeNum);
    const response = await this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.POST,
        body: message ? {message} : {},
      }),
      url: `${url}/wip`,
      anonymizedUrl: `${ANONYMIZED_CHANGE_BASE_URL}/wip`,
      reportServerError: true,
    });
    if (response.status === 204) {
      return 'Change marked as Work In Progress.';
    }
    return undefined;
  }

  async deleteComment(
    changeNum: NumericChangeId,
    patchNum: PatchSetNum,
    commentID: UrlEncodedCommentId,
    reason: string
  ): Promise<CommentInfo | undefined> {
    const url = await this._changeBaseURL(changeNum, patchNum);
    return this._restApiHelper.fetchJSON({
      fetchOptions: getFetchOptions({
        method: HttpMethod.POST,
        body: {reason},
      }),
      url: `${url}/comments/${commentID}/delete`,
      anonymizedUrl: `${ANONYMIZED_REVISION_BASE_URL}/comments/*/delete`,
    }) as unknown as Promise<CommentInfo | undefined>;
  }

  getChange(
    changeNum: ChangeId | NumericChangeId,
    errFn?: ErrorCallback,
    optionsHex?: string
  ): Promise<ChangeInfo | undefined> {
    if (changeNum in this._projectLookup) {
      // _projectLookup can only store NumericChangeId, so we are sure that
      // changeNum is NumericChangeId in this case.
      return this._changeBaseURL(changeNum as NumericChangeId).then(url =>
        this._restApiHelper.fetchJSON(
          {
            url,
            params: optionsHex ? {O: optionsHex} : undefined,
            errFn,
            anonymizedUrl: '/changes/*~*',
          },
          /* noAcceptHeader */ true
        )
      ) as Promise<ChangeInfo | undefined>;
    } else {
      const params: FetchParams = {q: `change:${changeNum}`};
      if (optionsHex) {
        params['O'] = optionsHex;
      }
      return this._restApiHelper
        .fetchJSON(
          {
            url: '/changes/',
            params,
            errFn,
            anonymizedUrl: '/changes/?q=change:*',
          },
          /* noAcceptHeader */ true
        )
        .then(res => {
          const changeInfos = res as ChangeInfo[] | undefined;
          if (!changeInfos || !changeInfos.length) {
            return undefined;
          }
          return changeInfos[0];
        });
    }
  }

  /**
   * This can be called by the router, if the project can be determined from
   * the URL. Or when handling a dashabord or a search response.
   *
   * Then we don't need to make a dedicated REST API call or have a fallback,
   * if that fails.
   */
  addRepoNameToCache(changeNum: NumericChangeId, project: RepoName) {
    this._projectLookup[changeNum] = Promise.resolve(project);
  }

  getRepoName(changeNum: NumericChangeId): Promise<RepoName> {
    // Hopefully addRepoNameToCache() has already been called. Then we don't
    // have to make a dedicated REST API call to look up the project.
    let projectPromise = this._projectLookup[changeNum];
    if (projectPromise) return projectPromise;

    // Ignore errors, because we have some dedicated fallback logic, see below.
    const onError = () => {};
    projectPromise = this.getChange(changeNum, onError).then(change => {
      if (change?.project) return change.project;

      // In the very rare case that the change index cannot provide an answer
      // (e.g. stale index) we should check, if the router has called
      // addRepoNameToCache() in the meantime. Then we can fall back to that.
      const currentProjectPromise = this._projectLookup[changeNum];
      if (currentProjectPromise && currentProjectPromise !== projectPromise) {
        return currentProjectPromise;
      }

      // No luck. Without knowing the project we cannot proceed at all.
      firePageError(
        new Response(
          `Failed to lookup the repo for change number ${changeNum}`,
          {status: 404}
        )
      );
      // Don't store failed lookups in the lookup.
      this._projectLookup[changeNum] = undefined;
      throw new Error(
        `Failed to lookup the repo for change number ${changeNum}`
      );
    });
    this._projectLookup[changeNum] = projectPromise;
    return projectPromise;
  }

  async executeChangeAction(
    changeNum: NumericChangeId,
    method: HttpMethod | undefined,
    endpoint: string,
    patchNum?: PatchSetNum,
    payload?: RequestPayload,
    errFn?: ErrorCallback
  ): Promise<Response> {
    const url = await this._changeBaseURL(changeNum, patchNum);
    // No anonymizedUrl specified so the request will not be logged.
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method,
        body: payload,
      }),
      url: url + endpoint,
      errFn,
      reportServerError: true,
    });
  }

  async getBlame(
    changeNum: NumericChangeId,
    patchNum: PatchSetNum,
    path: string,
    base?: boolean
  ): Promise<BlameInfo[] | undefined> {
    const encodedPath = encodeURIComponent(path);
    const url = await this._changeBaseURL(changeNum, patchNum);
    return this._restApiHelper.fetchJSON({
      url: `${url}/files/${encodedPath}/blame`,
      params: base ? {base: 't'} : undefined,
      anonymizedUrl: `${ANONYMIZED_REVISION_BASE_URL}/files/*/blame`,
    }) as Promise<BlameInfo[] | undefined>;
  }

  async getPatchContent(
    changeNum: NumericChangeId,
    patchNum: PatchSetNum,
    context?: number,
    errFn?: ErrorCallback
  ): Promise<string | undefined> {
    const url = await this._changeBaseURL(changeNum, patchNum);
    const params: {[key: string]: string | number} = {
      download: '',
      raw: '',
    };
    if (context !== undefined && context !== 3) {
      params['context'] = context;
    }
    const response = await this._restApiHelper.fetch({
      url: `${url}/patch`,
      params,
      anonymizedUrl: `${ANONYMIZED_REVISION_BASE_URL}/patch`,
      errFn,
    });
    if (!response?.ok) return undefined;
    return await response.text();
  }

  /**
   * Modify the given create draft request promise so that it fails and throws
   * an error if the response bears HTTP status 200 instead of HTTP 201.
   *
   * @see Issue 7763
   * @param promise The original promise.
   * @return The modified promise.
   */
  _failForCreate200(promise: Promise<Response>): Promise<Response> {
    return promise.then(result => {
      if (result.status === 200) {
        // Read the response headers into an object representation.
        const headers = Array.from(result.headers.entries()).reduce(
          (obj, [key, val]) => {
            if (!HEADER_REPORTING_BLOCK_REGEX.test(key)) {
              obj[key] = val;
            }
            return obj;
          },
          {} as Record<string, string>
        );
        const err = new Error(
          [
            CREATE_DRAFT_UNEXPECTED_STATUS_MESSAGE,
            JSON.stringify(headers),
          ].join('\n')
        );
        // Throw the error so that it is caught by gr-reporting.
        throw err;
      }
      return result;
    });
  }

  getDashboard(
    repo: RepoName,
    dashboard: DashboardId,
    errFn?: ErrorCallback
  ): Promise<DashboardInfo | undefined> {
    const url =
      '/projects/' +
      encodeURIComponent(repo) +
      '/dashboards/' +
      encodeURIComponent(dashboard);
    return this._restApiHelper.fetchCacheJSON({
      url,
      errFn,
      anonymizedUrl: '/projects/*/dashboards/*',
    }) as Promise<DashboardInfo | undefined>;
  }

  getDocumentationSearches(filter: string): Promise<DocResult[] | undefined> {
    filter = filter.trim();
    const encodedFilter = encodeURIComponent(filter);

    return this._restApiHelper.fetchCacheJSON({
      url: `/Documentation/?q=${encodedFilter}`,
      anonymizedUrl: '/Documentation/?*',
    }) as Promise<DocResult[] | undefined>;
  }

  async getMergeable(
    changeNum: NumericChangeId
  ): Promise<MergeableInfo | undefined> {
    const url = await this._changeBaseURL(changeNum);
    return this._restApiHelper.fetchJSON({
      url: `${url}/revisions/current/mergeable`,
      anonymizedUrl: `${ANONYMIZED_CHANGE_BASE_URL}/revisions/current/mergeable`,
    }) as Promise<MergeableInfo | undefined>;
  }

  deleteDraftComments(query: string): Promise<Response> {
    const body: DeleteDraftCommentsInput = {query};
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method: HttpMethod.POST,
        body,
      }),
      url: '/accounts/self/drafts:delete',
    });
  }

  async getFlow(
    changeNum: NumericChangeId,
    flowId: string,
    errFn?: ErrorCallback
  ): Promise<FlowInfo | undefined> {
    const url = await this._changeBaseURL(changeNum);
    return this._restApiHelper.fetchJSON({
      url: `${url}/flows/${flowId}`,
      errFn,
      anonymizedUrl: `${ANONYMIZED_CHANGE_BASE_URL}/flows/*`,
    }) as Promise<FlowInfo | undefined>;
  }

  async listFlows(
    changeNum: NumericChangeId,
    errFn?: ErrorCallback
  ): Promise<FlowInfo[] | undefined> {
    const url = await this._changeBaseURL(changeNum);
    return this._restApiHelper.fetchJSON({
      url: `${url}/flows`,
      errFn,
      anonymizedUrl: `${ANONYMIZED_CHANGE_BASE_URL}/flows`,
    }) as Promise<FlowInfo[] | undefined>;
  }

  async getIfFlowsIsEnabled(
    changeNum: NumericChangeId,
    errFn?: ErrorCallback
  ): Promise<IsFlowsEnabledInfo | undefined> {
    const url = await this._changeBaseURL(changeNum);
    return this._restApiHelper.fetchJSON({
      url: `${url}/is-flows-enabled`,
      errFn,
      anonymizedUrl: `${ANONYMIZED_CHANGE_BASE_URL}/is-flows-enabled`,
    }) as Promise<IsFlowsEnabledInfo | undefined>;
  }

  async listFlowActions(
    changeNum: NumericChangeId,
    errFn?: ErrorCallback
  ): Promise<FlowActionInfo[] | undefined> {
    const url = await this._changeBaseURL(changeNum);
    return this._restApiHelper.fetchJSON({
      url: `${url}/flows-actions`,
      errFn,
      anonymizedUrl: `${ANONYMIZED_CHANGE_BASE_URL}/flows-actions`,
    }) as Promise<FlowActionInfo[] | undefined>;
  }

  async createFlow(
    changeNum: NumericChangeId,
    flow: FlowInput,
    errFn?: ErrorCallback
  ): Promise<FlowInfo | undefined> {
    const url = await this._changeBaseURL(changeNum);
    return this._restApiHelper.fetchJSON({
      fetchOptions: getFetchOptions({
        method: HttpMethod.POST,
        body: flow,
      }),
      url: `${url}/flows`,
      errFn,
      anonymizedUrl: `${ANONYMIZED_CHANGE_BASE_URL}/flows`,
    }) as Promise<FlowInfo | undefined>;
  }

  async deleteFlow(
    changeNum: NumericChangeId,
    flowId: string,
    errFn?: ErrorCallback
  ): Promise<Response> {
    const url = await this._changeBaseURL(changeNum);
    return this._restApiHelper.fetch({
      fetchOptions: {
        method: HttpMethod.DELETE,
      },
      url: `${url}/flows/${flowId}`,
      errFn,
      anonymizedUrl: `${ANONYMIZED_CHANGE_BASE_URL}/flows/*`,
    });
  }
}
