# Copyright 2012 Canonical Ltd.  This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).

"""MAAS OAuth API connection library."""

from __future__ import (
    absolute_import,
    print_function,
    unicode_literals,
)

str = None

__metaclass__ = type
__all__ = [
    'MAASClient',
    'MAASDispatcher',
    'MAASOAuth',
]

import gzip
import time
from functools import wraps
from io import BytesIO
import urllib2

from encode_json import encode_json_data
from multipart import encode_multipart_data
from utils import urlencode
import oauth.oauth as oauth


def retry(ExceptionToCheck, tries=4, delay=3, backoff=2, logger=None):
    """Retry calling the decorated function using an exponential backoff.

    http://www.saltycrane.com/blog/2009/11/trying-out-retry-decorator-python/
    original from: http://wiki.python.org/moin/PythonDecoratorLibrary#Retry

    :param ExceptionToCheck: the exception to check. may be a tuple of
        exceptions to check
    :type ExceptionToCheck: Exception or tuple
    :param tries: number of times to try (not retry) before giving up
    :type tries: int
    :param delay: initial delay between retries in seconds
    :type delay: int
    :param backoff: backoff multiplier e.g. value of 2 will double the delay
        each retry
    :type backoff: int
    :param logger: logger to use. If None, print
    :type logger: logging.Logger instance
    """

    def deco_retry(f):

        @wraps(f)
        def f_retry(*args, **kwargs):
            mtries, mdelay = tries, delay
            while mtries > 1:
                try:
                    return f(*args, **kwargs)
                except ExceptionToCheck, e:
                    msg = "%s, Retrying in %d seconds..." % (str(e), mdelay)
                    if logger:
                        logger.warning(msg)
                    else:
                        print
                        msg
                    time.sleep(mdelay)
                    mtries -= 1
                    mdelay *= backoff
            return f(*args, **kwargs)

        return f_retry  # true decorator

    return deco_retry


class MAASOAuth:
    """Helper class to OAuth-sign an HTTP request."""

    def __init__(self, consumer_key, resource_token, resource_secret):
        resource_tok_string = "oauth_token_secret=%s&oauth_token=%s" % (
            resource_secret, resource_token)
        self.resource_token = oauth.OAuthToken.from_string(resource_tok_string)
        self.consumer_token = oauth.OAuthConsumer(consumer_key, "")

    def sign_request(self, url, headers):
        """Sign a request.

        @param url: The URL to which the request is to be sent.
        @param headers: The headers in the request.  These will be updated
            with the signature.
        """
        oauth_request = oauth.OAuthRequest.from_consumer_and_token(
            self.consumer_token, token=self.resource_token, http_url=url)
        oauth_request.sign_request(
            oauth.OAuthSignatureMethod_PLAINTEXT(), self.consumer_token,
            self.resource_token)
        headers.update(oauth_request.to_header())


class NoAuth:
    """Anonymous authentication class for making unauthenticated requests."""

    def __init__(self, *args, **kwargs):
        pass

    def sign_request(self, *args, **kwargs):
        """Go through the motions of signing a request.

        Since this class does not really authenticate, this does nothing.
        """


class RequestWithMethod(urllib2.Request):
    """Enhances urllib2.Request so an http method can be supplied."""

    def __init__(self, *args, **kwargs):
        self._method = kwargs.pop('method', None)
        urllib2.Request.__init__(self, *args, **kwargs)

    def get_method(self):
        return (
            self._method if self._method
            else super(RequestWithMethod, self).get_method())


class MAASDispatcher:
    """Helper class to connect to a MAAS server using blocking requests.

    Be careful when changing its API: this class is designed so that it
    can be replaced with a Twisted-enabled alternative.  See the MAAS
    provider in Juju for the code this would require.
    """

    @retry(urllib2.URLError, tries=2, delay=5, backoff=2)
    def dispatch_query(self, request_url, headers, method="GET", data=None):
        """Synchronously dispatch an OAuth-signed request to L{request_url}.

        :param request_url: The URL to which the request is to be sent.
        :param headers: Headers to include in the request.
        :type headers: A dict.
        :param method: The HTTP method, e.g. C{GET}, C{POST}, etc.
            An AssertionError is raised if trying to pass data for a GET.
        :param data: The data to send, if any.
        :type data: A byte string.

        :return: A open file-like object that contains the response.
        """
        headers = dict(headers)
        # header keys are case insensitive, so we have to pass over them
        set_accept_encoding = False
        for key in headers:
            if key.lower() == 'accept-encoding':
                # The user already supplied a requested encoding, so just pass
                # it along.
                break
        else:
            set_accept_encoding = True
            headers['Accept-encoding'] = 'gzip'
        req = RequestWithMethod(request_url, data, headers, method=method)
        res = urllib2.urlopen(req)
        # If we set the Accept-encoding header, then we decode the header for
        # the caller.
        is_gzip = (
            set_accept_encoding
            and res.info().get('Content-Encoding') == 'gzip')
        if is_gzip:
            # Workaround python's gzip failure, gzip.GzipFile wants to be able
            # to seek the file object.
            res_content_io = BytesIO(res.read())
            ungz = gzip.GzipFile(mode='rb', fileobj=res_content_io)
            res = urllib2.addinfourl(ungz, res.headers, res.url, res.code)
        return res


