/**
 * @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{string} opt_p
   * @param {number} opt_n
   * @param {function(?Response, string=)=} opt_errFn
   */
  getSuggestedGroups(inputVal, opt_p, opt_n, opt_errFn) {
    const params = {s: inputVal};
    if (opt_n) { params.n = opt_n; }
    if (opt_p) { params.p = opt_p; }
    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);
