import socket
from urllib.error import URLError

from ..console_write import console_write


class PersistentHandler:
    connection = None
    use_count = 0

    def close(self):
        if self.connection:
            if self._debuglevel == 5:
                s = '' if self.use_count == 1 else 's'
                console_write(
                    '''
                    Urllib %s Debug General
                      Closing connection to %s on port %s after %s request%s
                    ''',
                    (
                        self.connection._debug_protocol,
                        self.connection.host,
                        self.connection.port,
                        self.use_count,
                        s
                    )
                )
            self.connection.close()
            self.connection = None
            self.use_count = 0

    def do_open(self, http_class, req):
        # Large portions from Python 3.3 Lib/urllib/request.py and
        # Python 2.6 Lib/urllib2.py

        host = req.host

        if not host:
            raise URLError('no host given')

        if self.connection and self.connection.host != host:
            self.close()

        # Re-use the connection if possible
        self.use_count += 1
        if not self.connection:
            h = http_class(host, timeout=req.timeout)
        else:
            h = self.connection
            if self._debuglevel == 5:
                console_write(
                    '''
                    Urllib %s Debug General
                      Re-using connection to %s on port %s for request #%s
                    ''',
                    (h._debug_protocol, h.host, h.port, self.use_count)
                )

        headers = dict(req.unredirected_hdrs)
        headers.update(dict((k, v) for k, v in req.headers.items()
                            if k not in headers))
        headers = dict((name.title(), val) for name, val in headers.items())

        if req._tunnel_host and not self.connection:
            tunnel_headers = {}
            proxy_auth_hdr = "Proxy-Authorization"
            if proxy_auth_hdr in headers:
                tunnel_headers[proxy_auth_hdr] = headers[proxy_auth_hdr]
                del headers[proxy_auth_hdr]

            h.set_tunnel(req._tunnel_host, headers=tunnel_headers)

        try:
            h.request(req.get_method(), req.selector, req.data, headers)
        except socket.error as err:  # timeout error
            h.close()
            raise URLError(err)
        else:
            r = h.getresponse()

        # Keep the connection around for re-use
        if r.is_keep_alive():
            self.connection = h
        else:
            if self._debuglevel == 5:
                s = '' if self.use_count == 1 else 's'
                console_write(
                    '''
                    Urllib %s Debug General
                      Closing connection to %s on port %s after %s request%s
                    ''',
                    (h._debug_protocol, h.host, h.port, self.use_count, s)
                )
            self.use_count = 0
            self.connection = None

        r.url = req.get_full_url()
        r.msg = r.reason
        return r
