/**
 * @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.
 */
import {getBaseUrl} from '../../../../utils/url-util.js';

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

export 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;
  }
}

export 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 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 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;
  }

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