import requests
import logging
from requests.models import HTTPError

logger = logging.getLogger(__name__)


class Request(object):
    def __init__(self, url, headers=None):
        self.headers = {
            'Accept': 'application/json'
        }
        if headers:
            self.headers.update(headers)

        self.BASE_URL = url

    def do_request(self, method, endpoint, *args, **kwargs):
        r = requests.request(method, self.BASE_URL + endpoint,
                             *args,
                             **kwargs,
                             headers={
                                 **kwargs.get('headers', {}),
                                 **self.headers
                             })

        try:
            r.raise_for_status()
        except HTTPError as e:
            if e.response.status_code < 500:
                logger.error(e.response.content.decode('utf-8'))
            raise e
        return r.json()

    def get(self, endpoint: str, *args, **kwargs):
        return self.do_request('get', endpoint, *args, **kwargs)

    def post(self, endpoint: str, data=None, **kwargs):
        return self.do_request('post', endpoint, data=data, **kwargs)

    def put(self, endpoint: str, **kwargs):
        return self.do_request('put', endpoint, **kwargs)

    def delete(self, endpoint: str, **kwargs):
        return self.do_request('delete', endpoint, **kwargs)


class AdminRequest(Request):
    def __init__(self, hostname, admin_username, admin_password,
                 **kwargs):
        self.username = admin_username
        url = f'{admin_username}:{admin_password}@{hostname}/'
        super().__init__('http://' + url)

    def __str__(self):
        return f'admin user: {self.username}'


class TokenRequest(Request):
    def __init__(self, hostname, token: str, **kwargs):
        self.token = token

        super().__init__(f'http://{hostname}/', {
            'Authorization': 'Bearer ' + token
        })

    def __str__(self):
        return f'token {self.token}'