class MAASClient:
    """Base class for connecting to MAAS servers.

    All "path" parameters can be either a string describing an absolute
    resource path, or a sequence of items that, when represented as unicode,
    make up the elements of the resource's path.  So `['nodes', node_id]`
    is equivalent to `"nodes/%s" % node_id`.
    """

    def __init__(self, auth, dispatcher, base_url):
        """Intialise the client.

        :param auth: A `MAASOAuth` to sign requests.
        :param dispatcher: An object implementing the MAASOAuthConnection
            base class.
        :param base_url: The base URL for the MAAS server, e.g.
            http://my.maas.com:5240/
        """
        self.dispatcher = dispatcher
        self.auth = auth
        self.url = base_url

    def _make_url(self, path):
        """Compose an absolute URL to `path`.

        :param path: Either a string giving a path to the desired resource,
            or a sequence of items that make up the path.
        :return: An absolute URL leading to `path`.
        """
        assert not isinstance(path, bytes)
        if not isinstance(path, unicode):
            assert not any(isinstance(element, bytes) for element in path)
            path = '/'.join(unicode(element) for element in path)
        # urljoin is very sensitive to leading slashes and when spurious
        # slashes appear it removes path parts. This is why joining is
        # done manually here.
        return self.url.rstrip("/") + "/" + path.lstrip("/")

    def _formulate_get(self, path, params=None):
        """Return URL and headers for a GET request.

        This is similar to _formulate_change, except parameters are encoded
        into the URL.

        :param path: Path to the object to issue a GET on.
        :param params: Optional dict of parameter values.
        :return: A tuple: URL and headers for the request.
        """
        url = self._make_url(path)
        if params is not None and len(params) > 0:
            url += "?" + urlencode(params.items())
        headers = {}
        self.auth.sign_request(url, headers)
        return url, headers

    def _formulate_change(self, path, params, as_json=False):
        """Return URL, headers, and body for a non-GET request.

        This is similar to _formulate_get, except parameters are encoded as
        a multipart form body.

        :param path: Path to the object to issue a GET on.
        :param params: A dict of parameter values.
        :param as_json: Encode params as application/json instead of
            multipart/form-data. Only use this if you know the API already
            supports JSON requests.
        :return: A tuple: URL, headers, and body for the request.
        """
        url = self._make_url(path)
        if 'op' in params:
            params = dict(params)
            op = params.pop('op')
            url += '?' + urlencode([('op', op)])
        if as_json:
            body, headers = encode_json_data(params)
        else:
            body, headers = encode_multipart_data(params, {})
        self.auth.sign_request(url, headers)
        return url, headers, body

    def get(self, path, op=None, **kwargs):
        """Dispatch a GET.

        :param op: Optional: named GET operation to invoke.  If given, any
            keyword arguments are passed to the named operation.
        :return: The result of the dispatch_query call on the dispatcher.
        """
        if op is not None:
            kwargs['op'] = op
        url, headers = self._formulate_get(path, kwargs)
        return self.dispatcher.dispatch_query(
            url, method="GET", headers=headers)

    def post(self, path, op, as_json=False, **kwargs):
        """Dispatch POST method `op` on `path`, with the given parameters.

        :param as_json: Instead of POSTing the content as multipart/form-data
            POST it as application/json
        :return: The result of the dispatch_query call on the dispatcher.
        """
        if op is not None:
            kwargs['op'] = op
        url, headers, body = self._formulate_change(
            path, kwargs, as_json=as_json)
        return self.dispatcher.dispatch_query(
            url, method="POST", headers=headers, data=body)

    def put(self, path, **kwargs):
        """Dispatch a PUT on the resource at `path`."""
        url, headers, body = self._formulate_change(path, kwargs)
        return self.dispatcher.dispatch_query(
            url, method="PUT", headers=headers, data=body)

    def delete(self, path):
        """Dispatch a DELETE on the resource at `path`."""
        url, headers, body = self._formulate_change(path, {})
        return self.dispatcher.dispatch_query(
            url, method="DELETE", headers=headers, data=body)
