/**
 * @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: es6-promise Needed for IE11 and fetch polyfill support, see Issue 4308 */
/* NB: Order is important, because of namespaced classes. */
/*
  FIXME(polymer-modulizer): the above comments were extracted
  from HTML and may be out of place here. Review them and
  then delete this comment!
*/
import '../../../scripts/bundled-polymer.js';

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 'es6-promise/lib/es6-promise.js';
import 'whatwg-fetch/fetch.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 {util} from '../../../scripts/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 Polymer.Element
 */
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/');
  }

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

  /**
   * @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._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) => util.parseDate(a.updated) - util.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;
    });
  }

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