/**
 * @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';
import {CancelConditionCallback} from '../../../../services/gr-rest-api/gr-rest-api';
import {
  AuthRequestInit,
  AuthService,
} from '../../../../services/gr-auth/gr-auth';
import {
  AccountDetailInfo,
  EmailInfo,
  ParsedJSON,
  RequestPayload,
} from '../../../../types/common';
import {HttpMethod} from '../../../../constants/constants';
import {RpcLogEventDetail} from '../../../../types/events';
import {fireNetworkError, fireServerError} from '../../../../utils/event-util';
import {FetchRequest} from '../../../../types/types';
import {ErrorCallback} from '../../../../api/rest';

export const JSON_PREFIX = ")]}'";

export interface ResponsePayload {
  // TODO(TS): readResponsePayload can assign null to the parsed property if
  // it can't parse input data. However polygerrit assumes in many places
  // that the parsed property can't be null. We should update
  // readResponsePayload method and reject a promise instead of assigning
  // null to the parsed property
  parsed: ParsedJSON; // Can be null!!! See comment above
  raw: string;
}

export function readResponsePayload(
  response: Response
): Promise<ResponsePayload> {
  return response.text().then(text => {
    let result;
    try {
      result = parsePrefixedJSON(text);
    } catch (_) {
      result = null;
    }
    // TODO(TS): readResponsePayload can assign null to the parsed property if
    // it can't parse input data. However polygerrit assumes in many places
    // that the parsed property can't be null. We should update
    // readResponsePayload method and reject a promise instead of assigning
    // null to the parsed property
    return {parsed: result!, raw: text};
  });
}

export function parsePrefixedJSON(jsonWithPrefix: string): ParsedJSON {
  return JSON.parse(jsonWithPrefix.substring(JSON_PREFIX.length)) as ParsedJSON;
}

/**
 * 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 {
  // TODO(TS): Type looks unusual. Fix it.
  // Container of per-canonical-path caches.
  private readonly data = new Map<
    string | undefined,
    unknown | Map<string, ParsedJSON | null>
  >();

  constructor() {
    if (window.INITIAL_DATA) {
      // 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] as unknown) as ParsedJSON)
      );
    }
  }

  // Returns the cache for the current canonical path.
  _cache(): Map<string, unknown> {
    if (!this.data.has(window.CANONICAL_PATH)) {
      this.data.set(
        window.CANONICAL_PATH,
        new Map<string, ParsedJSON | null>()
      );
    }
    return this.data.get(window.CANONICAL_PATH) as Map<
      string,
      ParsedJSON | null
    >;
  }

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

  get(key: '/accounts/self/emails'): EmailInfo[] | null;

  get(key: '/accounts/self/detail'): AccountDetailInfo[] | null;

  get(key: string): ParsedJSON | null;

  get(key: string): unknown {
    return this._cache().get(key);
  }

  set(key: '/accounts/self/emails', value: EmailInfo[]): void;

  set(key: '/accounts/self/detail', value: AccountDetailInfo[]): void;

  set(key: string, value: ParsedJSON | null): void;

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

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

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

type FetchPromisesCacheData = {
  [url: string]: Promise<ParsedJSON | undefined> | undefined;
};

export class FetchPromisesCache {
  private data: FetchPromisesCacheData;

  constructor() {
    this.data = {};
  }

  public testOnlyGetData() {
    return this.data;
  }

  /**
   * @return true only if a value for a key sets and it is not undefined
   */
  has(key: string): boolean {
    return !!this.data[key];
  }

  get(key: string) {
    return this.data[key];
  }

  /**
   * @param value a Promise to store in the cache. Pass undefined value to
   *     mark key as deleted.
   */
  set(key: string, value: Promise<ParsedJSON | undefined> | undefined) {
    this.data[key] = value;
  }

  invalidatePrefix(prefix: string) {
    const newData: FetchPromisesCacheData = {};
    Object.entries(this.data).forEach(([key, value]) => {
      if (!key.startsWith(prefix)) {
        newData[key] = value;
      }
    });
    this.data = newData;
  }
}
export type FetchParams = {
  [name: string]: string[] | string | number | boolean | undefined | null;
};

interface SendRequestBase {
  method: HttpMethod | undefined;
  body?: RequestPayload;
  contentType?: string;
  headers?: Record<string, string>;
  url: string;
  reportUrlAsIs?: boolean;
  anonymizedUrl?: string;
  errFn?: ErrorCallback;
}

export interface SendRawRequest extends SendRequestBase {
  parseResponse?: false | null;
}

export interface SendJSONRequest extends SendRequestBase {
  parseResponse: true;
}

export type SendRequest = SendRawRequest | SendJSONRequest;

export interface FetchJSONRequest extends FetchRequest {
  reportUrlAsIs?: boolean;
  params?: FetchParams;
  cancelCondition?: CancelConditionCallback;
  errFn?: ErrorCallback;
}

// export function isRequestWithCancel<T extends FetchJSONRequest>(
//   x: T
// ): x is T & RequestWithCancel {
//   return !!(x as RequestWithCancel).cancelCondition;
// }
//
// export function isRequestWithErrFn<T extends FetchJSONRequest>(
//   x: T
// ): x is T & RequestWithErrFn {
//   return !!(x as RequestWithErrFn).errFn;
// }

export class GrRestApiHelper {
  constructor(
    private readonly _cache: SiteBasedCache,
    private readonly _auth: AuthService,
    private readonly _fetchPromisesCache: FetchPromisesCache
  ) {}

