export type Middleware<Request extends ServerHttpRequest = ServerHttpRequest, Response extends ServerHttpResponse = ServerHttpResponse> = ((context: WebExchange<Request, Response>, next: () => Promise<void>) => Promise<void>)[];

export abstract class WebExchange<Request extends ServerHttpRequest = ServerHttpRequest, Response extends  ServerHttpResponse = ServerHttpResponse> {
    abstract readonly request: Request
    abstract readonly response: Response

    get method(): string | undefined {
        return this.request.method;
    }

    get path(): string | null | undefined {
        return this.request.path;
    }
}
export type ReadonlyHeaderValue = string | undefined;
export type HeaderValue = number | ReadonlyHeaderValue;
export type ReadonlyHeaderValues = (readonly string[]) | ReadonlyHeaderValue
export type HeaderValues = (readonly string[]) | HeaderValue

export interface HttpHeaders {
    get(name: string): HeaderValues
    list(name: string): string[]
    one(name: string): HeaderValue
    has(name: string): boolean
    keys(): IteratorObject<string>
}

export interface ReadonlyHttpHeaders extends HttpHeaders {
    get(name: string): ReadonlyHeaderValues
    one(name: string): string | undefined

}
export interface MutableHttpHeaders extends HttpHeaders {
    get(name: string): HeaderValues
    one(name: string): HeaderValue
    set(name: string, value: HeaderValues): this
    add(name: string, value: string | (readonly string[])): this
}

export interface HttpMessage<Headers = HttpHeaders> {
    readonly headers: Headers
}

export interface HttpRequest<Headers = HttpHeaders> extends HttpMessage<Headers> {
    readonly path: string,
    readonly method?: string
    readonly URL: URL
    readonly protocol: string
    /**
     * hostname[:port]
     */
    readonly host?: string
    readonly body: Promise<Blob>
}

export interface HttpResponse<Headers = HttpHeaders> extends HttpMessage<Headers> {
    readonly statusCode: number
}

export type ServerHttpRequest = HttpRequest<ReadonlyHttpHeaders> /* & {
    // readonly text: Promise<string>
    // readonly json: Promise<unknown>
    // readonly socket: http.IncomingMessage['socket']
    // readonly _req: http.IncomingMessage
}*/

export interface ServerHttpResponse extends HttpResponse<MutableHttpHeaders> {
    statusCode: number
}
