import httplib
from urlparse import urlparse
from threading import Semaphore
from logging import debug, info, warning, error

from Config import Config
from Exceptions import ParameterError

__all__ = [ "ConnMan" ]

import httplib
import socket
 
class http_connection(object):
    def __init__(self, id, hostname, ssl, cfg):
		self.hostname = hostname
		self.ssl = ssl
		self.id = id
		self.counter = 0
		debug("http_connection: to %s" % hostname)
		if cfg.proxy_host != "":
			debug("http_connection: via proxy %s" % cfg.proxy_host)
			self.c = httplib.HTTPConnection(cfg.proxy_host, cfg.proxy_port)
		elif ssl:
			debug("http_connection: via SSL (443)")
			self.c = httplib.HTTPSConnection(hostname)
		elif cfg.interface:
			debug("http_connection: bind to IP %s" % cfg.interface)
			self.c = httplib.HTTPConnection(hostname,source_address=(cfg.interface,0))
			# inspired by http://stackoverflow.com/questions/1150332/source-interface-with-python-and-urllib2
		else:
			debug("http_connection: regular connection")
			self.c = httplib.HTTPConnection(hostname)

class ConnMan(object):
    conn_pool_sem = Semaphore()
    conn_pool = {}
    conn_max_counter = 800    ## AWS closes connection after some ~90 requests


    @staticmethod
    def get(hostname, ssl = None):
        cfg = Config()
        if ssl == None:
            ssl = cfg.use_https
        conn = None
        if cfg.proxy_host != "":
            if ssl:
                raise ParameterError("use_ssl=True can't be used with proxy")
            conn_id = "proxy://%s:%s" % (cfg.proxy_host, cfg.proxy_port)
        else:
            conn_id = "http%s://%s" % (ssl and "s" or "", hostname)
        ConnMan.conn_pool_sem.acquire()
        if not ConnMan.conn_pool.has_key(conn_id):
            ConnMan.conn_pool[conn_id] = []
        if len(ConnMan.conn_pool[conn_id]):
            conn = ConnMan.conn_pool[conn_id].pop()
            debug("ConnMan.get(): re-using connection: %s#%d" % (conn.id, conn.counter))
        ConnMan.conn_pool_sem.release()
        if not conn:
            debug("ConnMan.get(): prepare new connection: %s" % conn_id)
            conn = http_connection(conn_id, hostname, ssl, cfg)
            debug("ConnMan.get(): doing actual connect: %s" % conn_id)
            conn.c.connect()
            debug("ConnMan.get(): check actual connect: %s" % conn_id)
            if conn.c.source_address:
                debug("ConnMan.get(): bound to interface: %s:%d" % conn.c.source_address)
        conn.counter += 1
        return conn

    @staticmethod
    def put(conn):
        if conn.id.startswith("proxy://"):
            conn.c.close()
            debug("ConnMan.put(): closing proxy connection (keep-alive not yet supported)")
            return

        if conn.counter >= ConnMan.conn_max_counter:
            conn.c.close()
            debug("ConnMan.put(): closing over-used connection")
            return

        ConnMan.conn_pool_sem.acquire()
        ConnMan.conn_pool[conn.id].append(conn)
        ConnMan.conn_pool_sem.release()
        debug("ConnMan.put(): connection put back to pool (%s#%d)" % (conn.id, conn.counter))

