import email.parser
import asyncio
import json

from http.client import HTTPMessage, _MAXHEADERS
from io import BytesIO
from urllib.parse import parse_qs
from base64 import b64encode
from functools import reduce
from cgi import valid_boundary, parse_header
from inspect import isawaitable
from asyncio import ensure_future
from typing import Dict, Callable

from multidict import MultiDict

from pulsar.api import HttpException, BadRequest
from pulsar.utils.system import convert_bytes
from pulsar.utils.structures import mapping_iterator
from pulsar.utils.httpurl import (CHARSET, ENCODE_BODY_METHODS,
                                  JSON_CONTENT_TYPES, parse_options_header)
from .headers import CONTENT_LENGTH


FORM_ENCODED_TYPES = ('application/x-www-form-urlencoded',
                      'application/x-url-encoded')
BODY_DATA = 0
BODY_FILES = 1
LARGE_BODY_CODE = 403


def http_protocol(parser):
    return "HTTP/%s" % parser.get_http_version()


class HttpBodyReader:
    """Asynchronous body reader and parser

    An instance of this class is injected into the wsgi.input key
    of the WSGI environment