/**
 * @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.
 */
(function() {
  'use strict';

  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/*';

  /**
   * @appliesMixin Gerrit.FireMixin
   * @appliesMixin Gerrit.PathListMixin
   * @appliesMixin Gerrit.PatchSetMixin
   * @appliesMixin Gerrit.RESTClientMixin
   * @extends Polymer.Element
   */
  class GrRestApiInterface extends Polymer.mixinBehaviors( [
    Gerrit.FireBehavior,
    Gerrit.PathListBehavior,
    Gerrit.PatchSetBehavior,
    Gerrit.RESTClientBehavior,
  ], Polymer.GestureEventListeners(
      Polymer.LegacyElementMixin(
          Polymer.Element))) {
    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 = Gerrit.Auth;
      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} 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) {
      const options = opt_options || this.listChangesOptionsToHex(
          this.ListChangesOption.LABELS,
          this.ListChangesOption.DETAILED_ACCOUNTS
      );
      // 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;
      }
      const iterateOverChanges = arr => {
        for (const change of (arr || [])) {
          this._maybeInsertInLookup(change);
        }
      };
      const req = {
        url: '/changes/',
        params,
        reportUrlAsIs: true,
      };
      return this._restApiHelper.fetchJSON(req).then(response => {
        // 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) {
      // 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_MERGEABLE,
        this.ListChangesOption.SKIP_DIFFSTAT,
      ];
      return this.getConfig(false).then(config => {
        if (config.receive && config.receive.enable_signed_push) {
          options.push(this.ListChangesOption.PUSH_CERTIFICATES);
        }
        const optionsHex = this.listChangesOptionsToHex(...options);
        return this._getChangeDetail(
            changeNum, optionsHex, opt_errFn, opt_cancelCondition)
            .then(GrReviewerUpdatesParser.parse);
      });
    }

    /**
     * @param {number|string} changeNum
     * @param {function(?Response, string=)=} opt_errFn
     * @param {function()=} opt_cancelCondition
     */
    getDiffChangeDetail(changeNum, opt_errFn, opt_cancelCondition) {
      const optionsHex = this.listChangesOptionsToHex(
          this.ListChangesOption.ALL_COMMITS,
          this.ListChangesOption.ALL_REVISIONS,
          this.ListChangesOption.SKIP_MERGEABLE,
          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};
        let req = {
          url,
          errFn: opt_errFn,
          cancelCondition: opt_cancelCondition,
          params,
          fetchOptions: this._etags.getOptions(urlWithParams),
          anonymizedUrl: '/changes/*~*/detail?O=' + optionsHex,
        };
        req = this._restApiHelper.addAcceptJsonHeader(req);
        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.fire('server-error', {request: req, response});
            }
            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);
    }

    /**
     * The closure compiler doesn't realize this.specialFilePathCompare is
     * valid.
     *
     * @suppress {checkTypes}
     */
    getChangeFilePathsAsSpeciallySortedArray(changeNum, patchRange) {
      return this.getChangeFiles(changeNum, patchRange).then(files => {
        if (!files) return;
        return Object.keys(files).sort(this.specialFilePathCompare);
      });
    }

    getChangeRevisionActions(changeNum, patchNum) {
      const req = {
        changeNum,
        endpoint: '/actions',
        patchNum,
        reportEndpointAsIs: true,
      };
      return this._getChangeURLAndFetch(req).then(revisionActions => {
        // The rebase button on change screen is always enabled.
        if (revisionActions.rebase) {
          revisionActions.rebase.rebaseOnCurrent =
              !!revisionActions.rebase.enabled;
          revisionActions.rebase.enabled = true;
        }
        return revisionActions;
      });
    }

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

    /**
     * @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.fire('server-error', {res}); }
        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/*',
      });
    }

    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,
      });
    }

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

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

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

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

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

      return this._getChangeURLAndFetch(req);
    }

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

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

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

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

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

    /**
     * @param {number|string} changeNum
     * @param {string} endpoint
     * @param {number|string=} opt_basePatchNum
     * @param {number|string=} opt_patchNum
     * @param {string=} opt_path
     * @return {!Promise<!Object>}
     */
    _getDiffComments(changeNum, endpoint, opt_basePatchNum,
        opt_patchNum, opt_path) {
      /**
       * Fetches the comments for a given patchNum.
       * Helper function to make promises more legible.
       *
       * @param {string|number=} opt_patchNum
       * @return {!Promise<!Object>} Diff comments response.
       */
      const fetchComments = opt_patchNum => this._getChangeURLAndFetch({
        changeNum,
        endpoint,
        patchNum: opt_patchNum,
        reportEndpointAsIs: true,
      });

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      return promise;
    }

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

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

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

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

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

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

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

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

        return {baseImage, revisionImage};
      });
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      const onError = response => {
        // Fire a page error so that the visual 404 is displayed.
        this.fire('page-error', {response});
      };

      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) {
      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,
          }));
    }

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