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

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

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

const Requests = {
  SEND_DIFF_DRAFT: 'sendDiffDraft',
};

const CREATE_DRAFT_UNEXPECTED_STATUS_MESSAGE =
    'Saving draft resulted in HTTP 200 (OK) but expected HTTP 201 (Created)';
const HEADER_REPORTING_BLACKLIST = /^set-cookie$/i;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  saveChangeReviewed(changeNum, reviewed) {
    return this._getChangeURLAndSend({
      changeNum,
      method: 'PUT',
      endpoint: reviewed ? '/reviewed' : '/unreviewed',
    });
  }

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

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

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

    return this._getChangeURLAndFetch(req);
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return promise;
  }

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

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

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

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

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

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

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

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

      return {baseImage, revisionImage};
    });
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  /**
   * Modify the given create draft request promise so that it fails and throws
   * an error if the response bears HTTP status 200 instead of HTTP 201.
   *
   * @see Issue 7763
   * @param {Promise} promise The original promise.
   * @return {Promise} The modified promise.
   */
  _failForCreate200(promise) {
    return promise.then(result => {
      if (result.status === 200) {
        // Read the response headers into an object representation.
        const headers = Array.from(result.headers.entries())
            .reduce((obj, [key, val]) => {
              if (!HEADER_REPORTING_BLACKLIST.test(key)) {
                obj[key] = val;
              }
              return obj;
            }, {});
        const err = new Error([
          CREATE_DRAFT_UNEXPECTED_STATUS_MESSAGE,
          JSON.stringify(headers),
        ].join('\n'));
        // Throw the error so that it is caught by gr-reporting.
        throw err;
      }
      return result;
    });
  }

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

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

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

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

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

customElements.define(GrRestApiInterface.is, GrRestApiInterface);
