from typing import cast
import logging
import json
import urllib.request
import http.client
import urllib.parse

logger = logging.getLogger(__name__)


class Response(http.client.HTTPResponse):
    @classmethod
    def tune(cls, resp: http.client.HTTPResponse) -> 'Response':
        resp.__class__ = cls
        return cast(Response, resp)

    def json(self):
        return json.loads(self.read().decode('utf-8'))


class SimpleRequestor:
    def __init__(self, base_url):
        self.base_url = base_url

    def request(self, method, path, params=None, data=None, headers=None) -> Response:
        headers = headers or {}

        path = f'{self.base_url}{path}'
        if params:
            path = f'{path}?{urllib.parse.urlencode(params)}'

        req = urllib.request.Request(
            url=path,
            method=method.upper(),
            data=json.dumps(data).encode('utf-8') if data else None,
            headers=headers,
        )

        if data and not req.get_header('Content-Type'):
            req.add_header('Content-Type', 'application/json')

        logger.info(f'{method} {req.full_url} with headers: {req.headers!r} and body: {req.data!r}')
        return Response.tune(urllib.request.urlopen(req))


if __name__ == '__main__':
    import logging
    logging.basicConfig(level=logging.INFO)

    requestor = SimpleRequestor('https://httpbin.org/')

    requestor.request('GET', 'anything', params={"limit": 10})
    resp = requestor.request('POST', 'anything', params={"a": 1}, data={"a": 2})

    print('Response:', resp.json())