"""
Web application
(from lessweb)
"""
from datetime import datetime
import itertools
import json
import logging
import os
import re
import traceback
from types import GeneratorType
from typing import List, Any, Callable, Type, Dict
from urllib.parse import splitquery, urlencode
from io import BytesIO
from contextlib import contextmanager

from lessweb.webapi import NeedParamError, BadParamError, NotFoundError, HttpStatus
from lessweb.webapi import http_methods
from lessweb.context import Context
from lessweb.model import fetch_param, ModelToDict
from lessweb.storage import Storage
from lessweb.utils import eafp, re_standardize, makedir
from lessweb.bridge import Bridge, assert_valid_bridge
from lessweb.garage import Jsonizable, BaseBridge, JsonToJson


__all__ = [
    "Interceptor", "Mapping", "interceptor", "Application",
]


class Interceptor:
    def __init__(self, pattern, method, dealer, patternobj) -> None: ...

class Mapping:
    def __init__(self, pattern, method, dealer, doc, patternobj, view, querynames) -> None: ...


def build_controller(dealer): ...


def interceptor(dealer): ...


class Application(object):
    def __init__(self, encoding: str='utf-8', debug: bool=True) -> None: ...
    def add_interceptor(self, pattern: str, method: str, dealer: Callable) -> None: ...
    def add_bridge(self, bridge: Type[Bridge]) -> None: ...
    def add_mapping(self, pattern: str, method: str, dealer: Callable, view=None) -> None: ...
    def add_connect_interceptor(self, pattern: str, dealer: Callable) -> None: ...
    def add_connect_mapping(self, pattern: str, dealer: Callable, view=None) -> None: ...
    def add_delete_interceptor(self, pattern: str, dealer: Callable) -> None: ...
    def add_delete_mapping(self, pattern: str, dealer: Callable, view=None) -> None: ...
    def add_get_interceptor(self, pattern: str, dealer: Callable) -> None: ...
    def add_get_mapping(self, pattern: str, dealer: Callable, view=None) -> None: ...
    def add_head_interceptor(self, pattern: str, dealer: Callable) -> None: ...
    def add_head_mapping(self, pattern: str, dealer: Callable, view=None) -> None: ...
    def add_options_interceptor(self, pattern: str, dealer: Callable) -> None: ...
    def add_options_mapping(self, pattern: str, dealer: Callable, view=None) -> None: ...
    def add_post_interceptor(self, pattern: str, dealer: Callable) -> None: ...
    def add_post_mapping(self, pattern: str, dealer: Callable, view=None) -> None: ...
    def add_put_interceptor(self, pattern: str, dealer: Callable) -> None: ...
    def add_put_mapping(self, pattern: str, dealer: Callable, view=None) -> None: ...

    def wsgifunc(self, *middleware) -> Callable: ...
    def run(self, wsgifunc: Callable=None, port:int=8080, homepath:str='', staticpath:str='static') -> None: ...

    def request(self, localpart:str='/', method:str='GET', data=None,
                host:str="0.0.0.0:8080", headers:Dict=None, https:bool=False, env:Dict=None) -> Storage: ...
    def test_get(self, localpart='/', query=None, headers=None, status_code=200, parsejson=True, https=False, env=None): ...
    def test_delete(self, localpart='/', query=None, headers=None, status_code=200, parsejson=True, https=False, env=None): ...
    def test_head(self, localpart='/', query=None, headers=None, status_code=200, parsejson=True, https=False, env=None): ...
    def test_post(self, localpart='/', data=None, headers=None, status_code=200, parsejson=True, https=False, env=None): ...
    def test_put(self, localpart='/', data=None, headers=None, status_code=200, parsejson=True, https=False, env=None): ...
