/**
 * @license
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/* NB: Order is important, because of namespaced classes. */

import {mixinBehaviors} from '@polymer/polymer/lib/legacy/class.js';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
import {PolymerElement} from '@polymer/polymer/polymer-element.js';
import {PatchSetBehavior} from '../../../behaviors/gr-patch-set-behavior/gr-patch-set-behavior.js';
import {PathListBehavior} from '../../../behaviors/gr-path-list-behavior/gr-path-list-behavior.js';
import {RESTClientBehavior} from '../../../behaviors/rest-client-behavior/rest-client-behavior.js';
import {GrEtagDecorator} from './gr-etag-decorator.js';
import {SiteBasedCache, FetchPromisesCache, GrRestApiHelper} from './gr-rest-apis/gr-rest-api-helper.js';
import {GrReviewerUpdatesParser} from './gr-reviewer-updates-parser.js';
import {parseDate} from '../../../utils/date-util.js';
import {authService} from './gr-auth.js';

const DiffViewMode = {
  SIDE_BY_SIDE: 'SIDE_BY_SIDE',
  UNIFIED: 'UNIFIED_DIFF',
};
const JSON_PREFIX = ')]}\'';
const MAX_PROJECT_RESULTS = 25;
// This value is somewhat arbitrary and not based on research or calculations.
const MAX_UNIFIED_DEFAULT_WINDOW_WIDTH_PX = 850;
const PARENT_PATCH_NUM = 'PARENT';

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_BLACKLIST = /^set-cookie$/i;

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

/**
 * @extends PolymerElement
 */
