/**
 * Allows you to send web requests and receive the responses.
 */
import * as image from "../image-source";
import * as fs from "../file-system";

/**
 * Downloads the content from the specified URL as a string.
 * @param url The URL to request from.
 */
export function getString(url: string): Promise<string>;

/**
 * Downloads the content from the specified URL as a string.
 * @param options An object that specifies various request options.
 */
export function getString(options: HttpRequestOptions): Promise<string>;

/**
 * Downloads the content from the specified URL as a string and returns its JSON.parse representation.
 * @param url The URL to request from.
 */
export function getJSON<T>(url: string): Promise<T>;

/**
 * Downloads the content from the specified URL as a string and returns its JSON.parse representation.
 * @param options An object that specifies various request options.
 */
export function getJSON<T>(options: HttpRequestOptions): Promise<T>;

/**
 * Downloads the content from the specified URL and attempts to decode it as an image.
 * @param url The URL to request from.
 */
export function getImage(url: string): Promise<image.ImageSource>;

/**
 * Downloads the content from the specified URL and attempts to decode it as an image.
 * @param options An object that specifies various request options.
 */
export function getImage(options: HttpRequestOptions): Promise<image.ImageSource>;

/**
 * Downloads the content from the specified URL and attempts to save it as file.
 * @param url The URL to request from.
 * @param destinationFilePath Optional. The downloaded file path.
 */
export function getFile(url: string, destinationFilePath?: string): Promise<fs.File>;

/**
 * Downloads the content from the specified URL and attempts to save it as file.
 * @param options An object that specifies various request options.
 * @param destinationFilePath Optional. The downloaded file path.
 */
export function getFile(options: HttpRequestOptions, destinationFilePath?: string): Promise<fs.File>;

/**
 * Makes a generic http request using the provided options and returns a HttpResponse Object.
 * @param options An object that specifies various request options.
 */
export function request(options: HttpRequestOptions): Promise<HttpResponse>;

/**
 * Provides options for the http requests.
 */
export interface HttpRequestOptions {
  /**
   * Gets or sets the request url.
   */
  url: string;

  /**
   * Gets or sets the request method.
   */
  method: string;

  /**
   * Gets or sets the request headers in JSON format.
   */
  headers?: any;

  /**
   * Gets or sets the request body.
   */
  content?: string | FormData;

  /**
   * Gets or sets the request timeout in milliseconds.
   */
  timeout?: number;

  /**
   * Gets or sets wether to *not* follow server's redirection responses.
   */
  dontFollowRedirects?: boolean;
}

/**
 * Encapsulates HTTP-response information from an HTTP-request.
 */
export interface HttpResponse {
  /**
   * Gets the response status code.
   */
  statusCode: number;

  /**
   * Gets the response headers.
   */
  headers: Headers;

  /**
   * Gets the response content.
   */
  content?: HttpContent;
}

export type Headers = { [key: string]: string | string[] };

export const enum HttpResponseEncoding {
  UTF8,
  GBK
}
/**
 * Encapsulates the content of an HttpResponse.
 */
export interface HttpContent {
  /**
   * Gets the response body as raw data.
   */
  raw: any;

  /**
   * Gets the response body as string.
   */
  toString: (encoding?: HttpResponseEncoding) => string;

  /**
   * Gets the response body as JSON object.
   */
  toJSON: (encoding?: HttpResponseEncoding) => any;

  /**
   * Gets the response body as ImageSource.
   */
  toImage: () => Promise<image.ImageSource>;

  /**
   * Gets the response body as file.
   */
  toFile: (destinationFilePath?: string) => fs.File;
}
