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

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

  const JSON_PREFIX = ')]}\'';
  const FAILED_TO_FETCH_ERROR = 'Failed to fetch';

  /**
   * 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} credentialCheck
     * @param {object} restApiInterface
     */
    constructor(cache, auth, fetchPromisesCache, credentialCheck,
        restApiInterface) {
      this._cache = cache;// TODO: make it public
      this._auth = auth;
      this._fetchPromisesCache = fetchPromisesCache;
      this._credentialCheck = credentialCheck;
      this._restApiInterface = restApiInterface;
    }

    /**
     * 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 ? 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 {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 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.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();
        } else {
          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) {
      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.fire('server-error', {request: req, response});
          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 {Defs.FetchJSONRequest} req
     * @return {Defs.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();
    }

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

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

    checkCredentials() {
      if (this._credentialCheck.checking) {
        return;
      }
      this._credentialCheck.checking = true;
      let req = {url: '/accounts/self/detail', reportUrlAsIs: true};
      req = this.addAcceptJsonHeader(req);
      // 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.set('/accounts/self/detail', res);
        }
        return res;
      }).catch(err => {
        this._credentialCheck.checking = false;
        if (err && err.message === FAILED_TO_FETCH_ERROR) {
          this.fire('auth-error');
          this._cache.delete('/accounts/self/detail');
        }
      });
    }

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

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