class GrRestApiInterface extends mixinBehaviors( [
  PathListBehavior,
  PatchSetBehavior,
  RESTClientBehavior,
], GestureEventListeners(
    LegacyElementMixin(
        PolymerElement))) {
  static get is() { return 'gr-rest-api-interface'; }
  /**
   * Fired when an server error occurs.
   *
   * @event server-error
   */

  /**
   * Fired when a network error occurs.
   *
   * @event network-error
   */

  /**
   * Fired after an RPC completes.
   *
   * @event rpc-log
   */

  constructor() {
    super();
    this.JSON_PREFIX = JSON_PREFIX;
  }

  static get properties() {
    return {
      _cache: {
        type: Object,
        value: new SiteBasedCache(), // Shared across instances.
      },
      _sharedFetchPromises: {
        type: Object,
        value: new FetchPromisesCache(), // Shared across instances.
      },
      _pendingRequests: {
        type: Object,
        value: {}, // Intentional to share the object across instances.
      },
      _etags: {
        type: Object,
        value: new GrEtagDecorator(), // Share across instances.
      },
      /**
       * Used to maintain a mapping of changeNums to project names.
       */
      _projectLookup: {
        type: Object,
        value: {}, // Intentional to share the object across instances.
      },
    };
  }

  /** @override */
  created() {
    super.created();
    this._auth = authService;
    this._initRestApiHelper();
  }

  _initRestApiHelper() {
    if (this._restApiHelper) {
      return;
    }
    if (this._cache && this._auth && this._sharedFetchPromises) {
      this._restApiHelper = new GrRestApiHelper(this._cache, this._auth,
          this._sharedFetchPromises, this);
    }
  }

  _fetchSharedCacheURL(req) {
    // Cache is shared across instances
    return this._restApiHelper.fetchCacheURL(req);
  }

  /**
   * @param {!Object} response
   * @return {?}
   */
  getResponseObject(response) {
    return this._restApiHelper.getResponseObject(response);
  }

  getConfig(noCache) {
    if (!noCache) {
      return this._fetchSharedCacheURL({
        url: '/config/server/info',
        reportUrlAsIs: true,
      });
    }

    return this._restApiHelper.fetchJSON({
      url: '/config/server/info',
      reportUrlAsIs: true,
    });
  }

  getRepo(repo, opt_errFn) {
    // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
    // supports it.
    return this._fetchSharedCacheURL({
      url: '/projects/' + encodeURIComponent(repo),
      errFn: opt_errFn,
      anonymizedUrl: '/projects/*',
    });
  }

  getProjectConfig(repo, opt_errFn) {
    // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
    // supports it.
    return this._fetchSharedCacheURL({
      url: '/projects/' + encodeURIComponent(repo) + '/config',
      errFn: opt_errFn,
      anonymizedUrl: '/projects/*/config',
    });
  }

  getRepoAccess(repo) {
    // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
    // supports it.
    return this._fetchSharedCacheURL({
      url: '/access/?project=' + encodeURIComponent(repo),
      anonymizedUrl: '/access/?project=*',
    });
  }

  getRepoDashboards(repo, opt_errFn) {
    // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
    // supports it.
    return this._fetchSharedCacheURL({
      url: `/projects/${encodeURIComponent(repo)}/dashboards?inherited`,
      errFn: opt_errFn,
      anonymizedUrl: '/projects/*/dashboards?inherited',
    });
  }

  saveRepoConfig(repo, config, opt_errFn) {
    // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
    // supports it.
    const url = `/projects/${encodeURIComponent(repo)}/config`;
    this._cache.delete(url);
    return this._restApiHelper.send({
      method: 'PUT',
      url,
      body: config,
      errFn: opt_errFn,
      anonymizedUrl: '/projects/*/config',
    });
  }

  runRepoGC(repo, opt_errFn) {
    if (!repo) { return ''; }
    // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
    // supports it.
    const encodeName = encodeURIComponent(repo);
    return this._restApiHelper.send({
      method: 'POST',
      url: `/projects/${encodeName}/gc`,
      body: '',
      errFn: opt_errFn,
      anonymizedUrl: '/projects/*/gc',
    });
  }

  /**
   * @param {?Object} config
   * @param {function(?Response, string=)=} opt_errFn
   */
  createRepo(config, opt_errFn) {
    if (!config.name) { return ''; }
    // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
    // supports it.
    const encodeName = encodeURIComponent(config.name);
    return this._restApiHelper.send({
      method: 'PUT',
      url: `/projects/${encodeName}`,
      body: config,
      errFn: opt_errFn,
      anonymizedUrl: '/projects/*',
    });
  }

  /**
   * @param {?Object} config
   * @param {function(?Response, string=)=} opt_errFn
   */
  createGroup(config, opt_errFn) {
    if (!config.name) { return ''; }
    const encodeName = encodeURIComponent(config.name);
    return this._restApiHelper.send({
      method: 'PUT',
      url: `/groups/${encodeName}`,
      body: config,
      errFn: opt_errFn,
      anonymizedUrl: '/groups/*',
    });
  }

  getGroupConfig(group, opt_errFn) {
    return this._restApiHelper.fetchJSON({
      url: `/groups/${encodeURIComponent(group)}/detail`,
      errFn: opt_errFn,
      anonymizedUrl: '/groups/*/detail',
    });
  }

  /**
   * @param {string} repo
   * @param {string} ref
   * @param {function(?Response, string=)=} opt_errFn
   */
  deleteRepoBranches(repo, ref, opt_errFn) {
    if (!repo || !ref) { return ''; }
    // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
    // supports it.
    const encodeName = encodeURIComponent(repo);
    const encodeRef = encodeURIComponent(ref);
    return this._restApiHelper.send({
      method: 'DELETE',
      url: `/projects/${encodeName}/branches/${encodeRef}`,
      body: '',
      errFn: opt_errFn,
      anonymizedUrl: '/projects/*/branches/*',
    });
  }

  /**
   * @param {string} repo
   * @param {string} ref
   * @param {function(?Response, string=)=} opt_errFn
   */
  deleteRepoTags(repo, ref, opt_errFn) {
    if (!repo || !ref) { return ''; }
    // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
    // supports it.
    const encodeName = encodeURIComponent(repo);
    const encodeRef = encodeURIComponent(ref);
    return this._restApiHelper.send({
      method: 'DELETE',
      url: `/projects/${encodeName}/tags/${encodeRef}`,
      body: '',
      errFn: opt_errFn,
      anonymizedUrl: '/projects/*/tags/*',
    });
  }

  /**
   * @param {string} name
   * @param {string} branch
   * @param {string} revision
   * @param {function(?Response, string=)=} opt_errFn
   */
  createRepoBranch(name, branch, revision, opt_errFn) {
    if (!name || !branch || !revision) { return ''; }
    // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
    // supports it.
    const encodeName = encodeURIComponent(name);
    const encodeBranch = encodeURIComponent(branch);
    return this._restApiHelper.send({
      method: 'PUT',
      url: `/projects/${encodeName}/branches/${encodeBranch}`,
      body: revision,
      errFn: opt_errFn,
      anonymizedUrl: '/projects/*/branches/*',
    });
  }

  /**
   * @param {string} name
   * @param {string} tag
   * @param {string} revision
   * @param {function(?Response, string=)=} opt_errFn
   */
  createRepoTag(name, tag, revision, opt_errFn) {
    if (!name || !tag || !revision) { return ''; }
    // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
    // supports it.
    const encodeName = encodeURIComponent(name);
    const encodeTag = encodeURIComponent(tag);
    return this._restApiHelper.send({
      method: 'PUT',
      url: `/projects/${encodeName}/tags/${encodeTag}`,
      body: revision,
      errFn: opt_errFn,
      anonymizedUrl: '/projects/*/tags/*',
    });
  }

  /**
   * @param {!string} groupName
   * @returns {!Promise<boolean>}
   */
  getIsGroupOwner(groupName) {
    const encodeName = encodeURIComponent(groupName);
    const req = {
      url: `/groups/?owned&g=${encodeName}`,
      anonymizedUrl: '/groups/owned&g=*',
    };
    return this._fetchSharedCacheURL(req)
        .then(configs => configs.hasOwnProperty(groupName));
  }

  getGroupMembers(groupName, opt_errFn) {
    const encodeName = encodeURIComponent(groupName);
    return this._restApiHelper.fetchJSON({
      url: `/groups/${encodeName}/members/`,
      errFn: opt_errFn,
      anonymizedUrl: '/groups/*/members',
    });
  }

  getIncludedGroup(groupName) {
    return this._restApiHelper.fetchJSON({
      url: `/groups/${encodeURIComponent(groupName)}/groups/`,
      anonymizedUrl: '/groups/*/groups',
    });
  }

  saveGroupName(groupId, name) {
    const encodeId = encodeURIComponent(groupId);
    return this._restApiHelper.send({
      method: 'PUT',
      url: `/groups/${encodeId}/name`,
      body: {name},
      anonymizedUrl: '/groups/*/name',
    });
  }

  saveGroupOwner(groupId, ownerId) {
    const encodeId = encodeURIComponent(groupId);
    return this._restApiHelper.send({
      method: 'PUT',
      url: `/groups/${encodeId}/owner`,
      body: {owner: ownerId},
      anonymizedUrl: '/groups/*/owner',
    });
  }

  saveGroupDescription(groupId, description) {
    const encodeId = encodeURIComponent(groupId);
    return this._restApiHelper.send({
      method: 'PUT',
      url: `/groups/${encodeId}/description`,
      body: {description},
      anonymizedUrl: '/groups/*/description',
    });
  }

  saveGroupOptions(groupId, options) {
    const encodeId = encodeURIComponent(groupId);
    return this._restApiHelper.send({
      method: 'PUT',
      url: `/groups/${encodeId}/options`,
      body: options,
      anonymizedUrl: '/groups/*/options',
    });
  }

  getGroupAuditLog(group, opt_errFn) {
    return this._fetchSharedCacheURL({
      url: '/groups/' + group + '/log.audit',
      errFn: opt_errFn,
      anonymizedUrl: '/groups/*/log.audit',
    });
  }

  saveGroupMembers(groupName, groupMembers) {
    const encodeName = encodeURIComponent(groupName);
    const encodeMember = encodeURIComponent(groupMembers);
    return this._restApiHelper.send({
      method: 'PUT',
      url: `/groups/${encodeName}/members/${encodeMember}`,
      parseResponse: true,
      anonymizedUrl: '/groups/*/members/*',
    });
  }

  saveIncludedGroup(groupName, includedGroup, opt_errFn) {
    const encodeName = encodeURIComponent(groupName);
    const encodeIncludedGroup = encodeURIComponent(includedGroup);
    const req = {
      method: 'PUT',
      url: `/groups/${encodeName}/groups/${encodeIncludedGroup}`,
      errFn: opt_errFn,
      anonymizedUrl: '/groups/*/groups/*',
    };
    return this._restApiHelper.send(req).then(response => {
      if (response.ok) {
        return this.getResponseObject(response);
      }
    });
  }

  deleteGroupMembers(groupName, groupMembers) {
    const encodeName = encodeURIComponent(groupName);
    const encodeMember = encodeURIComponent(groupMembers);
    return this._restApiHelper.send({
      method: 'DELETE',
      url: `/groups/${encodeName}/members/${encodeMember}`,
      anonymizedUrl: '/groups/*/members/*',
    });
  }

  deleteIncludedGroup(groupName, includedGroup) {
    const encodeName = encodeURIComponent(groupName);
    const encodeIncludedGroup = encodeURIComponent(includedGroup);
    return this._restApiHelper.send({
      method: 'DELETE',
      url: `/groups/${encodeName}/groups/${encodeIncludedGroup}`,
      anonymizedUrl: '/groups/*/groups/*',
    });
  }

  getVersion() {
    return this._fetchSharedCacheURL({
      url: '/config/server/version',
      reportUrlAsIs: true,
    });
  }

  getDiffPreferences() {
    return this.getLoggedIn().then(loggedIn => {
      if (loggedIn) {
        return this._fetchSharedCacheURL({
          url: '/accounts/self/preferences.diff',
          reportUrlAsIs: true,
        });
      }
      // These defaults should match the defaults in
      // java/com/google/gerrit/extensions/client/DiffPreferencesInfo.java
      // NOTE: There are some settings that don't apply to PolyGerrit
      // (Render mode being at least one of them).
      return Promise.resolve({
        auto_hide_diff_table_header: true,
        context: 10,
        cursor_blink_rate: 0,
        font_size: 12,
        ignore_whitespace: 'IGNORE_NONE',
        intraline_difference: true,
        line_length: 100,
        line_wrapping: false,
        show_line_endings: true,
        show_tabs: true,
        show_whitespace_errors: true,
        syntax_highlighting: true,
        tab_size: 8,
        theme: 'DEFAULT',
      });
    });
  }

  getEditPreferences() {
    return this.getLoggedIn().then(loggedIn => {
      if (loggedIn) {
        return this._fetchSharedCacheURL({
          url: '/accounts/self/preferences.edit',
          reportUrlAsIs: true,
        });
      }
      // These defaults should match the defaults in
      // java/com/google/gerrit/extensions/client/EditPreferencesInfo.java
      return Promise.resolve({
        auto_close_brackets: false,
        cursor_blink_rate: 0,
        hide_line_numbers: false,
        hide_top_menu: false,
        indent_unit: 2,
        indent_with_tabs: false,
        key_map_type: 'DEFAULT',
        line_length: 100,
        line_wrapping: false,
        match_brackets: true,
        show_base: false,
        show_tabs: true,
        show_whitespace_errors: true,
        syntax_highlighting: true,
        tab_size: 8,
        theme: 'DEFAULT',
      });
    });
  }

  /**
   * @param {?Object} prefs
   * @param {function(?Response, string=)=} opt_errFn
   */
  savePreferences(prefs, opt_errFn) {
    // 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.send({
      method: 'PUT',
      url: '/accounts/self/preferences',
      body: prefs,
      errFn: opt_errFn,
      reportUrlAsIs: true,
    });
  }

  /**
   * @param {?Object} prefs
   * @param {function(?Response, string=)=} opt_errFn
   */
  saveDiffPreferences(prefs, opt_errFn) {
    // Invalidate the cache.
    this._cache.delete('/accounts/self/preferences.diff');
    return this._restApiHelper.send({
      method: 'PUT',
      url: '/accounts/self/preferences.diff',
      body: prefs,
      errFn: opt_errFn,
      reportUrlAsIs: true,
    });
  }

  /**
   * @param {?Object} prefs
   * @param {function(?Response, string=)=} opt_errFn
   */
  saveEditPreferences(prefs, opt_errFn) {
    // Invalidate the cache.
    this._cache.delete('/accounts/self/preferences.edit');
    return this._restApiHelper.send({
      method: 'PUT',
      url: '/accounts/self/preferences.edit',
      body: prefs,
      errFn: opt_errFn,
      reportUrlAsIs: true,
    });
  }

  getAccount() {
    return this._fetchSharedCacheURL({
      url: '/accounts/self/detail',
      reportUrlAsIs: true,
      errFn: resp => {
        if (!resp || resp.status === 403) {
          this._cache.delete('/accounts/self/detail');
        }
      },
    });
  }

  getAvatarChangeUrl() {
    return this._fetchSharedCacheURL({
      url: '/accounts/self/avatar.change.url',
      reportUrlAsIs: true,
      errFn: resp => {
        if (!resp || resp.status === 403) {
          this._cache.delete('/accounts/self/avatar.change.url');
        }
      },
    });
  }

  getExternalIds() {
    return this._restApiHelper.fetchJSON({
      url: '/accounts/self/external.ids',
      reportUrlAsIs: true,
    });
  }

  deleteAccountIdentity(id) {
    return this._restApiHelper.send({
      method: 'POST',
      url: '/accounts/self/external.ids:delete',
      body: id,
      parseResponse: true,
      reportUrlAsIs: true,
    });
  }

  /**
   * @param {string} userId the ID of the user usch as an email address.
   * @return {!Promise<!Object>}
   */
  getAccountDetails(userId) {
    return this._restApiHelper.fetchJSON({
      url: `/accounts/${encodeURIComponent(userId)}/detail`,
      anonymizedUrl: '/accounts/*/detail',
    });
  }

  getAccountEmails() {
    return this._fetchSharedCacheURL({
      url: '/accounts/self/emails',
      reportUrlAsIs: true,
    });
  }

  /**
   * @param {string} email
   * @param {function(?Response, string=)=} opt_errFn
   */
  addAccountEmail(email, opt_errFn) {
    return this._restApiHelper.send({
      method: 'PUT',
      url: '/accounts/self/emails/' + encodeURIComponent(email),
      errFn: opt_errFn,
      anonymizedUrl: '/account/self/emails/*',
    });
  }

  /**
   * @param {string} email
   * @param {function(?Response, string=)=} opt_errFn
   */
  deleteAccountEmail(email, opt_errFn) {
    return this._restApiHelper.send({
      method: 'DELETE',
      url: '/accounts/self/emails/' + encodeURIComponent(email),
      errFn: opt_errFn,
      anonymizedUrl: '/accounts/self/email/*',
    });
  }

  /**
   * @param {string} email
   * @param {function(?Response, string=)=} opt_errFn
   */
  setPreferredAccountEmail(email, opt_errFn) {
    const encodedEmail = encodeURIComponent(email);
    const req = {
      method: 'PUT',
      url: `/accounts/self/emails/${encodedEmail}/preferred`,
      errFn: opt_errFn,
      anonymizedUrl: '/accounts/self/emails/*/preferred',
    };
    return this._restApiHelper.send(req).then(() => {
      // 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');
      if (cachedEmails) {
        const emails = cachedEmails.map(entry => {
          if (entry.email === email) {
            return {email, preferred: true};
          } else {
            return {email};
          }
        });
        this._cache.set('/accounts/self/emails', emails);
      }
    });
  }

  /**
   * @param {?Object} obj
   */
  _updateCachedAccount(obj) {
    // 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',
          Object.assign({}, cachedAccount, obj));
    }
  }

  /**
   * @param {string} name
   * @param {function(?Response, string=)=} opt_errFn
   */
  setAccountName(name, opt_errFn) {
    const req = {
      method: 'PUT',
      url: '/accounts/self/name',
      body: {name},
      errFn: opt_errFn,
      parseResponse: true,
      reportUrlAsIs: true,
    };
    return this._restApiHelper.send(req)
        .then(newName => this._updateCachedAccount({name: newName}));
  }

  /**
   * @param {string} username
   * @param {function(?Response, string=)=} opt_errFn
   */
  setAccountUsername(username, opt_errFn) {
    const req = {
      method: 'PUT',
      url: '/accounts/self/username',
      body: {username},
      errFn: opt_errFn,
      parseResponse: true,
      reportUrlAsIs: true,
    };
    return this._restApiHelper.send(req)
        .then(newName => this._updateCachedAccount({username: newName}));
  }

  /**
   * @param {string} displayName
   * @param {function(?Response, string=)=} opt_errFn
   */
  setAccountDisplayName(displayName, opt_errFn) {
    const req = {
      method: 'PUT',
      url: '/accounts/self/displayname',
      body: {display_name: displayName},
      errFn: opt_errFn,
      parseResponse: true,
      reportUrlAsIs: true,
    };
    return this._restApiHelper.send(req)
        .then(newName => this._updateCachedAccount({displayName: newName}));
  }

  /**
   * @param {string} status
   * @param {function(?Response, string=)=} opt_errFn
   */
  setAccountStatus(status, opt_errFn) {
    const req = {
      method: 'PUT',
      url: '/accounts/self/status',
      body: {status},
      errFn: opt_errFn,
      parseResponse: true,
      reportUrlAsIs: true,
    };
    return this._restApiHelper.send(req)
        .then(newStatus => this._updateCachedAccount({status: newStatus}));
  }

  getAccountStatus(userId) {
    return this._restApiHelper.fetchJSON({
      url: `/accounts/${encodeURIComponent(userId)}/status`,
      anonymizedUrl: '/accounts/*/status',
    });
  }

  getAccountGroups() {
    return this._restApiHelper.fetchJSON({
      url: '/accounts/self/groups',
      reportUrlAsIs: true,
    });
  }

  getAccountAgreements() {
    return this._restApiHelper.fetchJSON({
      url: '/accounts/self/agreements',
      reportUrlAsIs: true,
    });
  }

  saveAccountAgreement(name) {
    return this._restApiHelper.send({
      method: 'PUT',
      url: '/accounts/self/agreements',
      body: name,
      reportUrlAsIs: true,
    });
  }

  /**
   * @param {string=} opt_params
   */
  getAccountCapabilities(opt_params) {
    let queryString = '';
    if (opt_params) {
      queryString = '?q=' + opt_params
          .map(param => encodeURIComponent(param))
          .join('&q=');
    }
    return this._fetchSharedCacheURL({
      url: '/accounts/self/capabilities' + queryString,
      anonymizedUrl: '/accounts/self/capabilities?q=*',
    });
  }

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

  getIsAdmin() {
    return this.getLoggedIn()
        .then(isLoggedIn => {
          if (isLoggedIn) {
            return this.getAccountCapabilities();
          } else {
            return Promise.resolve();
          }
        })
        .then(
            capabilities => capabilities && capabilities.administrateServer
        );
  }

  getDefaultPreferences() {
    return this._fetchSharedCacheURL({
      url: '/config/server/preferences',
      reportUrlAsIs: true,
    });
  }

  getPreferences() {
    return this.getLoggedIn().then(loggedIn => {
      if (loggedIn) {
        const req = {url: '/accounts/self/preferences', reportUrlAsIs: true};
        return this._fetchSharedCacheURL(req).then(res => {
          if (this._isNarrowScreen()) {
            // Note that this can be problematic, because the diff will stay
            // unified even after increasing the window width.
            res.default_diff_view = DiffViewMode.UNIFIED;
          } else {
            res.default_diff_view = res.diff_view;
          }
          return Promise.resolve(res);
        });
      }

      return Promise.resolve({
        changes_per_page: 25,
        default_diff_view: this._isNarrowScreen() ?
          DiffViewMode.UNIFIED : DiffViewMode.SIDE_BY_SIDE,
        diff_view: 'SIDE_BY_SIDE',
        size_bar_in_change_table: true,
      });
    });
  }

  getWatchedProjects() {
    return this._fetchSharedCacheURL({
      url: '/accounts/self/watched.projects',
      reportUrlAsIs: true,
    });
  }

  /**
   * @param {string} projects
   * @param {function(?Response, string=)=} opt_errFn
   */
  saveWatchedProjects(projects, opt_errFn) {
    return this._restApiHelper.send({
      method: 'POST',
      url: '/accounts/self/watched.projects',
      body: projects,
      errFn: opt_errFn,
      parseResponse: true,
      reportUrlAsIs: true,
    });
  }

  /**
   * @param {string} projects
   * @param {function(?Response, string=)=} opt_errFn
   */
  deleteWatchedProjects(projects, opt_errFn) {
    return this._restApiHelper.send({
      method: 'POST',
      url: '/accounts/self/watched.projects:delete',
      body: projects,
      errFn: opt_errFn,
      reportUrlAsIs: true,
    });
  }

  _isNarrowScreen() {
    return window.innerWidth < MAX_UNIFIED_DEFAULT_WINDOW_WIDTH_PX;
  }

  /**
   * @param {number=} opt_changesPerPage
   * @param {string|!Array<string>=} opt_query A query or an array of queries.
   * @param {number|string=} opt_offset
   * @param {!Object=} opt_options
   * @return {?Array<!Object>|?Array<!Array<!Object>>} If opt_query is an
   *     array, _fetchJSON will return an array of arrays of changeInfos. If it
   *     is unspecified or a string, _fetchJSON will return an array of
   *     changeInfos.
   */
  getChanges(opt_changesPerPage, opt_query, opt_offset, opt_options) {
    return this.getConfig(false)
        .then(config => {
          const options = opt_options || this._getChangesOptionsHex(config);
          // Issue 4524: respect legacy token with max sortkey.
          if (opt_offset === 'n,z') {
            opt_offset = 0;
          }
          const params = {
            O: options,
            S: opt_offset || 0,
          };
          if (opt_changesPerPage) { params.n = opt_changesPerPage; }
          if (opt_query && opt_query.length > 0) {
            params.q = opt_query;
          }
          return {
            url: '/changes/',
            params,
            reportUrlAsIs: true,
          };
        })
        .then(req => this._restApiHelper.fetchJSON(req))
        .then(response => {
          const iterateOverChanges = arr => {
            for (const change of (arr || [])) {
              this._maybeInsertInLookup(change);
            }
          };
          // Response may be an array of changes OR an array of arrays of
          // changes.
          if (opt_query instanceof Array) {
            // Normalize the response to look like a multi-query response
            // when there is only one query.
            if (opt_query.length === 1) {
              response = [response];
            }
            for (const arr of response) {
              iterateOverChanges(arr);
            }
          } else {
            iterateOverChanges(response);
          }
          return response;
        });
  }

  /**
   * Inserts a change into _projectLookup iff it has a valid structure.
   *
   * @param {?{ _number: (number|string) }} change
   */
  _maybeInsertInLookup(change) {
    if (change && change.project && change._number) {
      this.setInProjectLookup(change._number, change.project);
    }
  }

  /**
   * TODO (beckysiegel) this needs to be rewritten with the optional param
   * at the end.
   *
   * @param {number|string} changeNum
   * @param {?number|string=} opt_patchNum passed as null sometimes.
   * @param {?=} endpoint
   * @return {!Promise<string>}
   */
  getChangeActionURL(changeNum, opt_patchNum, endpoint) {
    return this._changeBaseURL(changeNum, opt_patchNum)
        .then(url => url + endpoint);
  }

  /**
   * @param {number|string} changeNum
   * @param {function(?Response, string=)=} opt_errFn
   * @param {function()=} opt_cancelCondition
   */
  getChangeDetail(changeNum, opt_errFn, opt_cancelCondition) {
    return this.getConfig(false).then(config => {
      const optionsHex = this._getChangeOptionsHex(config);
      return this._getChangeDetail(
          changeNum, optionsHex, opt_errFn, opt_cancelCondition)
          .then(GrReviewerUpdatesParser.parse);
    });
  }

  _getChangesOptionsHex(config) {
    const options = [
      this.ListChangesOption.LABELS,
      this.ListChangesOption.DETAILED_ACCOUNTS,
    ];
    if (config && config.change && config.change.enable_attention_set) {
      options.push(this.ListChangesOption.DETAILED_LABELS);
    } else {
      options.push(this.ListChangesOption.REVIEWED);
    }

    return this.listChangesOptionsToHex(...options);
  }

  _getChangeOptionsHex(config) {
    if (window.DEFAULT_DETAIL_HEXES && window.DEFAULT_DETAIL_HEXES.changePage
        && !(config.receive && config.receive.enable_signed_push)) {
      return window.DEFAULT_DETAIL_HEXES.changePage;
    }

    // This list MUST be kept in sync with
    // ChangeIT#changeDetailsDoesNotRequireIndex
    const options = [
      this.ListChangesOption.ALL_COMMITS,
      this.ListChangesOption.ALL_REVISIONS,
      this.ListChangesOption.CHANGE_ACTIONS,
      this.ListChangesOption.DETAILED_LABELS,
      this.ListChangesOption.DOWNLOAD_COMMANDS,
      this.ListChangesOption.MESSAGES,
      this.ListChangesOption.SUBMITTABLE,
      this.ListChangesOption.WEB_LINKS,
      this.ListChangesOption.SKIP_DIFFSTAT,
    ];
    if (config.receive && config.receive.enable_signed_push) {
      options.push(this.ListChangesOption.PUSH_CERTIFICATES);
    }
    return this.listChangesOptionsToHex(...options);
  }

  /**
   * @param {number|string} changeNum
   * @param {function(?Response, string=)=} opt_errFn
   * @param {function()=} opt_cancelCondition
   */
  getDiffChangeDetail(changeNum, opt_errFn, opt_cancelCondition) {
    let optionsHex = '';
    if (window.DEFAULT_DETAIL_HEXES && window.DEFAULT_DETAIL_HEXES.diffPage) {
      optionsHex = window.DEFAULT_DETAIL_HEXES.diffPage;
    } else {
      optionsHex = this.listChangesOptionsToHex(
          this.ListChangesOption.ALL_COMMITS,
          this.ListChangesOption.ALL_REVISIONS,
          this.ListChangesOption.SKIP_DIFFSTAT
      );
    }
    return this._getChangeDetail(changeNum, optionsHex, opt_errFn,
        opt_cancelCondition);
  }

  /**
   * @param {number|string} changeNum
   * @param {string|undefined} optionsHex list changes options in hex
   * @param {function(?Response, string=)=} opt_errFn
   * @param {function()=} opt_cancelCondition
   */
  _getChangeDetail(changeNum, optionsHex, opt_errFn, opt_cancelCondition) {
    return this.getChangeActionURL(changeNum, null, '/detail').then(url => {
      const urlWithParams = this._restApiHelper
          .urlWithParams(url, optionsHex);
      const params = {O: optionsHex};
      const req = {
        url,
        errFn: opt_errFn,
        cancelCondition: opt_cancelCondition,
        params,
        fetchOptions: this._etags.getOptions(urlWithParams),
        anonymizedUrl: '/changes/*~*/detail?O=' + optionsHex,
      };
      return this._restApiHelper.fetchRawJSON(req).then(response => {
        if (response && response.status === 304) {
          return Promise.resolve(this._restApiHelper.parsePrefixedJSON(
              this._etags.getCachedPayload(urlWithParams)));
        }

        if (response && !response.ok) {
          if (opt_errFn) {
            opt_errFn.call(null, response);
          } else {
            this.dispatchEvent(new CustomEvent('server-error', {
              detail: {request: req, response},
              composed: true, bubbles: true,
            }));
          }
          return;
        }

        const payloadPromise = response ?
          this._restApiHelper.readResponsePayload(response) :
          Promise.resolve(null);

        return payloadPromise.then(payload => {
          if (!payload) { return null; }
          this._etags.collect(urlWithParams, response, payload.raw);
          this._maybeInsertInLookup(payload.parsed);

          return payload.parsed;
        });
      });
    });
  }

  /**
   * @param {number|string} changeNum
   * @param {number|string} patchNum
   */
  getChangeCommitInfo(changeNum, patchNum) {
    return this._getChangeURLAndFetch({
      changeNum,
      endpoint: '/commit?links',
      patchNum,
      reportEndpointAsIs: true,
    });
  }

  /**
   * @param {number|string} changeNum
   * @param {Gerrit.PatchRange} patchRange
   * @param {number=} opt_parentIndex
   */
  getChangeFiles(changeNum, patchRange, opt_parentIndex) {
    let params = undefined;
    if (this.isMergeParent(patchRange.basePatchNum)) {
      params = {parent: this.getParentIndex(patchRange.basePatchNum)};
    } else if (!this.patchNumEquals(patchRange.basePatchNum, 'PARENT')) {
      params = {base: patchRange.basePatchNum};
    }
    return this._getChangeURLAndFetch({
      changeNum,
      endpoint: '/files',
      patchNum: patchRange.patchNum,
      params,
      reportEndpointAsIs: true,
    });
  }

  /**
   * @param {number|string} changeNum
   * @param {Gerrit.PatchRange} patchRange
   */
  getChangeEditFiles(changeNum, patchRange) {
    let endpoint = '/edit?list';
    let anonymizedEndpoint = endpoint;
    if (patchRange.basePatchNum !== 'PARENT') {
      endpoint += '&base=' + encodeURIComponent(patchRange.basePatchNum + '');
      anonymizedEndpoint += '&base=*';
    }
    return this._getChangeURLAndFetch({
      changeNum,
      endpoint,
      anonymizedEndpoint,
    });
  }

  /**
   * @param {number|string} changeNum
   * @param {number|string} patchNum
   * @param {string} query
   * @return {!Promise<!Object>}
   */
  queryChangeFiles(changeNum, patchNum, query) {
    return this._getChangeURLAndFetch({
      changeNum,
      endpoint: `/files?q=${encodeURIComponent(query)}`,
      patchNum,
      anonymizedEndpoint: '/files?q=*',
    });
  }

  /**
   * @param {number|string} changeNum
   * @param {Gerrit.PatchRange} patchRange
   * @return {!Promise<!Array<!Object>>}
   */
  getChangeOrEditFiles(changeNum, patchRange) {
    if (this.patchNumEquals(patchRange.patchNum, this.EDIT_NAME)) {
      return this.getChangeEditFiles(changeNum, patchRange).then(res =>
        res.files);
    }
    return this.getChangeFiles(changeNum, patchRange);
  }

  getChangeRevisionActions(changeNum, patchNum) {
    const req = {
      changeNum,
      endpoint: '/actions',
      patchNum,
      reportEndpointAsIs: true,
    };
    return this._getChangeURLAndFetch(req);
  }

  /**
   * @param {number|string} changeNum
   * @param {string} inputVal
   * @param {function(?Response, string=)=} opt_errFn
   */
  getChangeSuggestedReviewers(changeNum, inputVal, opt_errFn) {
    return this._getChangeSuggestedGroup('REVIEWER', changeNum, inputVal,
        opt_errFn);
  }

  /**
   * @param {number|string} changeNum
   * @param {string} inputVal
   * @param {function(?Response, string=)=} opt_errFn
   */
  getChangeSuggestedCCs(changeNum, inputVal, opt_errFn) {
    return this._getChangeSuggestedGroup('CC', changeNum, inputVal,
        opt_errFn);
  }

  _getChangeSuggestedGroup(reviewerState, changeNum, inputVal, opt_errFn) {
    // More suggestions may obscure content underneath in the reply dialog,
    // see issue 10793.
    const params = {'n': 6, 'reviewer-state': reviewerState};
    if (inputVal) { params.q = inputVal; }
    return this._getChangeURLAndFetch({
      changeNum,
      endpoint: '/suggest_reviewers',
      errFn: opt_errFn,
      params,
      reportEndpointAsIs: true,
    });
  }

  /**
   * @param {number|string} changeNum
   */
  getChangeIncludedIn(changeNum) {
    return this._getChangeURLAndFetch({
      changeNum,
      endpoint: '/in',
      reportEndpointAsIs: true,
    });
  }

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

  /**
   * @param {string} filter
   * @param {number} groupsPerPage
   * @param {number=} opt_offset
   */
  _getGroupsUrl(filter, groupsPerPage, opt_offset) {
    const offset = opt_offset || 0;

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

  /**
   * @param {string} filter
   * @param {number} reposPerPage
   * @param {number=} opt_offset
   */
  _getReposUrl(filter, reposPerPage, opt_offset) {
    const defaultFilter = 'state:active OR state:read-only';
    const namePartDelimiters = /[@.\-\s\/_]/g;
    const offset = opt_offset || 0;

    if (filter && !filter.includes(':') && filter.match(namePartDelimiters)) {
      // The query language specifies hyphens as operators. Split the string
      // by hyphens and 'AND' the parts together as 'inname:' queries.
      // 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.
      const originalFilter = filter;
      filter = '';
      originalFilter.split(namePartDelimiters).forEach(part => {
        if (part) {
          filter += (filter === '' ? 'inname:' : ' AND inname:') + part;
        }
      });
    }
    // Check if filter is now empty which could be either because the user did
    // not provide it or because the user provided only a split character.
    if (!filter) {
      filter = defaultFilter;
    }

    filter = filter.trim();
    const encodedFilter = encodeURIComponent(filter);

    return `/projects/?n=${reposPerPage + 1}&S=${offset}` +
      `&query=${encodedFilter}`;
  }

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

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

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

  /**
   * @param {string} filter
   * @param {number} groupsPerPage
   * @param {number=} opt_offset
   * @return {!Promise<?Object>}
   */
  getGroups(filter, groupsPerPage, opt_offset) {
    const url = this._getGroupsUrl(filter, groupsPerPage, opt_offset);

    return this._fetchSharedCacheURL({
      url,
      anonymizedUrl: '/groups/?*',
    });
  }

  /**
   * @param {string} filter
   * @param {number} reposPerPage
   * @param {number=} opt_offset
   * @return {!Promise<?Object>}
   */
  getRepos(filter, reposPerPage, opt_offset) {
    const url = this._getReposUrl(filter, reposPerPage, opt_offset);

    // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
    // supports it.
    return this._fetchSharedCacheURL({
      url,
      anonymizedUrl: '/projects/?*',
    });
  }

  setRepoHead(repo, ref) {
    // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
    // supports it.
    return this._restApiHelper.send({
      method: 'PUT',
      url: `/projects/${encodeURIComponent(repo)}/HEAD`,
      body: {ref},
      anonymizedUrl: '/projects/*/HEAD',
    });
  }

  /**
   * @param {string} filter
   * @param {string} repo
   * @param {number} reposBranchesPerPage
   * @param {number=} opt_offset
   * @param {?function(?Response, string=)=} opt_errFn
   * @return {!Promise<?Object>}
   */
  getRepoBranches(filter, repo, reposBranchesPerPage, opt_offset, opt_errFn) {
    const offset = opt_offset || 0;
    const count = reposBranchesPerPage + 1;
    filter = this._computeFilter(filter);
    repo = encodeURIComponent(repo);
    const url = `/projects/${repo}/branches?n=${count}&S=${offset}${filter}`;
    // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
    // supports it.
    return this._restApiHelper.fetchJSON({
      url,
      errFn: opt_errFn,
      anonymizedUrl: '/projects/*/branches?*',
    });
  }

  /**
   * @param {string} filter
   * @param {string} repo
   * @param {number} reposTagsPerPage
   * @param {number=} opt_offset
   * @param {?function(?Response, string=)=} opt_errFn
   * @return {!Promise<?Object>}
   */
  getRepoTags(filter, repo, reposTagsPerPage, opt_offset, opt_errFn) {
    const offset = opt_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;
    // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
    // supports it.
    return this._restApiHelper.fetchJSON({
      url,
      errFn: opt_errFn,
      anonymizedUrl: '/projects/*/tags',
    });
  }

  /**
   * @param {string} filter
   * @param {number} pluginsPerPage
   * @param {number=} opt_offset
   * @param {?function(?Response, string=)=} opt_errFn
   * @return {!Promise<?Object>}
   */
  getPlugins(filter, pluginsPerPage, opt_offset, opt_errFn) {
    const offset = opt_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: opt_errFn,
      anonymizedUrl: '/plugins/?all',
    });
  }

  getRepoAccessRights(repoName, opt_errFn) {
    // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
    // supports it.
    return this._restApiHelper.fetchJSON({
      url: `/projects/${encodeURIComponent(repoName)}/access`,
      errFn: opt_errFn,
      anonymizedUrl: '/projects/*/access',
    });
  }

  setRepoAccessRights(repoName, repoInfo) {
    // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
    // supports it.
    return this._restApiHelper.send({
      method: 'POST',
      url: `/projects/${encodeURIComponent(repoName)}/access`,
      body: repoInfo,
      anonymizedUrl: '/projects/*/access',
    });
  }

  setRepoAccessRightsForReview(projectName, projectInfo) {
    return this._restApiHelper.send({
      method: 'PUT',
      url: `/projects/${encodeURIComponent(projectName)}/access:review`,
      body: projectInfo,
      parseResponse: true,
      anonymizedUrl: '/projects/*/access:review',
    });
  }

  /**
   * @param {string} inputVal
   * @param {number} opt_n
   * @param {function(?Response, string=)=} opt_errFn
   */
  getSuggestedGroups(inputVal, opt_n, opt_errFn) {
    const params = {s: inputVal};
    if (opt_n) { params.n = opt_n; }
    return this._restApiHelper.fetchJSON({
      url: '/groups/',
      errFn: opt_errFn,
      params,
      reportUrlAsIs: true,
    });
  }

  /**
   * @param {string} inputVal
   * @param {number} opt_n
   * @param {function(?Response, string=)=} opt_errFn
   */
  getSuggestedProjects(inputVal, opt_n, opt_errFn) {
    const params = {
      m: inputVal,
      n: MAX_PROJECT_RESULTS,
      type: 'ALL',
    };
    if (opt_n) { params.n = opt_n; }
    return this._restApiHelper.fetchJSON({
      url: '/projects/',
      errFn: opt_errFn,
      params,
      reportUrlAsIs: true,
    });
  }

  /**
   * @param {string} inputVal
   * @param {number} opt_n
   * @param {function(?Response, string=)=} opt_errFn
   */
  getSuggestedAccounts(inputVal, opt_n, opt_errFn) {
    if (!inputVal) {
      return Promise.resolve([]);
    }
    const params = {suggest: null, q: inputVal};
    if (opt_n) { params.n = opt_n; }
    return this._restApiHelper.fetchJSON({
      url: '/accounts/',
      errFn: opt_errFn,
      params,
      anonymizedUrl: '/accounts/?n=*',
    });
  }

  addChangeReviewer(changeNum, reviewerID) {
    return this._sendChangeReviewerRequest('POST', changeNum, reviewerID);
  }

  removeChangeReviewer(changeNum, reviewerID) {
    return this._sendChangeReviewerRequest('DELETE', changeNum, reviewerID);
  }

  _sendChangeReviewerRequest(method, changeNum, reviewerID) {
    return this.getChangeActionURL(changeNum, null, '/reviewers')
        .then(url => {
          let body;
          switch (method) {
            case 'POST':
              body = {reviewer: reviewerID};
              break;
            case 'DELETE':
              url += '/' + encodeURIComponent(reviewerID);
              break;
            default:
              throw Error('Unsupported HTTP method: ' + method);
          }

          return this._restApiHelper.send({method, url, body});
        });
  }

  getRelatedChanges(changeNum, patchNum) {
    return this._getChangeURLAndFetch({
      changeNum,
      endpoint: '/related',
      patchNum,
      reportEndpointAsIs: true,
    });
  }

  getChangesSubmittedTogether(changeNum) {
    return this._getChangeURLAndFetch({
      changeNum,
      endpoint: '/submitted_together?o=NON_VISIBLE_CHANGES',
      reportEndpointAsIs: true,
    });
  }

  getChangeConflicts(changeNum) {
    const options = this.listChangesOptionsToHex(
        this.ListChangesOption.CURRENT_REVISION,
        this.ListChangesOption.CURRENT_COMMIT
    );
    const params = {
      O: options,
      q: 'status:open conflicts:' + changeNum,
    };
    return this._restApiHelper.fetchJSON({
      url: '/changes/',
      params,
      anonymizedUrl: '/changes/conflicts:*',
    });
  }

  getChangeCherryPicks(project, changeID, changeNum) {
    const options = this.listChangesOptionsToHex(
        this.ListChangesOption.CURRENT_REVISION,
        this.ListChangesOption.CURRENT_COMMIT
    );
    const query = [
      'project:' + project,
      'change:' + changeID,
      '-change:' + changeNum,
      '-is:abandoned',
    ].join(' ');
    const params = {
      O: options,
      q: query,
    };
    return this._restApiHelper.fetchJSON({
      url: '/changes/',
      params,
      anonymizedUrl: '/changes/change:*',
    });
  }

  getChangesWithSameTopic(topic, changeNum) {
    const options = this.listChangesOptionsToHex(
        this.ListChangesOption.LABELS,
        this.ListChangesOption.CURRENT_REVISION,
        this.ListChangesOption.CURRENT_COMMIT,
        this.ListChangesOption.DETAILED_LABELS
    );
    const query = [
      'status:open',
      '-change:' + changeNum,
      `topic:"${topic}"`,
    ].join(' ');
    const params = {
      O: options,
      q: query,
    };
    return this._restApiHelper.fetchJSON({
      url: '/changes/',
      params,
      anonymizedUrl: '/changes/topic:*',
    });
  }

  getReviewedFiles(changeNum, patchNum) {
    return this._getChangeURLAndFetch({
      changeNum,
      endpoint: '/files?reviewed',
      patchNum,
      reportEndpointAsIs: true,
    });
  }

  /**
   * @param {number|string} changeNum
   * @param {number|string} patchNum
   * @param {string} path
   * @param {boolean} reviewed
   * @param {function(?Response, string=)=} opt_errFn
   */
  saveFileReviewed(changeNum, patchNum, path, reviewed, opt_errFn) {
    return this._getChangeURLAndSend({
      changeNum,
      method: reviewed ? 'PUT' : 'DELETE',
      patchNum,
      endpoint: `/files/${encodeURIComponent(path)}/reviewed`,
      errFn: opt_errFn,
      anonymizedEndpoint: '/files/*/reviewed',
    });
  }

  /**
   * @param {number|string} changeNum
   * @param {number|string} patchNum
   * @param {!Object} review
   * @param {function(?Response, string=)=} opt_errFn
   */
  saveChangeReview(changeNum, patchNum, review, opt_errFn) {
    const promises = [
      this.awaitPendingDiffDrafts(),
      this.getChangeActionURL(changeNum, patchNum, '/review'),
    ];
    return Promise.all(promises).then(([, url]) => this._restApiHelper.send({
      method: 'POST',
      url,
      body: review,
      errFn: opt_errFn,
    }));
  }

  getChangeEdit(changeNum, opt_download_commands) {
    const params = opt_download_commands ? {'download-commands': true} : null;
    return this.getLoggedIn().then(loggedIn => {
      if (!loggedIn) { return false; }
      return this._getChangeURLAndFetch({
        changeNum,
        endpoint: '/edit/',
        params,
        reportEndpointAsIs: true,
      }, true);
    });
  }

  /**
   * @param {string} project
   * @param {string} branch
   * @param {string} subject
   * @param {string=} opt_topic
   * @param {boolean=} opt_isPrivate
   * @param {boolean=} opt_workInProgress
   * @param {string=} opt_baseChange
   * @param {string=} opt_baseCommit
   */
  createChange(project, branch, subject, opt_topic, opt_isPrivate,
      opt_workInProgress, opt_baseChange, opt_baseCommit) {
    return this._restApiHelper.send({
      method: 'POST',
      url: '/changes/',
      body: {
        project,
        branch,
        subject,
        topic: opt_topic,
        is_private: opt_isPrivate,
        work_in_progress: opt_workInProgress,
        base_change: opt_baseChange,
        base_commit: opt_baseCommit,
      },
      parseResponse: true,
      reportUrlAsIs: true,
    });
  }

  /**
   * @param {number|string} changeNum
   * @param {string} path
   * @param {number|string} patchNum
   */
  getFileContent(changeNum, path, patchNum) {
    // 404s indicate the file does not exist yet in the revision, so suppress
    // them.
    const suppress404s = res => {
      if (res && res.status !== 404) {
        this.dispatchEvent(new CustomEvent('server-error', {
          detail: {res},
          composed: true, bubbles: true,
        }));
      }
      return res;
    };
    const promise = this.patchNumEquals(patchNum, this.EDIT_NAME) ?
      this._getFileInChangeEdit(changeNum, path) :
      this._getFileInRevision(changeNum, path, patchNum, suppress404s);

    return promise.then(res => {
      if (!res.ok) { 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 this.getResponseObject(res).then(content => {
        return {content, type, ok: true};
      });
    });
  }

  /**
   * Gets a file in a specific change and revision.
   *
   * @param {number|string} changeNum
   * @param {string} path
   * @param {number|string} patchNum
   * @param {?function(?Response, string=)=} opt_errFn
   */
  _getFileInRevision(changeNum, path, patchNum, opt_errFn) {
    return this._getChangeURLAndSend({
      changeNum,
      method: 'GET',
      patchNum,
      endpoint: `/files/${encodeURIComponent(path)}/content`,
      errFn: opt_errFn,
      headers: {Accept: 'application/json'},
      anonymizedEndpoint: '/files/*/content',
    });
  }

  /**
   * Gets a file in a change edit.
   *
   * @param {number|string} changeNum
   * @param {string} path
   */
  _getFileInChangeEdit(changeNum, path) {
    return this._getChangeURLAndSend({
      changeNum,
      method: 'GET',
      endpoint: '/edit/' + encodeURIComponent(path),
      headers: {Accept: 'application/json'},
      anonymizedEndpoint: '/edit/*',
    });
  }

  rebaseChangeEdit(changeNum) {
    return this._getChangeURLAndSend({
      changeNum,
      method: 'POST',
      endpoint: '/edit:rebase',
      reportEndpointAsIs: true,
    });
  }

  deleteChangeEdit(changeNum) {
    return this._getChangeURLAndSend({
      changeNum,
      method: 'DELETE',
      endpoint: '/edit',
      reportEndpointAsIs: true,
    });
  }

  restoreFileInChangeEdit(changeNum, restore_path) {
    return this._getChangeURLAndSend({
      changeNum,
      method: 'POST',
      endpoint: '/edit',
      body: {restore_path},
      reportEndpointAsIs: true,
    });
  }

  renameFileInChangeEdit(changeNum, old_path, new_path) {
    return this._getChangeURLAndSend({
      changeNum,
      method: 'POST',
      endpoint: '/edit',
      body: {old_path, new_path},
      reportEndpointAsIs: true,
    });
  }

  deleteFileInChangeEdit(changeNum, path) {
    return this._getChangeURLAndSend({
      changeNum,
      method: 'DELETE',
      endpoint: '/edit/' + encodeURIComponent(path),
      anonymizedEndpoint: '/edit/*',
    });
  }

  saveChangeEdit(changeNum, path, contents) {
    return this._getChangeURLAndSend({
      changeNum,
      method: 'PUT',
      endpoint: '/edit/' + encodeURIComponent(path),
      body: contents,
      contentType: 'text/plain',
      anonymizedEndpoint: '/edit/*',
    });
  }

  saveFileUploadChangeEdit(changeNum, path, content) {
    return this._getChangeURLAndSend({
      changeNum,
      method: 'PUT',
      endpoint: '/edit/' + encodeURIComponent(path),
      body: {binary_content: content},
      anonymizedEndpoint: '/edit/*',
    });
  }

  getRobotCommentFixPreview(changeNum, patchNum, fixId) {
    return this._getChangeURLAndFetch({
      changeNum,
      patchNum,
      endpoint: `/fixes/${encodeURIComponent(fixId)}/preview`,
      reportEndpointAsId: true,
    });
  }

  applyFixSuggestion(changeNum, patchNum, fixId) {
    return this._getChangeURLAndSend({
      method: 'POST',
      changeNum,
      patchNum,
      endpoint: `/fixes/${encodeURIComponent(fixId)}/apply`,
      reportEndpointAsId: true,
    });
  }

  // Deprecated, prefer to use putChangeCommitMessage instead.
  saveChangeCommitMessageEdit(changeNum, message) {
    return this._getChangeURLAndSend({
      changeNum,
      method: 'PUT',
      endpoint: '/edit:message',
      body: {message},
      reportEndpointAsIs: true,
    });
  }

  publishChangeEdit(changeNum) {
    return this._getChangeURLAndSend({
      changeNum,
      method: 'POST',
      endpoint: '/edit:publish',
      reportEndpointAsIs: true,
    });
  }

  putChangeCommitMessage(changeNum, message) {
    return this._getChangeURLAndSend({
      changeNum,
      method: 'PUT',
      endpoint: '/message',
      body: {message},
      reportEndpointAsIs: true,
    });
  }

  deleteChangeCommitMessage(changeNum, messageId) {
    return this._getChangeURLAndSend({
      changeNum,
      method: 'DELETE',
      endpoint: '/messages/' + messageId,
      reportEndpointAsIs: true,
    });
  }

  saveChangeStarred(changeNum, starred) {
    // Some servers may require the project name to be provided
    // alongside the change number, so resolve the project name
    // first.
    return this.getFromProjectLookup(changeNum).then(project => {
      const url = '/accounts/self/starred.changes/' +
          (project ? encodeURIComponent(project) + '~' : '') + changeNum;
      return this._restApiHelper.send({
        method: starred ? 'PUT' : 'DELETE',
        url,
        anonymizedUrl: '/accounts/self/starred.changes/*',
      });
    });
  }

  saveChangeReviewed(changeNum, reviewed) {
    return this.getConfig().then(config => {
      const isAttentionSetEnabled = !!config && !!config.change
          && config.change.enable_attention_set;
      if (isAttentionSetEnabled) return Promise.resolve();
      return this._getChangeURLAndSend({
        changeNum,
        method: 'PUT',
        endpoint: reviewed ? '/reviewed' : '/unreviewed',
      });
    });
  }

  /**
   * Public version of the _restApiHelper.send method preserved for plugins.
   *
   * @param {string} method
   * @param {string} url
   * @param {?string|number|Object=} opt_body passed as null sometimes
   *    and also apparently a number. TODO (beckysiegel) remove need for
   *    number at least.
   * @param {?function(?Response, string=)=} opt_errFn
   *    passed as null sometimes.
   * @param {?string=} opt_contentType
   * @param {Object=} opt_headers
   */
  send(method, url, opt_body, opt_errFn, opt_contentType,
      opt_headers) {
    return this._restApiHelper.send({
      method,
      url,
      body: opt_body,
      errFn: opt_errFn,
      contentType: opt_contentType,
      headers: opt_headers,
    });
  }

  /**
   * @param {number|string} changeNum
   * @param {number|string} basePatchNum Negative values specify merge parent
   *     index.
   * @param {number|string} patchNum
   * @param {string} path
   * @param {string=} opt_whitespace the ignore-whitespace level for the diff
   *     algorithm.
   * @param {function(?Response, string=)=} opt_errFn
   */
  getDiff(changeNum, basePatchNum, patchNum, path, opt_whitespace,
      opt_errFn) {
    const params = {
      context: 'ALL',
      intraline: null,
      whitespace: opt_whitespace || 'IGNORE_NONE',
    };
    if (this.isMergeParent(basePatchNum)) {
      params.parent = this.getParentIndex(basePatchNum);
    } else if (!this.patchNumEquals(basePatchNum, PARENT_PATCH_NUM)) {
      params.base = basePatchNum;
    }
    const endpoint = `/files/${encodeURIComponent(path)}/diff`;
    const req = {
      changeNum,
      endpoint,
      patchNum,
      errFn: opt_errFn,
      params,
      anonymizedEndpoint: '/files/*/diff',
    };

    // Invalidate the cache if its edit patch to make sure we always get latest.
    if (patchNum === this.EDIT_NAME) {
      if (!req.fetchOptions) req.fetchOptions = {};
      if (!req.fetchOptions.headers) req.fetchOptions.headers = new Headers();
      req.fetchOptions.headers.append('Cache-Control', 'no-cache');
    }

    return this._getChangeURLAndFetch(req);
  }

  /**
   * @param {number|string} changeNum
   * @param {number|string=} opt_basePatchNum
   * @param {number|string=} opt_patchNum
   * @param {string=} opt_path
   * @return {!Promise<!Object>}
   */
  getDiffComments(changeNum, opt_basePatchNum, opt_patchNum, opt_path) {
    return this._getDiffComments(changeNum, '/comments', opt_basePatchNum,
        opt_patchNum, opt_path);
  }

  /**
   * @param {number|string} changeNum
   * @param {number|string=} opt_basePatchNum
   * @param {number|string=} opt_patchNum
   * @param {string=} opt_path
   * @return {!Promise<!Object>}
   */
  getDiffRobotComments(changeNum, opt_basePatchNum, opt_patchNum, opt_path) {
    return this._getDiffComments(changeNum, '/robotcomments',
        opt_basePatchNum, opt_patchNum, opt_path);
  }

  /**
   * If the user is logged in, fetch the user's draft diff comments. If there
   * is no logged in user, the request is not made and the promise yields an
   * empty object.
   *
   * @param {number|string} changeNum
   * @param {number|string=} opt_basePatchNum
   * @param {number|string=} opt_patchNum
   * @param {string=} opt_path
   * @return {!Promise<!Object>}
   */
  getDiffDrafts(changeNum, opt_basePatchNum, opt_patchNum, opt_path) {
    return this.getLoggedIn().then(loggedIn => {
      if (!loggedIn) { return Promise.resolve({}); }
      return this._getDiffComments(changeNum, '/drafts', opt_basePatchNum,
          opt_patchNum, opt_path);
    });
  }

  _setRange(comments, comment) {
    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) {
    comments = comments || [];
    comments.sort(
        (a, b) => parseDate(a.updated) - parseDate(b.updated)
    );
    for (const comment of comments) {
      this._setRange(comments, comment);
    }
    return comments;
  }

  /**
   * @param {number|string} changeNum
   * @param {string} endpoint
   * @param {number|string=} opt_basePatchNum
   * @param {number|string=} opt_patchNum
   * @param {string=} opt_path
   * @return {!Promise<!Object>}
   */
  _getDiffComments(changeNum, endpoint, opt_basePatchNum,
      opt_patchNum, opt_path) {
    /**
     * Fetches the comments for a given patchNum.
     * Helper function to make promises more legible.
     *
     * @param {string|number=} opt_patchNum
     * @return {!Promise<!Object>} Diff comments response.
     */
    // We don't want to add accept header, since preloading of comments is
    // working only without accept header.
    const noAcceptHeader = true;
    const fetchComments = opt_patchNum => this._getChangeURLAndFetch({
      changeNum,
      endpoint,
      patchNum: opt_patchNum,
      reportEndpointAsIs: true,
    }, noAcceptHeader);

    if (!opt_basePatchNum && !opt_patchNum && !opt_path) {
      return fetchComments();
    }
    function onlyParent(c) { return c.side == PARENT_PATCH_NUM; }
    function withoutParent(c) { return c.side != PARENT_PATCH_NUM; }
    function setPath(c) { c.path = opt_path; }

    const promises = [];
    let comments;
    let baseComments;
    let fetchPromise;
    fetchPromise = fetchComments(opt_patchNum).then(response => {
      comments = response[opt_path] || [];
      // TODO(kaspern): Implement this on in the backend so this can
      // be removed.
      // Sort comments by date so that parent ranges can be propagated
      // in a single pass.
      comments = this._setRanges(comments);

      if (opt_basePatchNum == PARENT_PATCH_NUM) {
        baseComments = comments.filter(onlyParent);
        baseComments.forEach(setPath);
      }
      comments = comments.filter(withoutParent);

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

    if (opt_basePatchNum != PARENT_PATCH_NUM) {
      fetchPromise = fetchComments(opt_basePatchNum).then(response => {
        baseComments = (response[opt_path] || [])
            .filter(withoutParent);
        baseComments = this._setRanges(baseComments);
        baseComments.forEach(setPath);
      });
      promises.push(fetchPromise);
    }

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

  /**
   * @param {number|string} changeNum
   * @param {string} endpoint
   * @param {number|string=} opt_patchNum
   */
  _getDiffCommentsFetchURL(changeNum, endpoint, opt_patchNum) {
    return this._changeBaseURL(changeNum, opt_patchNum)
        .then(url => url + endpoint);
  }

  saveDiffDraft(changeNum, patchNum, draft) {
    return this._sendDiffDraftRequest('PUT', changeNum, patchNum, draft);
  }

  deleteDiffDraft(changeNum, patchNum, draft) {
    return this._sendDiffDraftRequest('DELETE', changeNum, patchNum, draft);
  }

  /**
   * @returns {boolean} Whether there are pending diff draft sends.
   */
  hasPendingDiffDrafts() {
    const promises = this._pendingRequests[Requests.SEND_DIFF_DRAFT];
    return promises && promises.length;
  }

  /**
   * @returns {!Promise<undefined>} A promise that resolves when all pending
   *    diff draft sends have resolved.
   */
  awaitPendingDiffDrafts() {
    return Promise.all(this._pendingRequests[Requests.SEND_DIFF_DRAFT] || [])
        .then(() => {
          this._pendingRequests[Requests.SEND_DIFF_DRAFT] = [];
        });
  }

  _sendDiffDraftRequest(method, changeNum, patchNum, draft) {
    const isCreate = !draft.id && method === 'PUT';
    let endpoint = '/drafts';
    let anonymizedEndpoint = endpoint;
    if (draft.id) {
      endpoint += '/' + draft.id;
      anonymizedEndpoint += '/*';
    }
    let body;
    if (method === 'PUT') {
      body = draft;
    }

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

    const req = {
      changeNum,
      method,
      patchNum,
      endpoint,
      body,
      anonymizedEndpoint,
    };

    const promise = this._getChangeURLAndSend(req);
    this._pendingRequests[Requests.SEND_DIFF_DRAFT].push(promise);

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

    return promise;
  }

  getCommitInfo(project, commit) {
    return this._restApiHelper.fetchJSON({
      url: '/projects/' + encodeURIComponent(project) +
          '/commits/' + encodeURIComponent(commit),
      anonymizedUrl: '/projects/*/comments/*',
    });
  }

  _fetchB64File(url) {
    return this._restApiHelper.fetch({url: this.getBaseUrl() + 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};
              });
        });
  }

  /**
   * @param {string} changeId
   * @param {string|number} patchNum
   * @param {string} path
   * @param {number=} opt_parentIndex
   */
  getB64FileContents(changeId, patchNum, path, opt_parentIndex) {
    const parent = typeof opt_parentIndex === 'number' ?
      '?parent=' + opt_parentIndex : '';
    return this._changeBaseURL(changeId, patchNum).then(url => {
      url = `${url}/files/${encodeURIComponent(path)}/content${parent}`;
      return this._fetchB64File(url);
    });
  }

  getImagesForDiff(changeNum, diff, patchRange) {
    let promiseA;
    let promiseB;

    if (diff.meta_a && 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 && 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 => {
      const baseImage = results[0];
      const revisionImage = results[1];

      // Sometimes the server doesn't send back the content type.
      if (baseImage) {
        baseImage._expectedType = diff.meta_a.content_type;
        baseImage._name = diff.meta_a.name;
      }
      if (revisionImage) {
        revisionImage._expectedType = diff.meta_b.content_type;
        revisionImage._name = diff.meta_b.name;
      }

      return {baseImage, revisionImage};
    });
  }

  /**
   * @param {number|string} changeNum
   * @param {?number|string=} opt_patchNum passed as null sometimes.
   * @param {string=} opt_project
   * @return {!Promise<string>}
   */
  _changeBaseURL(changeNum, opt_patchNum, opt_project) {
    // TODO(kaspern): For full slicer migration, app should warn with a call
    // stack every time _changeBaseURL is called without a project.
    const projectPromise = opt_project ?
      Promise.resolve(opt_project) :
      this.getFromProjectLookup(changeNum);
    return projectPromise.then(project => {
      let url = `/changes/${encodeURIComponent(project)}~${changeNum}`;
      if (opt_patchNum) {
        url += `/revisions/${opt_patchNum}`;
      }
      return url;
    });
  }

  addToAttentionSet(changeNum, user, reason) {
    return this._getChangeURLAndSend({
      changeNum,
      method: 'POST',
      endpoint: '/attention',
      body: {user, reason},
      reportUrlAsIs: true,
    });
  }

  removeFromAttentionSet(changeNum, user, reason) {
    return this._getChangeURLAndSend({
      changeNum,
      method: 'DELETE',
      endpoint: `/attention/${user}`,
      anonymizedEndpoint: '/attention/*',
      body: {reason},
    });
  }

  /**
   * @suppress {checkTypes}
   * Resulted in error: Promise.prototype.then does not match formal
   * parameter.
   */
  setChangeTopic(changeNum, topic) {
    return this._getChangeURLAndSend({
      changeNum,
      method: 'PUT',
      endpoint: '/topic',
      body: {topic},
      parseResponse: true,
      reportUrlAsIs: true,
    });
  }

  /**
   * @suppress {checkTypes}
   * Resulted in error: Promise.prototype.then does not match formal
   * parameter.
   */
  setChangeHashtag(changeNum, hashtag) {
    return this._getChangeURLAndSend({
      changeNum,
      method: 'POST',
      endpoint: '/hashtags',
      body: hashtag,
      parseResponse: true,
      reportUrlAsIs: true,
    });
  }

  deleteAccountHttpPassword() {
    return this._restApiHelper.send({
      method: 'DELETE',
      url: '/accounts/self/password.http',
      reportUrlAsIs: true,
    });
  }

  /**
   * @suppress {checkTypes}
   * Resulted in error: Promise.prototype.then does not match formal
   * parameter.
   */
  generateAccountHttpPassword() {
    return this._restApiHelper.send({
      method: 'PUT',
      url: '/accounts/self/password.http',
      body: {generate: true},
      parseResponse: true,
      reportUrlAsIs: true,
    });
  }

  getAccountSSHKeys() {
    return this._fetchSharedCacheURL({
      url: '/accounts/self/sshkeys',
      reportUrlAsIs: true,
    });
  }

  addAccountSSHKey(key) {
    const req = {
      method: 'POST',
      url: '/accounts/self/sshkeys',
      body: key,
      contentType: 'text/plain',
      reportUrlAsIs: true,
    };
    return this._restApiHelper.send(req)
        .then(response => {
          if (response.status < 200 && response.status >= 300) {
            return Promise.reject(new Error('error'));
          }
          return this.getResponseObject(response);
        })
        .then(obj => {
          if (!obj.valid) { return Promise.reject(new Error('error')); }
          return obj;
        });
  }

  deleteAccountSSHKey(id) {
    return this._restApiHelper.send({
      method: 'DELETE',
      url: '/accounts/self/sshkeys/' + id,
      anonymizedUrl: '/accounts/self/sshkeys/*',
    });
  }

  getAccountGPGKeys() {
    return this._restApiHelper.fetchJSON({
      url: '/accounts/self/gpgkeys',
      reportUrlAsIs: true,
    });
  }

  addAccountGPGKey(key) {
    const req = {
      method: 'POST',
      url: '/accounts/self/gpgkeys',
      body: key,
      reportUrlAsIs: true,
    };
    return this._restApiHelper.send(req)
        .then(response => {
          if (response.status < 200 && response.status >= 300) {
            return Promise.reject(new Error('error'));
          }
          return this.getResponseObject(response);
        })
        .then(obj => {
          if (!obj) { return Promise.reject(new Error('error')); }
          return obj;
        });
  }

  deleteAccountGPGKey(id) {
    return this._restApiHelper.send({
      method: 'DELETE',
      url: '/accounts/self/gpgkeys/' + id,
      anonymizedUrl: '/accounts/self/gpgkeys/*',
    });
  }

  deleteVote(changeNum, account, label) {
    return this._getChangeURLAndSend({
      changeNum,
      method: 'DELETE',
      endpoint: `/reviewers/${account}/votes/${encodeURIComponent(label)}`,
      anonymizedEndpoint: '/reviewers/*/votes/*',
    });
  }

  setDescription(changeNum, patchNum, desc) {
    return this._getChangeURLAndSend({
      changeNum,
      method: 'PUT', patchNum,
      endpoint: '/description',
      body: {description: desc},
      reportUrlAsIs: true,
    });
  }

  confirmEmail(token) {
    const req = {
      method: 'PUT',
      url: '/config/server/email.confirm',
      body: {token},
      reportUrlAsIs: true,
    };
    return this._restApiHelper.send(req).then(response => {
      if (response.status === 204) {
        return 'Email confirmed successfully.';
      }
      return null;
    });
  }

  getCapabilities(opt_errFn) {
    return this._restApiHelper.fetchJSON({
      url: '/config/server/capabilities',
      errFn: opt_errFn,
      reportUrlAsIs: true,
    });
  }

  getTopMenus(opt_errFn) {
    return this._fetchSharedCacheURL({
      url: '/config/server/top-menus',
      errFn: opt_errFn,
      reportUrlAsIs: true,
    });
  }

  setAssignee(changeNum, assignee) {
    return this._getChangeURLAndSend({
      changeNum,
      method: 'PUT',
      endpoint: '/assignee',
      body: {assignee},
      reportUrlAsIs: true,
    });
  }

  deleteAssignee(changeNum) {
    return this._getChangeURLAndSend({
      changeNum,
      method: 'DELETE',
      endpoint: '/assignee',
      reportUrlAsIs: true,
    });
  }

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

  /**
   * @param {number|string} changeNum
   * @param {number|string=} opt_message
   */
  startWorkInProgress(changeNum, opt_message) {
    const body = {};
    if (opt_message) {
      body.message = opt_message;
    }
    const req = {
      changeNum,
      method: 'POST',
      endpoint: '/wip',
      body,
      reportUrlAsIs: true,
    };
    return this._getChangeURLAndSend(req).then(response => {
      if (response.status === 204) {
        return 'Change marked as Work In Progress.';
      }
    });
  }

  /**
   * @param {number|string} changeNum
   * @param {number|string=} opt_body
   * @param {function(?Response, string=)=} opt_errFn
   */
  startReview(changeNum, opt_body, opt_errFn) {
    return this._getChangeURLAndSend({
      changeNum,
      method: 'POST',
      endpoint: '/ready',
      body: opt_body,
      errFn: opt_errFn,
      reportUrlAsIs: true,
    });
  }

  /**
   * @suppress {checkTypes}
   * Resulted in error: Promise.prototype.then does not match formal
   * parameter.
   */
  deleteComment(changeNum, patchNum, commentID, reason) {
    return this._getChangeURLAndSend({
      changeNum,
      method: 'POST',
      patchNum,
      endpoint: `/comments/${commentID}/delete`,
      body: {reason},
      parseResponse: true,
      anonymizedEndpoint: '/comments/*/delete',
    });
  }

  /**
   * Given a changeNum, gets the change.
   *
   * @param {number|string} changeNum
   * @param {function(?Response, string=)=} opt_errFn
   * @return {!Promise<?Object>} The change
   */
  getChange(changeNum, opt_errFn) {
    // Cannot use _changeBaseURL, as this function is used by _projectLookup.
    return this._restApiHelper.fetchJSON({
      url: `/changes/?q=change:${changeNum}`,
      errFn: opt_errFn,
      anonymizedUrl: '/changes/?q=change:*',
    }).then(res => {
      if (!res || !res.length) { return null; }
      return res[0];
    });
  }

  /**
   * @param {string|number} changeNum
   * @param {string=} project
   */
  setInProjectLookup(changeNum, project) {
    if (this._projectLookup[changeNum] &&
        this._projectLookup[changeNum] !== project) {
      console.warn('Change set with multiple project nums.' +
          'One of them must be invalid.');
    }
    this._projectLookup[changeNum] = project;
  }

  /**
   * Checks in _projectLookup for the changeNum. If it exists, returns the
   * project. If not, calls the restAPI to get the change, populates
   * _projectLookup with the project for that change, and returns the project.
   *
   * @param {string|number} changeNum
   * @return {!Promise<string|undefined>}
   */
  getFromProjectLookup(changeNum) {
    const project = this._projectLookup[changeNum];
    if (project) { return Promise.resolve(project); }

    const onError = response => {
      // Fire a page error so that the visual 404 is displayed.
      this.dispatchEvent(new CustomEvent('page-error', {
        detail: {response},
        composed: true, bubbles: true,
      }));
    };

    return this.getChange(changeNum, onError).then(change => {
      if (!change || !change.project) { return; }
      this.setInProjectLookup(changeNum, change.project);
      return change.project;
    });
  }

  /**
   * Alias for _changeBaseURL.then(send).
   *
   * @todo(beckysiegel) clean up comments
   * @param {Gerrit.ChangeSendRequest} req
   * @return {!Promise<!Object>}
   */
  _getChangeURLAndSend(req) {
    const anonymizedBaseUrl = req.patchNum ?
      ANONYMIZED_REVISION_BASE_URL : ANONYMIZED_CHANGE_BASE_URL;
    const anonymizedEndpoint = req.reportEndpointAsIs ?
      req.endpoint : req.anonymizedEndpoint;

    return this._changeBaseURL(req.changeNum, req.patchNum)
        .then(url => this._restApiHelper.send({
          method: req.method,
          url: url + req.endpoint,
          body: req.body,
          errFn: req.errFn,
          contentType: req.contentType,
          headers: req.headers,
          parseResponse: req.parseResponse,
          anonymizedUrl: anonymizedEndpoint ?
            (anonymizedBaseUrl + anonymizedEndpoint) : undefined,
        }));
  }

  /**
   * Alias for _changeBaseURL.then(_fetchJSON).
   *
   * @param {Gerrit.ChangeFetchRequest} req
   * @return {!Promise<!Object>}
   */
  _getChangeURLAndFetch(req, noAcceptHeader) {
    const anonymizedEndpoint = req.reportEndpointAsIs ?
      req.endpoint : req.anonymizedEndpoint;
    const anonymizedBaseUrl = req.patchNum ?
      ANONYMIZED_REVISION_BASE_URL : ANONYMIZED_CHANGE_BASE_URL;
    return this._changeBaseURL(req.changeNum, req.patchNum)
        .then(url => this._restApiHelper.fetchJSON({
          url: url + req.endpoint,
          errFn: req.errFn,
          params: req.params,
          fetchOptions: req.fetchOptions,
          anonymizedUrl: anonymizedEndpoint ?
            (anonymizedBaseUrl + anonymizedEndpoint) : undefined,
        }, noAcceptHeader));
  }

  /**
   * Execute a change action or revision action on a change.
   *
   * @param {number} changeNum
   * @param {string} method
   * @param {string} endpoint
   * @param {string|number|undefined} opt_patchNum
   * @param {Object=} opt_payload
   * @param {?function(?Response, string=)=} opt_errFn
   * @return {Promise}
   */
  executeChangeAction(changeNum, method, endpoint, opt_patchNum, opt_payload,
      opt_errFn) {
    return this._getChangeURLAndSend({
      changeNum,
      method,
      patchNum: opt_patchNum,
      endpoint,
      body: opt_payload,
      errFn: opt_errFn,
    });
  }

  /**
   * Get blame information for the given diff.
   *
   * @param {string|number} changeNum
   * @param {string|number} patchNum
   * @param {string} path
   * @param {boolean=} opt_base If true, requests blame for the base of the
   *     diff, rather than the revision.
   * @return {!Promise<!Object>}
   */
  getBlame(changeNum, patchNum, path, opt_base) {
    const encodedPath = encodeURIComponent(path);
    return this._getChangeURLAndFetch({
      changeNum,
      endpoint: `/files/${encodedPath}/blame`,
      patchNum,
      params: opt_base ? {base: 't'} : undefined,
      anonymizedEndpoint: '/files/*/blame',
    });
  }

  /**
   * 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} promise The original promise.
   * @return {Promise} The modified promise.
   */
  _failForCreate200(promise) {
    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_BLACKLIST.test(key)) {
                obj[key] = val;
              }
              return obj;
            }, {});
        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;
    });
  }

  /**
   * Fetch a project dashboard definition.
   * https://gerrit-review.googlesource.com/Documentation/rest-api-projects.html#get-dashboard
   *
   * @param {string} project
   * @param {string} dashboard
   * @param {function(?Response, string=)=} opt_errFn
   *    passed as null sometimes.
   * @return {!Promise<!Object>}
   */
  getDashboard(project, dashboard, opt_errFn) {
    const url = '/projects/' + encodeURIComponent(project) + '/dashboards/' +
        encodeURIComponent(dashboard);
    return this._fetchSharedCacheURL({
      url,
      errFn: opt_errFn,
      anonymizedUrl: '/projects/*/dashboards/*',
    });
  }

  /**
   * @param {string} filter
   * @return {!Promise<?Object>}
   */
  getDocumentationSearches(filter) {
    filter = filter.trim();
    const encodedFilter = encodeURIComponent(filter);

    // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
    // supports it.
    return this._fetchSharedCacheURL({
      url: `/Documentation/?q=${encodedFilter}`,
      anonymizedUrl: '/Documentation/?*',
    });
  }

  getMergeable(changeNum) {
    return this._getChangeURLAndFetch({
      changeNum,
      endpoint: '/revisions/current/mergeable',
      parseResponse: true,
      reportEndpointAsIs: true,
    });
  }

  deleteDraftComments(query) {
    return this._restApiHelper.send({
      method: 'POST',
      url: '/accounts/self/drafts:delete',
      body: {query},
    });
  }
}

customElements.define(GrRestApiInterface.is, GrRestApiInterface);
