/**
 * @license
 * Copyright (C) 2019 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(window) {
  'use strict';

  const JSON_PREFIX = ')]}\'';

  /**
   * 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();
      if (window.INITIAL_DATA != undefined) {
        // Put all data shipped with index.html into the cache. This makes it
        // so that we spare more round trips to the server when the app loads
        // initially.
        Object
            .entries(window.INITIAL_DATA)
            .forEach(e => this._cache().set(e[0], e[1]));
      }
    }

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

    invalidatePrefix(prefix) {
      const newMap = new Map();
      for (const [key, value] of this._cache().entries()) {
        if (!key.startsWith(prefix)) {
          newMap.set(key, value);
        }
      }
      this._data.set(window.CANONICAL_PATH, newMap);
    }
  }

  class FetchPromisesCache {
    constructor() {
      this._data = {};
    }

    has(key) {
      return !!this._data[key];
    }

    get(key) {
      return this._data[key];
    }

    set(key, value) {
      this._data[key] = value;
    }

    invalidatePrefix(prefix) {
      const newData = {};
      Object.entries(this._data).forEach(([key, value]) => {
        if (!key.startsWith(prefix)) {
          newData[key] = value;
        }
      });
      this._data = newData;
    }
  }

  class GrRestApiHelper {
    /**
     * @param {SiteBasedCache} cache
     * @param {object} auth
     * @param {FetchPromisesCache} fetchPromisesCache
     * @param {object} restApiInterface
     */
    constructor(cache, auth, fetchPromisesCache,
        restApiInterface) {
      this._cache = cache;// TODO: make it public
      this._auth = auth;
      this._fetchPromisesCache = fetchPromisesCache;
      this._restApiInterface = restApiInterface;
    }

    /**
     * Wraps calls to the underlying authenticated fetch function (_auth.fetch)
     * with timing and logging.
     *
     * @param {Gerrit.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 ? res.status : null));

      // 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 {Gerrit.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 endTime = Date.now();
      const elapsed = (endTime - startTime);
      const startAt = new Date(startTime);
      const endAt = new Date(endTime);
      console.log([
        'HTTP',
        status,
        method,
        elapsed + 'ms',
        req.anonymizedUrl || req.url,
        `(${startAt.toISOString()}, ${endAt.toISOString()})`,
      ].join(' '));
      if (req.anonymizedUrl) {
        this.dispatchEvent(new CustomEvent('rpc-log', {
          detail: {status, method, elapsed, anonymizedUrl: req.anonymizedUrl},
          composed: true, bubbles: true,
        }));
      }
    }

    /**
     * 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 {Gerrit.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 => {
            if (req.errFn) {
              req.errFn.call(undefined, null, err);
            } else {
              this.dispatchEvent(new CustomEvent('network-error', {
                detail: {error: err},
                composed: true, bubbles: true,
              }));
            }
            throw err;
          });
    }

    /**
     * Fetch JSON from url provided.
     * Returns a Promise that resolves to a parsed response.
     * Same as {@link fetchRawJSON}, plus error handling.
     *
     * @param {Gerrit.FetchJSONRequest} req
     * @param {boolean} noAcceptHeader - don't add default accept json header
     */
    fetchJSON(req, noAcceptHeader) {
      if (!noAcceptHeader) {
        req = this.addAcceptJsonHeader(req);
      }
      return this.fetchRawJSON(req).then(response => {
        if (!response) {
          return;
        }
        if (!response.ok) {
          if (req.errFn) {
            req.errFn.call(null, response);
            return;
          }
          this.dispatchEvent(new CustomEvent('server-error', {
            detail: {request: req, response},
            composed: true, bubbles: true,
          }));
          return;
        }
        return response && this.getResponseObject(response);
      });
    }

    /**
     * @param {string} url
     * @param {?Object|string=} 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));
    }

    /**
     * @param {Gerrit.FetchJSONRequest} req
     * @return {Gerrit.FetchJSONRequest}
     */
    addAcceptJsonHeader(req) {
      if (!req.fetchOptions) req.fetchOptions = {};
      if (!req.fetchOptions.headers) req.fetchOptions.headers = new Headers();
      if (!req.fetchOptions.headers.has('Accept')) {
        req.fetchOptions.headers.append('Accept', 'application/json');
      }
      return req;
    }

    getBaseUrl() {
      return this._restApiInterface.getBaseUrl();
    }

    dispatchEvent(type, detail) {
      return this._restApiInterface.dispatchEvent(type, detail);
    }

    /**
     * @param {Gerrit.FetchJSONRequest} req
     */
    fetchCacheURL(req) {
      if (this._fetchPromisesCache.has(req.url)) {
        return this._fetchPromisesCache.get(req.url);
      }
      // TODO(andybons): Periodic cache invalidation.
      if (this._cache.has(req.url)) {
        return Promise.resolve(this._cache.get(req.url));
      }
      this._fetchPromisesCache.set(req.url,
          this.fetchJSON(req)
              .then(response => {
                if (response !== undefined) {
                  this._cache.set(req.url, response);
                }
                this._fetchPromisesCache.set(req.url, undefined);
                return response;
              })
              .catch(err => {
                this._fetchPromisesCache.set(req.url, undefined);
                throw err;
              })
      );
      return this._fetchPromisesCache.get(req.url);
    }

    /**
     * Send an XHR.
     *
     * @param {Gerrit.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.dispatchEvent(new CustomEvent('server-error', {
                detail: {request: fetchReq, response},
                composed: true, bubbles: true,
              }));
            }
            return response;
          })
          .catch(err => {
            this.dispatchEvent(new CustomEvent('network-error', {
              detail: {error: err},
              composed: true, bubbles: true,
            }));
            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;
    }

    /**
     * @param {string} prefix
     */
    invalidateFetchPromisesPrefix(prefix) {
      this._fetchPromisesCache.invalidatePrefix(prefix);
      this._cache.invalidatePrefix(prefix);
    }
  }

  window.SiteBasedCache = SiteBasedCache;
  window.FetchPromisesCache = FetchPromisesCache;
  window.GrRestApiHelper = GrRestApiHelper;
})(window);
