import copy, getpass, logging, pprint, re, urllib, urlparse
import httplib2
from django.utils import datastructures, simplejson
from autotest_lib.frontend.afe import rpc_client_lib
from autotest_lib.client.common_lib import utils


_request_headers = {}


def _get_request_headers(uri):
    server = urlparse.urlparse(uri)[0:2]
    if server in _request_headers:
        return _request_headers[server]

    headers = rpc_client_lib.authorization_headers(getpass.getuser(), uri)
    headers['Content-Type'] = 'application/json'

    _request_headers[server] = headers
    return headers


def _clear_request_headers(uri):
    server = urlparse.urlparse(uri)[0:2]
    if server in _request_headers:
        del _request_headers[server]


def _site_verify_response_default(headers, response_body):
    return headers['status'] != '401'


class RestClientError(Exception):
    pass


class ClientError(Exception):
    pass


class ServerError(Exception):
    pass


class Response(object):
    def __init__(self, httplib_response, httplib_content):
        self.status = int(httplib_response['status'])
        self.headers = httplib_response
        self.entity_body = httplib_content


    def decoded_body(self):
        return simplejson.loads(self.entity_body)


    def __str__(self):
        return '\n'.join([str(self.status), self.entity_body])


class Resource(object):
    def __init__(self, representation_dict, http):
        self._http = http
        assert 'href' in representation_dict
        for key, value in representation_dict.iteritems():
            setattr(self, str(key), value)


    def __repr__(self):
        return 'Resource(%r)' % self._representation()


    def pprint(self):
        # pretty-print support for debugging/interactive use
        pprint.pprint(self._representation())


    @classmethod
    def load(cls, uri, http=None):
        if not http:
            http = httplib2.Http()
        directory = cls({'href': uri}, http)
        return directory.get()


    def _read_representation(self, value):
        # recursively convert representation dicts to Resource objects
        if isinstance(value, list):
            return [self._read_representation(element) for element in value]
        if isinstance(value, dict):
            converted_dict = dict((key, self._read_representation(sub_value))
                                  for key, sub_value in value.iteritems())
            if 'href' in converted_dict:
                return type(self)(converted_dict, http=self._http)
            return converted_dict
        return value


    def _write_representation(self, value):
        # recursively convert Resource objects to representation dicts
        if isinstance(value, list):
            return [self._write_representation(element) for element in value]
        if isinstance(value, dict):
            return dict((key, self._write_representation(sub_value))
                        for key, sub_value in value.iteritems())
        if isinstance(value, Resource):
            return value._representation()
        return value


    def _representation(self):
        return dict((key, self._write_representation(value))
                    for key, value in self.__dict__.iteritems()
                    if not key.startswith('_')
                    and not callable(value))


    def _do_request(self, method, uri, query_parameters, encoded_body):
        uri_parts = [uri]
        if query_parameters:
            if '?' in uri:
                uri_parts += '&'
            else:
                uri_parts += '?'
            uri_parts += urllib.urlencode(query_parameters, doseq=True)
        full_uri = ''.join(uri_parts)

        if encoded_body:
            entity_body = simplejson.dumps(encoded_body)
        else:
            entity_body = None

        logging.debug('%s %s', method, full_uri)
        if entity_body:
            logging.debug(entity_body)

        site_verify = utils.import_site_function(
                __file__, 'autotest_lib.frontend.shared.site_rest_client',
                'site_verify_response', _site_verify_response_default)
        headers, response_body = self._http.request(
                full_uri, method, body=entity_body,
                headers=_get_request_headers(uri))
        if not site_verify(headers, response_body):
            logging.debug('Response verification failed, clearing headers and '
                          'trying again:\n%s', response_body)
            _clear_request_headers(uri)
            headers, response_body = _http.request(
                full_uri, method, body=entity_body,
                headers=_get_request_headers(uri))

        logging.debug('Response: %s', headers['status'])

        return Response(headers, response_body)


    def _request(self, method, query_parameters=None, encoded_body=None):
        if query_parameters is None:
            query_parameters = {}

        response = self._do_request(method, self.href, query_parameters,
                                    encoded_body)

        if 300 <= response.status < 400: # redirection
            return self._do_request(method, response.headers['location'],
                                    query_parameters, encoded_body)
        if 400 <= response.status < 500:
            raise ClientError(str(response))
        if 500 <= response.status < 600:
            raise ServerError(str(response))
        return response


    def _stringify_query_parameter(self, value):
        if isinstance(value, (list, tuple)):
            return ','.join(self._stringify_query_parameter(item)
                            for item in value)
        return str(value)


    def _iterlists(self, mapping):
        """This effectively lets us treat dicts as MultiValueDicts."""
        if hasattr(mapping, 'iterlists'): # mapping is already a MultiValueDict
            return mapping.iterlists()
        return ((key, (value,)) for key, value in mapping.iteritems())


    def get(self, query_parameters=None, **kwarg_query_parameters):
        """
        @param query_parameters: a dict or MultiValueDict
        """
        query_parameters = copy.copy(query_parameters) # avoid mutating original
        if query_parameters is None:
            query_parameters = {}
        query_parameters.update(kwarg_query_parameters)

        string_parameters = datastructures.MultiValueDict()
        for key, values in self._iterlists(query_parameters):
            string_parameters.setlist(
                    key, [self._stringify_query_parameter(value)
                          for value in values])

        response = self._request('GET',
                                 query_parameters=string_parameters.lists())
        assert response.status == 200
        return self._read_representation(response.decoded_body())


    def get_full(self, results_limit, query_parameters=None,
                 **kwarg_query_parameters):
        """
        Like get() for collections, when the full collection is expected.

        @param results_limit: maxmimum number of results to allow
        @raises ClientError if there are more than results_limit results.
        """
        result = self.get(query_parameters=query_parameters,
                          items_per_page=results_limit,
                          **kwarg_query_parameters)
        if result.total_results > results_limit:
            raise ClientError(
                    'Too many results (%s > %s) for request %s (%s %s)'
                    % (result.total_results, results_limit, self.href,
                       query_parameters, kwarg_query_parameters))
        return result



    def put(self):
        response = self._request('PUT', encoded_body=self._representation())
        assert response.status == 200
        return self._read_representation(response.decoded_body())


    def delete(self):
        response = self._request('DELETE')
        assert response.status == 204 # no content


    def post(self, request_dict):
        # request_dict may still have resources in it
        request_dict = self._write_representation(request_dict)
        response = self._request('POST', encoded_body=request_dict)
        assert response.status == 201 # created
        return self._read_representation({'href': response.headers['location']})
