import * as koa from 'koa';
import * as http from 'http';
import * as https from 'https';

declare function koaHttpProxy(host: string | ((ctx: koa.Context) => string), options: koaHttpProxy.IOptions): koa.Middleware;

declare namespace koaHttpProxy {
  export interface IOptions {
    agent?: http.Agent,
    headers?: { [key: string]: any },
    strippedHeaders?: [string],
    https?: boolean,
    limit?: string,
    parseReqBody?: boolean,
    port?: number,
    preserveHostHdr?: boolean,
    preserveReqSession?: boolean,
    reqAsBuffer?: boolean,
    reqBodyEncoding?: string | null,
    connectTimeout?: number,
    timeout?: number,
    needToNext?: boolean,
    filter?(ctx: koa.Context): boolean,
    onResolveProxyRequest?(ctx: koa.Context): void | Promise<void>,
    onResolveProxyResponse?(ctx: koa.Context): void | Promise<void>,
    proxyReqBodyDecorator?(bodyContent: string | Buffer, ctx: koa.Context): string | Promise<string> | Buffer | Promise<Buffer>,
    proxyReqOptDecorator?(proxyReqOpts: IRequestOption, ctx: koa.Context): IRequestOption | Promise<IRequestOption>,
    proxyReqPathResolver?(ctx: koa.Context): string | Promise<string>,
    userResDecorator?(proxyRes: http.IncomingMessage, proxyResData: string | Buffer, ctx: koa.Context): string | Buffer | Promise<string> | Promise<Buffer>,
    userResHeadersDecorator?(headers: {[key: string]: string}, ctx: koa.Context): Promise<{[key: string]: string}> | {[key: string]: string},
  }

  export type IRequestOption = {
    hostname: string,
    port: number,
    headers: { [key: string]: any },
    method: string,
    path: string,
    bodyContent: string | Buffer,
    params: any,
  } & http.RequestOptions & https.RequestOptions

  export interface Container {
    user: {
      ctx: koa.Context
    },
    proxy: {
      req: Partial<http.IncomingMessage>,
      res: Partial<http.IncomingMessage>,
      bodyContent?: Buffer,
      resData?: Buffer,
      reqBuilder: IRequestOption,
      requestModule: typeof http | typeof https,
      options: koaHttpProxy.IOptions,
      params: {
        host: string | ((ctx: koa.Context) => string),
        userOptions: koaHttpProxy.IOptions,
      },
      isSecure?: boolean,
    },
    params: {
      host: string | ((ctx: koa.Context) => string),
      userOptions: koaHttpProxy.IOptions,
    },
  }
}

export = koaHttpProxy