  /**
   * Wraps calls to the underlying authenticated fetch function (_auth.fetch)
   * with timing and logging.
s   */
  fetch(req: FetchRequest): Promise<Response> {
    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 startTime the time that the request was started.
   * @param 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.
   */
  private _logCall(
    req: FetchRequest,
    startTime: number,
    status: number | null
  ) {
    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.info(
      [
        'HTTP',
        status,
        method,
        `${elapsed}ms`,
        req.anonymizedUrl || req.url,
        `(${startAt.toISOString()}, ${endAt.toISOString()})`,
      ].join(' ')
    );
    if (req.anonymizedUrl) {
      const detail: RpcLogEventDetail = {
        status,
        method,
        elapsed,
        anonymizedUrl: req.anonymizedUrl,
      };
      document.dispatchEvent(
        new CustomEvent('gr-rpc-log', {
          detail,
          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.
   *
   * @return Promise which resolves to undefined if cancelCondition returns true
   *     and resolves to Response otherwise
   */
  fetchRawJSON(req: FetchJSONRequest): Promise<Response | undefined> {
    const urlWithParams = this.urlWithParams(req.url, req.params);
    const fetchReq: FetchRequest = {
      url: urlWithParams,
      fetchOptions: req.fetchOptions,
      anonymizedUrl: req.reportUrlAsIs ? urlWithParams : req.anonymizedUrl,
    };
    return this.fetch(fetchReq)
      .then((res: Response) => {
        if (req.cancelCondition && req.cancelCondition()) {
          if (res.body) {
            res.body.cancel();
          }
          return;
        }
        return res;
      })
      .catch(err => {
        if (req.errFn) {
          req.errFn.call(undefined, null, err);
        } else {
          fireNetworkError(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 noAcceptHeader - don't add default accept json header
   */
  fetchJSON(
    req: FetchJSONRequest,
    noAcceptHeader?: boolean
  ): Promise<ParsedJSON | undefined> {
    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;
        }
        fireServerError(response, req);
        return;
      }
      return this.getResponseObject(response);
    });
  }

  urlWithParams(url: string, fetchParams?: FetchParams): string {
    if (!fetchParams) {
      return getBaseUrl() + url;
    }

    const params: Array<string | number | boolean> = [];
    for (const [p, paramValue] of Object.entries(fetchParams)) {
      // TODO(TS): Replace == null with === and check for null and undefined
      // eslint-disable-next-line eqeqeq
      if (paramValue == null) {
        params.push(this.encodeRFC5987(p));
        continue;
      }
      // TODO(TS): Unclear, why do we need the following code.
      // If paramValue can be array - we should either fix FetchParams type
      // or convert the array to a string before calling urlWithParams method.
      const paramValueAsArray = ([] as Array<string | number | boolean>).concat(
        paramValue
      );
      for (const value of paramValueAsArray) {
        params.push(`${this.encodeRFC5987(p)}=${this.encodeRFC5987(value)}`);
      }
    }
    return getBaseUrl() + url + '?' + params.join('&');
  }

  // Backend encode url in RFC5987 and frontend needs to do same to match
  // queries for preloading queries
  encodeRFC5987(uri: string | number | boolean) {
    return encodeURIComponent(uri).replace(
      /['()*]/g,
      c => '%' + c.charCodeAt(0).toString(16)
    );
  }

  getResponseObject(response: Response): Promise<ParsedJSON> {
    return readResponsePayload(response).then(payload => payload.parsed);
  }

  addAcceptJsonHeader(req: FetchJSONRequest) {
    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;
  }

  fetchCacheURL(req: FetchJSONRequest): Promise<ParsedJSON | undefined> {
    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)!;
  }

  // if errFn is not set, then only Response possible
  send(req: SendRawRequest & {errFn?: undefined}): Promise<Response>;

  send(req: SendRawRequest): Promise<Response | undefined>;

  send(req: SendJSONRequest): Promise<ParsedJSON>;

  send(req: SendRequest): Promise<Response | ParsedJSON | undefined>;

  /**
   * Send an XHR.
   *
   * @return Promise resolves to Response/ParsedJSON only if the request is successful
   *     (i.e. no exception and response.ok is true). If response fails then
   *     promise resolves either to void if errFn is set or rejects if errFn
   *     is not set   */
  send(req: SendRequest): Promise<Response | ParsedJSON | undefined> {
    const options: AuthRequestInit = {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 [name, value] of Object.entries(req.headers)) {
        options.headers.set(name, value);
      }
    }
    const url = req.url.startsWith('http') ? req.url : getBaseUrl() + req.url;
    const fetchReq: FetchRequest = {
      url,
      fetchOptions: options,
      anonymizedUrl: req.reportUrlAsIs ? url : req.anonymizedUrl,
    };
    const xhr = this.fetch(fetchReq)
      .catch(err => {
        fireNetworkError(err);
        if (req.errFn) {
          return req.errFn.call(undefined, null, err);
        } else {
          throw err;
        }
      })
      .then(response => {
        if (response && !response.ok) {
          if (req.errFn) {
            req.errFn.call(undefined, response);
            return;
          }
          fireServerError(response, fetchReq);
        }
        return response;
      });

    if (req.parseResponse) {
      // TODO(TS): remove as Response and fix error.
      // Javascript code allows returning of a Response object from errFn.
      // This can be a mistake and we should add check here or it can be used
      // somewhere - in this case we should fix it carefully (define
      // different type of callback if parseResponse is true, etc...).
      return xhr.then(res => this.getResponseObject(res as Response));
    }
    // The actual xhr type is Promise<Response|undefined|void> because of the
    // catch callback
    return xhr as Promise<Response | undefined>;
  }

  invalidateFetchPromisesPrefix(prefix: string) {
    this._fetchPromisesCache.invalidatePrefix(prefix);
    this._cache.invalidatePrefix(prefix);
  }
}
