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

import {mixinBehaviors} from '@polymer/polymer/lib/legacy/class.js';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
import {PolymerElement} from '@polymer/polymer/polymer-element.js';
import {PatchSetBehavior} from '../../../behaviors/gr-patch-set-behavior/gr-patch-set-behavior.js';
import {PathListBehavior} from '../../../behaviors/gr-path-list-behavior/gr-path-list-behavior.js';
import {RESTClientBehavior} from '../../../behaviors/rest-client-behavior/rest-client-behavior.js';
import {GrEtagDecorator} from './gr-etag-decorator.js';
import {SiteBasedCache, FetchPromisesCache, GrRestApiHelper} from './gr-rest-apis/gr-rest-api-helper.js';
import {GrReviewerUpdatesParser} from './gr-reviewer-updates-parser.js';
import {parseDate} from '../../../utils/date-util.js';
import {authService} from './gr-auth.js';
import {getBaseUrl} from '../../../utils/url-util.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_BLOCK_REGEX = /^set-cookie$/i;

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

let siteBasedCache = new SiteBasedCache(); // Shared across instances.
let fetchPromisesCache = new FetchPromisesCache(); // Shared across instances.
let pendingRequest = {}; // Shared across instances.
let grEtagDecorator = new GrEtagDecorator; // Shared across instances.
let projectLookup = {}; // Shared across instances.

export function _testOnlyResetGrRestApiSharedObjects() {
  for (const key in fetchPromisesCache._data) {
    if (fetchPromisesCache._data.hasOwnProperty(key)) {
      // reject already fulfilled promise does nothing
      fetchPromisesCache._data[key].reject();
    }
  }

  for (const key in pendingRequest) {
    if (!pendingRequest.hasOwnProperty(key)) {
      continue;
    }
    for (const req of pendingRequest[key]) {
      // reject already fulfilled promise does nothing
      req.reject();
    }
  }

  siteBasedCache = new SiteBasedCache();
  fetchPromisesCache = new FetchPromisesCache();
  pendingRequest = {};
  grEtagDecorator = new GrEtagDecorator;
  projectLookup = {};
  authService.clearCache();
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  /**
   * @param {?Object} prefs
   * @param {function(?Response, string=)=} opt_errFn
   */
  savePreferences(prefs, opt_errFn) {
    // Note (Issue 5142): normalize the download scheme with lower case before
    // saving.
    if (prefs.download_scheme) {
      prefs.download_scheme = prefs.download_scheme.toLowerCase();
    }

    return this._restApiHelper.send({
      method: 'PUT',
      url: '/accounts/self/preferences',
      body: prefs,
      errFn: opt_errFn,
      reportUrlAsIs: true,
    });
  }

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

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

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

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

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

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

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

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

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

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

  /**
   * @param {string} email
   * @param {function(?Response, string=)=} opt_errFn
   */
  setPreferredAccountEmail(email, opt_errFn) {
    const encodedEmail = encodeURIComponent(email);
    const req = {
      method: 'PUT',
      url: `/accounts/self/emails/${encodedEmail}/preferred`,
      errFn: opt_errFn,
      anonymizedUrl: '/accounts/self/emails/*/preferred',
    };
    return this._restApiHelper.send(req).then(() => {
      // If result of getAccountEmails is in cache, update it in the cache
      // so we don't have to invalidate it.
      const cachedEmails = this._cache.get('/accounts/self/emails');
      if (cachedEmails) {
        const emails = cachedEmails.map(entry => {
          if (entry.email === email) {
            return {email, preferred: true};
          } else {
            return {email};
          }
        });
        this._cache.set('/accounts/self/emails', emails);
      }
    });
  }

  /**
   * @param {?Object} obj
   */
  _updateCachedAccount(obj) {
    // If result of getAccount is in cache, update it in the cache
    // so we don't have to invalidate it.
    const cachedAccount = this._cache.get('/accounts/self/detail');
    if (cachedAccount) {
      // Replace object in cache with new object to force UI updates.
      this._cache.set('/accounts/self/detail',
          Object.assign({}, cachedAccount, obj));
    }
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    if (filter && !filter.includes(':') && filter.match(namePartDelimiters)) {
      // The query language specifies hyphens as operators. Split the string
      // by hyphens and 'AND' the parts together as 'inname:' queries.
      // If the filter includes a semicolon, the user is using a more complex
      // query so we trust them and don't do any magic under the hood.
      const originalFilter = filter;
      filter = '';
      originalFilter.split(namePartDelimiters).forEach(part => {
        if (part) {
          filter += (filter === '' ? 'inname:' : ' AND inname:') + part;
        }
      });
    }
    // Check if filter is now empty which could be either because the user did
    // not provide it or because the user provided only a split character.
    if (!filter) {
      filter = defaultFilter;
    }

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

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

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

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

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

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

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

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

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

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

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

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

  /**
   * @param {string} filter
   * @param {number} pluginsPerPage
   * @param {number=} opt_offset
   * @param {?function(?Response, string=)=} opt_errFn
   * @return {!Promise<?Object>}
   */
  getPlugins(filter, pluginsPerPage, opt_offset, opt_errFn) {
    const offset = opt_offset || 0;
    const encodedFilter = this._computeFilter(filter);
    const n = pluginsPerPage + 1;
    const url = `/plugins/?all&n=${n}&S=${offset}${encodedFilter}`;
    return this._restApiHelper.fetchJSON({
      url,
      errFn: opt_errFn,
      anonymizedUrl: '/plugins/?all',
    });
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return promise.then(res => {
      if (!res.ok) { return res; }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return this._getChangeURLAndFetch(req);
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return promise;
  }

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

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

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

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

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

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

    return Promise.all([promiseA, promiseB]).then(results => {
      const baseImage = results[0];
      const revisionImage = results[1];

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

      return {baseImage, revisionImage};
    });
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  /**
   * Modify the given create draft request promise so that it fails and throws
   * an error if the response bears HTTP status 200 instead of HTTP 201.
   *
   * @see Issue 7763
   * @param {Promise} promise The original promise.
   * @return {Promise} The modified promise.
   */
  _failForCreate200(promise) {
    return promise.then(result => {
      if (result.status === 200) {
        // Read the response headers into an object representation.
        const headers = Array.from(result.headers.entries())
            .reduce((obj, [key, val]) => {
              if (!HEADER_REPORTING_BLOCK_REGEX.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);
