from lxml.builder import ElementMaker
from lxml.etree import tostring, parse, XPath
from httplib import HTTPConnection

SOAP_NO_NAME = "--NONAME--"

class Soap(object):
    def __init__(self,domain,url,namespace,servicename):        
        self.domain = domain
        self.url = url
        self.namespace = namespace
        self.serviceName = servicename
        self.xpathNamespace  = { 'thens': self.namespace }

    
    def soap_response(self, response):
        reply = parse(response)
        return reply
	
    def XPathWithQuery(self, query):
        return XPath( query, namespaces=self.xpathNamespace)

    def makeRequest(self, methodname, request):	    
        thesoapaction = ""
        if(self.serviceName == SOAP_NO_NAME):
            thesoapaction = (self.addTrailingSlash(self.namespace) + methodname)
        else:
            thesoapaction = (self.addTrailingSlash(self.namespace) + self.serviceName +"/"+ methodname)
        
        headers = {
            'Content-Type': 'text/xml; charset=utf-8',
            'SOAPAction': thesoapaction
        }
        requestelement = ElementMaker(
            namespace='http://schemas.xmlsoap.org/soap/envelope/',
            nsmap={
		        'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
		        'xsd': 'http://www.w3.org/2001/XMLSchema',
		        'soap': 'http://schemas.xmlsoap.org/soap/envelope/',
            })
        envelope = requestelement.Envelope
        body = requestelement.Body
        requestxml = envelope(body(request))
        conn = HTTPConnection(self.domain)
        conn.request('POST', self.url, tostring(requestxml), headers)
        response = conn.getresponse()
        if response.status == 200:
            return self.soap_response(response)
        else:
            raise RuntimeError(
	             'soap_request: bad response',
	             response.status,
	             response.reason
                 )
    
    def addTrailingSlash(self, namespace):
        ret = namespace
        if(len(ret) > 2):
            if(ret[-1] == '/'):
                pass
            else:
                ret =  (ret + '/')
        return ret

