from typing import Optional, Dict, List, Union, Any
import cgi
import json

from io import BytesIO
from requests.structures import CaseInsensitiveDict

from lessweb.storage import Storage
from lessweb.webapi import UploadedFile, Cookie, HttpStatus
from lessweb.webapi import header_name_of_wsgi_key, wsgi_key_of_header_name
from lessweb.webapi import parse_cookie, mimetypes
from lessweb.utils import fields_in_query
from lessweb.garage import Jsonizable


class Request:
    def __init__(self) -> None: ...
    def contains_cookie(self, name: str) -> bool: ...
    def get_cookie(self, name: str) -> Optional[str]: ...
    def get_cookienames(self) -> List[str]: ...
    def contains_header(self, name: str) -> bool: ...
    def get_header(self, name: str) -> Optional[str]: ...
    def get_headernames(self) -> List[str]: ...


class Response:
    def __init__(self) -> None: ...
    def set_cookie(self, name:str, value:str, expires:int=None, path:str='/',
                   domain:str=None, secure:bool=False, httponly:bool=False) -> None: ...
    def get_cookie(self, name:str) -> Optional[Cookie]: ...
    def del_cookie(self, name:str) -> None: ...
    def set_status(self, status: HttpStatus) -> None: ...
    def get_status(self) -> HttpStatus: ...
    def set_header(self, name: str, value: Union[str, int]) -> None: ...
    def get_header(self, name: str) -> Optional[str]: ...
    def del_header(self, name: str) -> None: ...
    def get_headernames(self) -> List[str]: ...
    def clear(self) -> None: ...
    def send_access_allow(self, allow_headers: List[str]=None) -> None: ...
    def send_allow_methods(self, methods: List[str]): ...
    def send_redirect(self, location: str) -> None: ...
    def send_content_type(self, mimekey='html', encoding: str=''): ...


class Context(object):
    from lessweb.application import Application
    app_stack: List
    app: Application
    view: Any
    environ: Dict
    env: Dict
    host: str
    protocol: str
    homedomain: str
    homepath: str
    home: str
    realhome: str
    ip: str
    method: str
    path: str
    query: str
    fullpath: str
    request: Request
    response: Response
    def __init__(self, app=None) -> None: ...
    def __call__(self): ...
    def set_param(self, realname, realvalue) -> None: ...
    def get_param(self, realname, default=None) -> Any: ...
    def set_alias(self, realname, queryname) -> None: ...
    def is_json_request(self) -> bool: ...
    def body_data(self) -> bytes: ...
    def get_input(self, queryname, default=None)->Jsonizable: ...
    def get_inputs(self)->Dict[str, Jsonizable]: ...
