import urllib2
import urllib
import json
from logging import Logger

class HttpRequestor(object):
    """
    Helper class for sending requests of HTTP with GET and POST
    """

    api_url = ""                    #: domain url to use when sending requests
    api_method = ""                 #: api method to use when sending requests
    api_params = ""                 #: parameters to send to the method when sending requests
    api_header = {}                 #: Authorization to put into header when sending requests
    api_post_payload = {}           #: Payload to be delivered when sending a POST request
    logger = None                   #: logger to send loggin information to.  Logger comes from pytest test definitions
    api_path_params = ""            #:
    formatted_params = ""           #:

    def __init__(self, api_url, logger):
        """
        Constructor for class

        @param api_url: URL to the base of the API
        @type api_url: str
        @param logger: instance of a logging object configured in testing project
        @type logger: Logger

        """

        self.api_url = api_url
        self.logger = logger

    def make_path_params(self, params):
        """
        Constucts a request with the parameters formated in path parameter format.
        EX: http://myserver.com/api/method/pathParam1/pathParam2

        @param params: a list of parameter values to send to the api
        @type params: dict
        """

        path_params = ""

        for param in params:
            path_params = path_params + "/" + param

        #path params must be at the start of the parameter list
        self.formatted_params = urllib.quote_plus(path_params, "/") + self.formatted_params

    def make_query_params(self, params):
        """
        Constucts a request with the parameters formated in query parameter format.
        EX: http://myserver.com/api/method?queryParam=paramValue

        @param params: a dictionary of parameter names and values to send to the api
        @type params: dict
        """

        encoded_param = urllib.urlencode(params)

        #query params must be at the end of the paramater list
        self.formatted_params = self.formatted_params + "?" + encoded_param

    def make_get_request(self):
        """
        Sends a GET HTTP request.  Make sure you have set the classe's api_params,api_url and api_method first

        Args :null

        Returns : (file-like object) the HTTP response

        Raises :null
        """

        url = self.api_url + self.api_method
        request = urllib2.Request(url + self.formatted_params)

        if len(self.api_header) > 0:
            for key in self.api_header.keys():
                request.add_header(key, self.api_header[key])

        self.logger.info(request.get_full_url())
        self.logger.info(request.get_data())
        self.logger.info(request.get_method())

        try:

            return urllib2.urlopen(request)

        except urllib2.URLError, e:
            return e
        finally:
            self.formatted_params = ""

    def make_post_request(self):
        """
        Sends a POST HTTP request.  Make sure you have set the classe's api_params,api_url,
        api_header and api_method first

        Returns : (file-like object) the HTTP response
        """
        url = self.api_url + self.api_method
        request = urllib2.Request(url)

        encoded_param = urllib.urlencode(self.api_params)
        request.add_data(encoded_param)

        if self.api_post_payload:
            request.add_data(json.dumps(self.api_post_payload))

        for key in self.api_header.keys():
            request.add_header(key, self.api_header[key])

        try:

            self.logger.info(request.get_full_url())
            self.logger.info(request.get_data())
            self.logger.info(request.get_method())
            return urllib2.urlopen(request)

        except urllib2.URLError, e:
            return e
        finally:
            self.formatted_params = ""

    def get_auth(self, credentials):
        """
        Creates the authentication for accessing HTTP

        @param credentials: 'username' and 'password' keys for a dictionary containing the HTTP Basic Auth to access
        the api
        @type credentials: dict
        """

        # create a handler for the username / password
        passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
        # none is so that all pages under the realm are opened with password
        passman.add_password(None, self.api_url, credentials['username'], credentials['password'])

        # authenticate and open the website
        authhandler = urllib2.HTTPBasicAuthHandler(passman)
        opener = urllib2.build_opener(authhandler)
        urllib2.install_opener(opener)