/**
 * @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 Defs = {};

  /**
   * @typedef {{
   *    basePatchNum: (string|number),
   *    patchNum: (number),
   * }}
   */
  Defs.patchRange;

  /**
   * @typedef {{
   *    url: string,
   *    fetchOptions: (Object|null|undefined),
   *    anonymizedUrl: (string|undefined),
   * }}
   */
  Defs.FetchRequest;

  /**
   * Object to describe a request for passing into _fetchJSON or _fetchRawJSON.
   * - url is the URL for the request (excluding get params)
   * - errFn is a function to invoke when the request fails.
   * - cancelCondition is a function that, if provided and returns true, will
   *     cancel the response after it resolves.
   * - params is a key-value hash to specify get params for the request URL.
   * @typedef {{
   *    url: string,
   *    errFn: (function(?Response, string=)|null|undefined),
   *    cancelCondition: (function()|null|undefined),
   *    params: (Object|null|undefined),
   *    fetchOptions: (Object|null|undefined),
   *    anonymizedUrl: (string|undefined),
   *    reportUrlAsIs: (boolean|undefined),
   * }}
   */
  Defs.FetchJSONRequest;

  /**
   * @typedef {{
   *   changeNum: (string|number),
   *   endpoint: string,
   *   patchNum: (string|number|null|undefined),
   *   errFn: (function(?Response, string=)|null|undefined),
   *   params: (Object|null|undefined),
   *   fetchOptions: (Object|null|undefined),
   *   anonymizedEndpoint: (string|undefined),
   *   reportEndpointAsIs: (boolean|undefined),
   * }}
   */
  Defs.ChangeFetchRequest;

  /**
   * Object to describe a request for passing into _send.
   * - method is the HTTP method to use in the request.
   * - url is the URL for the request
   * - body is a request payload.
   *     TODO (beckysiegel) remove need for number at least.
   * - errFn is a function to invoke when the request fails.
   * - cancelCondition is a function that, if provided and returns true, will
   *   cancel the response after it resolves.
   * - contentType is the content type of the body.
   * - headers is a key-value hash to describe HTTP headers for the request.
   * - parseResponse states whether the result should be parsed as a JSON
   *     object using getResponseObject.
   * @typedef {{
   *   method: string,
   *   url: string,
   *   body: (string|number|Object|null|undefined),
   *   errFn: (function(?Response, string=)|null|undefined),
   *   contentType: (string|null|undefined),
   *   headers: (Object|undefined),
   *   parseResponse: (boolean|undefined),
   *   anonymizedUrl: (string|undefined),
   *   reportUrlAsIs: (boolean|undefined),
   * }}
   */
  Defs.SendRequest;

  /**
   * @typedef {{
   *   changeNum: (string|number),
   *   method: string,
   *   patchNum: (string|number|undefined),
   *   endpoint: string,
   *   body: (string|number|Object|null|undefined),
   *   errFn: (function(?Response, string=)|null|undefined),
   *   contentType: (string|null|undefined),
   *   headers: (Object|undefined),
   *   parseResponse: (boolean|undefined),
   *   anonymizedEndpoint: (string|undefined),
   *   reportEndpointAsIs: (boolean|undefined),
   * }}
   */
  Defs.ChangeSendRequest;

  const DiffViewMode = {
    SIDE_BY_SIDE: 'SIDE_BY_SIDE',
    UNIFIED: 'UNIFIED_DIFF',
  };
  const JSON_PREFIX = ')]}\'';
  const MAX_PROJECT_RESULTS = 25;
  const MAX_UNIFIED_DEFAULT_WINDOW_WIDTH_PX = 900;
  const PARENT_PATCH_NUM = 'PARENT';
  const FAILED_TO_FETCH_ERROR = 'Failed to fetch';

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

  /**
   * Wrapper around Map for caching server responses. Site-based so that
   * changes to CANONICAL_PATH will result in a different cache going into
   * effect.
   */
  class SiteBasedCache {
    constructor() {
      // Container of per-canonical-path caches.
      this._data = new Map();
    }

    // Returns the cache for the current canonical path.
    _cache() {
      if (!this._data.has(window.CANONICAL_PATH)) {
        this._data.set(window.CANONICAL_PATH, new Map());
      }
      return this._data.get(window.CANONICAL_PATH);
    }

    has(key) {
      return this._cache().has(key);
    }

    get(key) {
      return this._cache().get(key);
    }

    set(key, value) {
      this._cache().set(key, value);
    }

    delete(key) {
      this._cache().delete(key);
    }
  }

  Polymer({
    is: 'gr-rest-api-interface',

    behaviors: [
      Gerrit.PathListBehavior,
      Gerrit.PatchSetBehavior,
      Gerrit.RESTClientBehavior,
    ],

    /**
     * Fired when an server error occurs.
     *
     * @event server-error
     */

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

    /**
     * Fired when credentials were rejected by server (e.g. expired).
     *
     * @event auth-error
     */

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

    properties: {
      _cache: {
        type: Object,
        value: new SiteBasedCache(), // Shared across instances.
      },
      _credentialCheck: {
        type: Object,
        value: {checking: false}, // Shared across instances.
      },
      _sharedFetchPromises: {
        type: Object,
        value: {}, // Intentional to share the object 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.
      },
      _auth: {
        type: Object,
        value: Gerrit.Auth, // Share across instances.
      },
    },

    JSON_PREFIX,

    /**
     * Wraps calls to the underlying authenticated fetch function (_auth.fetch)
     * with timing and logging.
     * @param {Defs.FetchRequest} req
     */
    _fetch(req) {
      const start = Date.now();
      const xhr = this._auth.fetch(req.url, req.fetchOptions);

      // Log the call after it completes.
      xhr.then(res => this._logCall(req, start, res.status));

      // Return the XHR directly (without the log).
      return xhr;
    },

    /**
     * Log information about a REST call. Because the elapsed time is determined
     * by this method, it should be called immediately after the request
     * finishes.
     * @param {Defs.FetchRequest} req
     * @param {number} startTime the time that the request was started.
     * @param {number} status the HTTP status of the response. The status value
     *     is used here rather than the response object so there is no way this
     *     method can read the body stream.
     */
    _logCall(req, startTime, status) {
      const method = (req.fetchOptions && req.fetchOptions.method) ?
          req.fetchOptions.method : 'GET';
      const elapsed = (Date.now() - startTime);
      console.log([
        'HTTP',
        status,
        method,
        elapsed + 'ms',
        req.anonymizedUrl || req.url,
      ].join(' '));
      if (req.anonymizedUrl) {
        this.fire('rpc-log',
            {status, method, elapsed, anonymizedUrl: req.anonymizedUrl});
      }
    },

    /**
     * Fetch JSON from url provided.
     * Returns a Promise that resolves to a native Response.
     * Doesn't do error checking. Supports cancel condition. Performs auth.
     * Validates auth expiry errors.
     * @param {Defs.FetchJSONRequest} req
     */
    _fetchRawJSON(req) {
      const urlWithParams = this._urlWithParams(req.url, req.params);
      const fetchReq = {
        url: urlWithParams,
        fetchOptions: req.fetchOptions,
        anonymizedUrl: req.reportUrlAsIs ? urlWithParams : req.anonymizedUrl,
      };
      return this._fetch(fetchReq).then(res => {
        if (req.cancelCondition && req.cancelCondition()) {
          res.body.cancel();
          return;
        }
        return res;
      }).catch(err => {
        const isLoggedIn = !!this._cache.get('/accounts/self/detail');
        if (isLoggedIn && err && err.message === FAILED_TO_FETCH_ERROR) {
          this.checkCredentials();
          return;
        }
        if (req.errFn) {
          req.errFn.call(undefined, null, err);
        } else {
          this.fire('network-error', {error: err});
        }
        throw err;
      });
    },

    /**
     * Fetch JSON from url provided.
     * Returns a Promise that resolves to a parsed response.
     * Same as {@link _fetchRawJSON}, plus error handling.
     * @param {Defs.FetchJSONRequest} req
     */
    _fetchJSON(req) {
      return this._fetchRawJSON(req).then(response => {
        if (!response) {
          return;
        }
        if (!response.ok) {
          if (req.errFn) {
            req.errFn.call(null, response);
            return;
          }
          this.fire('server-error', {request: req, response});
          return;
        }
        return response && this.getResponseObject(response);
      });
    },

    /**
     * @param {string} url
     * @param {?Object=} opt_params URL params, key-value hash.
     * @return {string}
     */
    _urlWithParams(url, opt_params) {
      if (!opt_params) { return this.getBaseUrl() + url; }

      const params = [];
      for (const p in opt_params) {
        if (!opt_params.hasOwnProperty(p)) { continue; }
        if (opt_params[p] == null) {
          params.push(encodeURIComponent(p));
          continue;
        }
        for (const value of [].concat(opt_params[p])) {
          params.push(`${encodeURIComponent(p)}=${encodeURIComponent(value)}`);
        }
      }
      return this.getBaseUrl() + url + '?' + params.join('&');
    },

    /**
     * @param {!Object} response
     * @return {?}
     */
    getResponseObject(response) {
      return this._readResponsePayload(response)
          .then(payload => payload.parsed);
    },

    /**
     * @param {!Object} response
     * @return {!Object}
     */
    _readResponsePayload(response) {
      return response.text().then(text => {
        let result;
        try {
          result = this._parsePrefixedJSON(text);
        } catch (_) {
          result = null;
        }
        return {parsed: result, raw: text};
      });
    },

    /**
     * @param {string} source
     * @return {?}
     */
    _parsePrefixedJSON(source) {
      return JSON.parse(source.substring(JSON_PREFIX.length));
    },

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

      return this._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 encodeName = encodeURIComponent(repo);
      return this._send({
        method: 'PUT',
        url: `/projects/${encodeName}/config`,
        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._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._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._send({
        method: 'PUT',
        url: `/groups/${encodeName}`,
        body: config,
        errFn: opt_errFn,
        anonymizedUrl: '/groups/*',
      });
    },

    getGroupConfig(group, opt_errFn) {
      return this._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._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._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._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._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&q=${encodeName}`,
        anonymizedUrl: '/groups/owned&q=*',
      };
      return this._fetchSharedCacheURL(req)
          .then(configs => configs.hasOwnProperty(groupName));
    },

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

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

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

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

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

    saveGroupOptions(groupId, options) {
      const encodeId = encodeURIComponent(groupId);
      return this._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._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._send(req).then(response => {
        if (response.ok) {
          return this.getResponseObject(response);
        }
      });
    },

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

    deleteIncludedGroup(groupName, includedGroup) {
      const encodeName = encodeURIComponent(groupName);
      const encodeIncludedGroup = encodeURIComponent(includedGroup);
      return this._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._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._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._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._fetchJSON({
        url: '/accounts/self/external.ids',
        reportUrlAsIs: true,
      });
    },

    deleteAccountIdentity(id) {
      return this._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._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._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._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._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._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._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._send(req)
          .then(newStatus => this._updateCachedAccount({status: newStatus}));
    },

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

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

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

    saveAccountAgreement(name) {
      return this._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 => { return encodeURIComponent(param); })
            .join('&q=');
      }
      return this._fetchSharedCacheURL({
        url: '/accounts/self/capabilities' + queryString,
        anonymizedUrl: '/accounts/self/capabilities?q=*',
      });
    },

    getLoggedIn() {
      return this.getAccount().then(account => {
        return account != null;
      });
    },

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

    checkCredentials() {
      if (this._credentialCheck.checking) {
        return;
      }
      this._credentialCheck.checking = true;
      const req = {url: '/accounts/self/detail', reportUrlAsIs: true};
      // Skip the REST response cache.
      return this._fetchRawJSON(req).then(res => {
        if (!res) { return; }
        if (res.status === 403) {
          this.fire('auth-error');
          this._cache.delete('/accounts/self/detail');
        } else if (res.ok) {
          return this.getResponseObject(res);
        }
      }).then(res => {
        this._credentialCheck.checking = false;
        if (res) {
          this._cache.delete('/accounts/self/detail');
        }
        return res;
      }).catch(err => {
        this._credentialCheck.checking = false;
      });
    },

    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()) {
              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._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._send({
        method: 'POST',
        url: '/accounts/self/watched.projects:delete',
        body: projects,
        errFn: opt_errFn,
        reportUrlAsIs: true,
      });
    },

    /**
     * @param {Defs.FetchJSONRequest} req
     */
    _fetchSharedCacheURL(req) {
      if (this._sharedFetchPromises[req.url]) {
        return this._sharedFetchPromises[req.url];
      }
      // TODO(andybons): Periodic cache invalidation.
      if (this._cache.has(req.url)) {
        return Promise.resolve(this._cache.get(req.url));
      }
      this._sharedFetchPromises[req.url] = this._fetchJSON(req)
          .then(response => {
            if (response !== undefined) {
              this._cache.set(req.url, response);
            }
            this._sharedFetchPromises[req.url] = undefined;
            return response;
          }).catch(err => {
            this._sharedFetchPromises[req.url] = undefined;
            throw err;
          });
      return this._sharedFetchPromises[req.url];
    },

    _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._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) {
      const options = [
        this.ListChangesOption.ALL_COMMITS,
        this.ListChangesOption.ALL_REVISIONS,
        this.ListChangesOption.CHANGE_ACTIONS,
        this.ListChangesOption.CURRENT_ACTIONS,
        this.ListChangesOption.DETAILED_LABELS,
        this.ListChangesOption.DOWNLOAD_COMMANDS,
        this.ListChangesOption.MESSAGES,
        this.ListChangesOption.SUBMITTABLE,
        this.ListChangesOption.WEB_LINKS,
        this.ListChangesOption.SKIP_MERGEABLE,
      ];
      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 params = this.listChangesOptionsToHex(
          this.ListChangesOption.ALL_COMMITS,
          this.ListChangesOption.ALL_REVISIONS,
          this.ListChangesOption.SKIP_MERGEABLE
      );
      return this._getChangeDetail(changeNum, params, opt_errFn,
          opt_cancelCondition);
    },

    /**
     * @param {number|string} changeNum
     * @param {function(?Response, string=)=} opt_errFn
     * @param {function()=} opt_cancelCondition
     */
    _getChangeDetail(changeNum, params, opt_errFn, opt_cancelCondition) {
      return this.getChangeActionURL(changeNum, null, '/detail').then(url => {
        const urlWithParams = this._urlWithParams(url, params);
        const req = {
          url,
          errFn: opt_errFn,
          cancelCondition: opt_cancelCondition,
          params: {O: params},
          fetchOptions: this._etags.getOptions(urlWithParams),
          anonymizedUrl: '/changes/*~*/detail?O=' + params,
        };
        return this._fetchRawJSON(req).then(response => {
          if (response && response.status === 304) {
            return Promise.resolve(this._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._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 {Defs.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 {Defs.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 {Defs.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 => {
        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) {
      const params = {n: 10};
      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
     * @return {!Promise<?Object>}
     */
    getGroups(filter, groupsPerPage, opt_offset) {
      const offset = opt_offset || 0;

      return this._fetchSharedCacheURL({
        url: `/groups/?n=${groupsPerPage + 1}&S=${offset}` +
            this._computeFilter(filter),
        anonymizedUrl: '/groups/?*',
      });
    },

    /**
     * @param {string} filter
     * @param {number} reposPerPage
     * @param {number=} opt_offset
     * @return {!Promise<?Object>}
     */
    getRepos(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);

      // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
      // supports it.
      return this._fetchSharedCacheURL({
        url: `/projects/?n=${reposPerPage + 1}&S=${offset}` +
            `&query=${encodedFilter}`,
        anonymizedUrl: '/projects/?*',
      });
    },

    setRepoHead(repo, ref) {
      // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
      // supports it.
      return this._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._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._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._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._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._send({
        method: 'POST',
        url: `/projects/${encodeURIComponent(repoName)}/access`,
        body: repoInfo,
        anonymizedUrl: '/projects/*/access',
      });
    },

    setRepoAccessRightsForReview(projectName, projectInfo) {
      return this._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._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._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._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._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 is:mergeable conflicts:' + changeNum,
      };
      return this._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._fetchJSON({
        url: '/changes/',
        params,
        anonymizedUrl: '/changes/change:*',
      });
    },

    getChangesWithSameTopic(topic) {
      const options = this.listChangesOptionsToHex(
          this.ListChangesOption.LABELS,
          this.ListChangesOption.CURRENT_REVISION,
          this.ListChangesOption.CURRENT_COMMIT,
          this.ListChangesOption.DETAILED_LABELS
      );
      const params = {
        O: options,
        q: 'status:open topic:' + topic,
      };
      return this._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]) => {
        return this._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._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/*',
      });
    },

    // 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._send({
          method: starred ? 'PUT' : 'DELETE',
          url,
          anonymizedUrl: '/accounts/self/starred.changes/*',
        });
      });
    },

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

    /**
     * Send an XHR.
     * @param {Defs.SendRequest} req
     * @return {Promise}
     */
    _send(req) {
      const options = {method: req.method};
      if (req.body) {
        options.headers = new Headers();
        options.headers.set(
            'Content-Type', req.contentType || 'application/json');
        options.body = typeof req.body === 'string' ?
            req.body : JSON.stringify(req.body);
      }
      if (req.headers) {
        if (!options.headers) { options.headers = new Headers(); }
        for (const header in req.headers) {
          if (!req.headers.hasOwnProperty(header)) { continue; }
          options.headers.set(header, req.headers[header]);
        }
      }
      const url = req.url.startsWith('http') ?
          req.url : this.getBaseUrl() + req.url;
      const fetchReq = {
        url,
        fetchOptions: options,
        anonymizedUrl: req.reportUrlAsIs ? url : req.anonymizedUrl,
      };
      const xhr = this._fetch(fetchReq).then(response => {
        if (!response.ok) {
          if (req.errFn) {
            return req.errFn.call(undefined, response);
          }
          this.fire('server-error', {request: fetchReq, response});
        }
        return response;
      }).catch(err => {
        this.fire('network-error', {error: err});
        if (req.errFn) {
          return req.errFn.call(undefined, null, err);
        } else {
          throw err;
        }
      });

      if (req.parseResponse) {
        return xhr.then(res => this.getResponseObject(res));
      }

      return xhr;
    },

    /**
     * Public version of the _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._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`;

      return this._getChangeURLAndFetch({
        changeNum,
        endpoint,
        patchNum,
        errFn: opt_errFn,
        params,
        anonymizedEndpoint: '/files/*/diff',
      });
    },

    /**
     * @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) => {
        return 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 => {
        return 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(() => {
        return 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._fetchJSON({
        url: '/projects/' + encodeURIComponent(project) +
            '/commits/' + encodeURIComponent(commit),
        anonymizedUrl: '/projects/*/comments/*',
      });
    },

    _fetchB64File(url) {
      return this._fetch({url: this.getBaseUrl() + url})
          .then(response => {
            if (!response.ok) { return Promise.reject(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._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._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: 'plain/text',
        reportUrlAsIs: true,
      };
      return this._send(req)
          .then(response => {
            if (response.status < 200 && response.status >= 300) {
              return Promise.reject();
            }
            return this.getResponseObject(response);
          })
          .then(obj => {
            if (!obj.valid) { return Promise.reject(); }
            return obj;
          });
    },

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

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

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

    deleteAccountGPGKey(id) {
      return this._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._send(req).then(response => {
        if (response.status === 204) {
          return 'Email confirmed successfully.';
        }
        return null;
      });
    },

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

    getTopMenus(opt_errFn) {
      return this._fetchJSON({
        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 => {
            return 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._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 {Defs.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 => {
        return this._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 {Defs.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 => {
        return this._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._send({
        method: 'POST',
        url: '/accounts/self/drafts:delete',
        body: {query},
      });
    },
  });
})();
