import requests
import httpx
import json

from ctyun.result import ResponseHeader

from ctyun.cloudtrail.model.result import LookupEventsResult

from ctyun.exceptions import ServiceException


class HttpClient:
    def __init__(self, url, data=None, headers={}, method=None, params={}):
        self.url = url
        self.headers = headers
        self.data = data
        self.method = method
        self.params = params

    def request(self, result, action=None, use_httpx=True, use_http2=False, timeout=10.0, max_retry=3):
        if self.method is not None and self.method.lower() == "post":
            if not use_httpx:
                response = requests.post(url=self.url, data=self.data, headers=self.headers, verify=False)
            else:
                response = httpx.Client(http2=use_http2).post(url=self.url, data=self.data, headers=self.headers)
                # print("http_ver", response.http_version)
            status = response.status_code
            response_headers = response.headers
            header = ResponseHeader(headers=response_headers, status_code=status)

            if 200 <= status < 400:
                response_content = response.content.decode('utf-8')
                if len(response_content) > 2:
                    if action == "LookupEvents":
                        response_result = json.loads(response.content.decode('utf-8'))
                        response_result['header'] = header
                        res = LookupEventsResult(response_result)
                        res.set_header(header)
                        res.parser_result()
                        return res
                    else:
                        response_result = json.loads(response.content.decode('utf-8'),
                                                     object_hook=result.__class__)
                else:
                    response_result = result
                response_result.set_header(header)
                return response_result
            else:
                exception = ServiceException(response.content.decode('utf-8'))
                exception.set_header(header)
                raise exception

        elif self.method is not None and self.method.lower() == "get":
            get_ok = False
            retry = 0
            while (not get_ok) and (retry < max_retry):
                if not use_httpx:
                    response = requests.get(url=self.url, params=self.params, headers=self.headers, verify=False)
                    get_ok = True
                else:
                    try:
                        # if retry > 0:
                        #    print("\nretry:",retry)
                        # client = httpx.Client(http2=True)
                        # response = client.get(url=self.url, params=self.params, headers=self.headers, timeout=timeout)
                        response = httpx.Client(http2=use_http2).get(url=self.url, params=self.params,
                                                                     headers=self.headers, timeout=timeout)
                    except:
                        get_ok = False
                        # raise Exception(status)
                    else:
                        get_ok = True
                retry = retry + 1
                if get_ok:
                    status = response.status_code
                    response_headers = response.headers
                    header = ResponseHeader(headers=response_headers, status_code=status)

                    if 200 <= status < 400:
                        response_content = response.content.decode('utf-8')
                        if len(response_content) > 2:
                            result.parse(response_content)

                        result.set_header(header)
                        return result
                    else:
                        exception = ServiceException(response.content.decode('utf-8'))
                        exception.set_header(header)
                        raise exception
            if not get_ok and retry >= max_retry:
                raise Exception("no response")
