#-*-coding:utf-8-*-
"""
    outil d'éxécution de requête http
    >>> from pyeole.httprequest import HttpRequest
    >>> a = HttpRequest()
    >>> result = a.request(myurl, post_datas_dict, get_datas_dict, headers)
"""
import sys
from os.path import isfile
if sys.version_info[0] >= 3:
    from urllib.parse import urlencode
    import urllib.request as urllib2
    import http.cookiejar as cookielib
else:
    from urllib import urlencode
    import urllib2
    import cookielib

class RequestError(Exception):
    """
        Erreur levée lors d'une requête
    """
    pass

def get_cookie_handler(cookie_file=None):
    """
        Renvoie le gestionnaire de cookie
    """
    if cookie_file and isfile(cookie_file):
        cookie_handler = cookielib.LWPCookieJar()
        cookie_handler.load(cookie_file)
        return cookie_handler
    return None

def get_cookie_processor(cookie_handler):
    """
        Ajoute la gestion automatique de cookie dans urllib2
    """
    return urllib2.HTTPCookieProcessor(cookie_handler)

def get_proxy_handler(proxy={}):
    """
        Désactive la détection automatique du proxy
        en forçant un proxy vide
        :proxy: configuration d'un proxy (ex:{'http': 'http://www.someproxy.com:3128'})
    """
    return urllib2.ProxyHandler(proxy)

class DefLog:
    """
        Au cas où il n'y a pas de logger
    """
    def error(self, *args):
        """
            pour printer une erreur
        """
        for i in args:
            print(i)

class HTTPRequest:
    """
        Envoie des requêtes http
        :cookie_file: fichier de cookie utilisé
        :proxy: description d'un proxy ex : {'http':'http://toto.com:3128'}
    """
    def __init__(self, cookie_file=None, proxy=None, log=None):
        self.log = log or DefLog()
        # Cookie
        self.cookie_file = cookie_file
        # Proxy
        self.proxy = proxy
        # création de l'opener (objet qui rajoute les conf proxy...
        self.make_opener()

    def make_opener(self):
        """
            Crée un gestionnaire d'ouverture de requête (cookie, proxy)
        """
        handlers = []
        handlers.append(get_proxy_handler(self.proxy))
        self.cookie_handler = get_cookie_handler(self.cookie_file)
        if self.cookie_handler:
            handlers.append(get_cookie_processor(self.cookie_handler))
        self.opener = urllib2.build_opener(*handlers)

    def request(self, url_script, post_datas={}, get_datas={}, headers={}):
        """
            éxécute une requête
            :url_script: url à appeller
            :post_datas: arguments POST
            :get_datas: arguments envoyés en GET
            :headers: comme son nom l'indique
        """
        self.url_script = url_script
        # Header et corp de la requête
        self.headers = headers
        self.post_datas = urlencode(post_datas)
        self.get_datas = urlencode(get_datas)
        if sys.version_info[0] >= 3:
            self.post_datas = self.post_datas.encode('utf-8')
            self.get_datas = self.get_datas.encode('utf-8')
        return self._do_request(self._build_request())

    def _build_request(self):
        """
            Construit la requête
        """
        if self.get_datas:
            url_script = "%s?%s" % (self.url_script, self.get_datas)
        else:
            url_script = self.url_script
        return urllib2.Request(url_script, self.post_datas, self.headers)

    def _do_request(self, myrequest):
        """
            éxécute la requête
        """
        try:
            urllib2.install_opener(self.opener)
            handle = urllib2.urlopen(myrequest)
        except IOError as err:
            self.log.error(" # Erreur : une erreur est survenue lors de la \
requête vers : %s" % (self.url_script,))
            if hasattr(err, 'reason'):
                self.log.error(' - Echec à la connexion au serveur.')
                self.log.error(' - Raison: %s' % (err.reason,))
            elif hasattr(err, 'code'):
                self.log.error(" - Le serveur n'a pu satisfaire la demande.")
                self.log.error(" - Code d' erreur : %s" % (err.code,))
            raise RequestError("Une erreur est survenue lors de la requête.")
        self.save_cookies()
        return handle.read()

    def save_cookies(self):
        """
            sauvegarde les cookies de session à la fin de la requête
        """
        if self.cookie_file:
            self.cookie_handler.save(self.cookie_file)

