/**
 * @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,
  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,
  EditInfo,
  EDIT,
  EditPreferencesInfo,
  EmailAddress,
  EmailInfo,
  EncodedGroupId,
  FileNameToFileInfoMap,
  FilePathToDiffInfoMap,
  FixId,
  GitRef,
  GpgKeyId,
  GpgKeyInfo,
  GpgKeysInput,
  GroupAuditEventInfo,
  GroupId,
  GroupInfo,
  GroupInput,
  GroupName,
  GroupNameToGroupInfoMap,
  GroupOptionsInput,
  Hashtag,
  HashtagsInput,
  ImagesForDiff,
  IncludedInInfo,
  MergeableInfo,
  NameToProjectInfoMap,
  NumericChangeId,
  PARENT,
  ParsedJSON,
  Password,
  PatchRange,
  PatchSetNum,
  PathToRobotCommentsInfoMap,
  PluginInfo,
  PreferencesInfo,
  PreferencesInput,
  ProjectAccessInfo,
  RepoAccessInfoMap,
  ProjectAccessInput,
  ProjectInfo,
  ProjectInfoWithName,
  ProjectInput,
  ProjectWatchInfo,
  RelatedChangesInfo,
  RepoName,
  RequestPayload,
  ReviewInput,
  RevisionId,
  ServerInfo,
  SshKeyInfo,
  SubmittedTogetherInfo,
  SuggestedReviewerInfo,
  TagInfo,
  TagInput,
  TopMenuEntryInfo,
  UrlEncodedCommentId,
  DraftInfo,
  ListChangesOption,
  ReviewResult,
} from '../../types/common';
import {
  DiffInfo,
  DiffPreferencesInfo,
  IgnoreWhitespaceType,
} from '../../types/diff';
import {
  GetDiffCommentsOutput,
  GetDiffRobotCommentsOutput,
  RestApiService,
} 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 {FlagsService, KnownExperimentId} from '../flags/flags';
import {RetryScheduler} from '../scheduler/retry-scheduler';
import {FixReplacementInfo} 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.
let fetchPromisesCache = new FetchPromisesCache(); // Shared across instances.
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.

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 = {};
  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,
    private readonly flagService: FlagsService
  ) {
    const readScheduler = createReadScheduler();
    const writeScheduler = createWriteScheduler();
    this._restApiHelper = new GrRestApiHelper(
      this._cache,
      this.authService,
      this._sharedFetchPromises,
      readScheduler,
      writeScheduler
    );
    this._serialScheduler = createSerializingScheduler();
  }

  finalize() {}

  async getResponseObject(response: Response): Promise<ParsedJSON> {
    return (await readJSONResponsePayload(response)).parsed;
  }

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

    return this._restApiHelper.fetchJSON({
      url: '/config/server/info',
      reportUrlAsIs: true,
    }) as Promise<ServerInfo | 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 & {name: string}): Promise<Response> {
    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,
    });
  }

  getGroupAuditLog(
    group: EncodedGroupId,
    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(): Promise<string | undefined> {
    return this._restApiHelper.fetchCacheJSON({
      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(): Promise<AccountDetailInfo | undefined> {
    return this._restApiHelper.fetchCacheJSON({
      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);
    }
  }

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

  /**
   * Depending on an experiment this will either use `getChangesForMultipleQueries()`, which
   * makes just one request to the REST API. Or it will fan out into multiple parallel
   * requests and call `getChanges()` for each query.
   */
  async getChangesForDashboard(
    changesPerPage?: number,
    queries?: string[],
    offset?: 'n,z' | number,
    options?: string
  ): Promise<ChangeInfo[][] | undefined> {
    // CAUTION: Before actually enabling this experiment for everyone we will have to also change
    // the prefetched query in the backend. As is the experiment may help improving the
    // DashboardDisplayed metric, but it will definitely make the *Startup*DashboardDisplayed
    // latency worse.
    const parallelRequests = this.flagService.isEnabled(
      KnownExperimentId.PARALLEL_DASHBOARD_REQUESTS
    );
    if (parallelRequests && queries && queries.length > 1) {
      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[][];
      });
    } else {
      return this.getChangesForMultipleQueries(
        changesPerPage,
        queries,
        offset,
        options
      );
    }
  }

  /**
   * For every query fetches the matching changes.
   *
   * If options is undefined then default options (see getListChangesOptionsHex) is
   * used.
   */
  getChangesForMultipleQueries(
    changesPerPage?: number,
    query?: string[],
    offset?: 'n,z' | number,
    options?: string
  ): Promise<ChangeInfo[][] | undefined> {
    if (!query) return Promise.resolve(undefined);

    const request = this.getRequestForGetChanges(
      changesPerPage,
      query,
      offset,
      options
    );

    return Promise.resolve(
      this._restApiHelper.fetchJSON(request, true) as Promise<
        ChangeInfo[] | ChangeInfo[][] | undefined
      >
    ).then(response => {
      if (!response) {
        return;
      }
      const iterateOverChanges = (arr: ChangeInfo[]) => {
        for (const change of arr) {
          this._maybeInsertInLookup(change);
        }
      };
      // Normalize the response to look like a multi-query response
      // when there is only one query.
      const responseArray: Array<ChangeInfo[]> =
        query.length === 1
          ? [response as ChangeInfo[]]
          : (response as ChangeInfo[][]);
      for (const arr of responseArray) {
        iterateOverChanges(arr);
      }
      return responseArray;
    });
  }

  /**
   * 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[]) {
    const query = changeNums.map(num => `change:${num}`).join(' OR ');
    const changeDetails = await this.getChanges(
      undefined,
      query,
      undefined,
      listChangesOptionsToHex(
        ListChangesOption.CHANGE_ACTIONS,
        ListChangesOption.CURRENT_REVISION,
        ListChangesOption.DETAILED_LABELS,
        // TODO: remove this option and merge requirements from dashboard req
        ListChangesOption.SUBMIT_REQUIREMENTS
      )
    );
    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)
    );
  }

  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;
    }
    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.SUBMITTABLE,
      ListChangesOption.WEB_LINKS,
      ListChangesOption.SKIP_DIFFSTAT,
      ListChangesOption.SUBMIT_REQUIREMENTS,
    ];
    if (this.flagService.isEnabled(KnownExperimentId.REVISION_PARENTS_DATA)) {
      options.push(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 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
    );
  }

  async _getChangeSuggestedGroup(
    reviewerState: ReviewerState,
    changeNum: NumericChangeId,
    inputVal: string,
    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
  ): 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({
        url,
        anonymizedUrl: '/projects/?*',
        errFn,
      }) as Promise<ProjectInfoWithName[] | undefined>;
    } else {
      const result = await (this._restApiHelper.fetchCacheJSON({
        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',
    });
  }

  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
    );
    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
    );
    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
    );
    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',
      'SUBMITTABLE',
      'SKIP_DIFFSTAT',
      'SUBMIT_REQUIREMENTS',
    ];
    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,
      })
    ) 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 url = await this._changeBaseURL(changeNum, patchNum);
    return 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 Promise<FilePathToDiffInfoMap | undefined>;
  }

  async getRobotCommentFixPreview(
    changeNum: NumericChangeId,
    patchNum: PatchSetNum,
    fixId: FixId
  ): Promise<FilePathToDiffInfoMap | undefined> {
    const url = await this._changeBaseURL(changeNum, patchNum);
    const endpoint = `/fixes/${encodeURIComponent(fixId)}/preview`;
    return this._restApiHelper.fetchJSON({
      url: `${url}${endpoint}`,
      anonymizedUrl: `${ANONYMIZED_REVISION_BASE_URL}${endpoint}`,
    }) as Promise<FilePathToDiffInfoMap | undefined>;
  }

  async applyFixSuggestion(
    changeNum: NumericChangeId,
    fixPatchNum: PatchSetNum,
    fixReplacementInfos: FixReplacementInfo[],
    targetPatchNum?: PatchSetNum
  ): 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`,
      reportServerError: true,
    });
  }

  async applyRobotFixSuggestion(
    changeNum: NumericChangeId,
    patchNum: PatchSetNum,
    fixId: string
  ): Promise<Response> {
    const url = await this._changeBaseURL(changeNum, patchNum);
    const endpoint = `/fixes/${encodeURIComponent(fixId)}/apply`;
    return this._restApiHelper.fetch({
      fetchOptions: {method: HttpMethod.POST},
      url: `${url}${endpoint}`,
      anonymizedUrl: `${ANONYMIZED_REVISION_BASE_URL}${endpoint}`,
      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/*',
        })
      );
    });
  }

  send(
    method: HttpMethod,
    url: string,
    body?: RequestPayload,
    errFn?: undefined,
    contentType?: string,
    headers?: Record<string, string>
  ): Promise<Response>;

  send(
    method: HttpMethod,
    url: string,
    body: RequestPayload | undefined,
    errFn: ErrorCallback,
    contentType?: string,
    headers?: Record<string, string>
  ): Promise<Response | undefined>;

  /**
   * Public version of the _restApiHelper.send method preserved for plugins.
   *
   * @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,
    headers?: Record<string, string>
  ): Promise<Response | undefined> {
    return this._restApiHelper.fetch({
      fetchOptions: getFetchOptions({
        method,
        body,
        contentType,
        headers,
      }),
      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
    );
  }

  getDiffRobotComments(
    changeNum: NumericChangeId
  ): Promise<PathToRobotCommentsInfoMap | undefined>;

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

  getDiffRobotComments(
    changeNum: NumericChangeId,
    basePatchNum?: BasePatchSetNum,
    patchNum?: PatchSetNum,
    path?: string
  ) {
    if (!basePatchNum && !patchNum && !path) {
      return this._getDiffComments(changeNum, '/robotcomments');
    }

    return this._getDiffComments(
      changeNum,
      '/robotcomments',
      undefined,
      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: '/robotcomments'
  ): Promise<PathToRobotCommentsInfoMap | undefined>;

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

  _getDiffComments(
    changeNum: NumericChangeId,
    endpoint: '/robotcomments',
    params?: FetchParams,
    basePatchNum?: BasePatchSetNum,
    patchNum?: PatchSetNum,
    path?: string
  ): Promise<GetDiffRobotCommentsOutput>;

  /**
   * 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
    | GetDiffRobotCommentsOutput
    | {[path: string]: CommentInfo[]}
    | PathToRobotCommentsInfoMap
    | 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[]} | PathToRobotCommentsInfoMap | 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>;
  }

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

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

  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
  ): 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,
            errFn,
            anonymizedUrl: '/changes/*~*',
          },
          /* noAcceptHeader */ true
        )
      ) as Promise<ChangeInfo | undefined>;
    } else {
      return this._restApiHelper
        .fetchJSON(
          {
            url: `/changes/?q=change:${changeNum}`,
            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>;
  }

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