import xml.parsers.expat
import httplib2
import lxml
from lxml.etree import Element, ElementTree, HTML
from io import StringIO

# Just to get some example data
#con = httplib2.Http()
#con.add_credentials('wibble', 'fish')
#a, b = con.request("http://localhost/myWebDAV/", method="PROPFIND", headers={'Depth':'1'})

class Response(object):
    """

Response objects are for storing information about resources

"""

    def __init__(self):
        """

Response objects are for storing information about resources

"""

        self.href = None
        self.resourcetype = None
        self.creationdate = None
        self.getcontentlength = None
        self.getlastmodified = None
        self.getetag = None
        self.executable = None
        self.locks = []
        self.getcontenttype = None

class Lock(object):
    """ This is an object for storing resource lock information
    """
    def __init__(self):
        self.locktype = None
        self.lockscope = None

class Parser(object):
    def __init__(self):
        """
            Warning, this has been depreciated. Use LxxmlParser instead
        """
        self.element_list = []
        self.closed_elements = []
        self.response_objects = []
        self.current_element = None

        self.p = xml.parsers.expat.ParserCreate()
        self.p.StartElementHandler = self.start_element
        self.p.EndElementHandler = self.end_element
        self.p.CharacterDataHandler = self.char_data
        self.is_lock = False
        #self.p.StartNamespaceDeclHandler = self.ns_data

    def start_element(self, name, attrs):
        #print 'Start element:', name, attrs

        namespace, element_name = name.split(':')

        if element_name == 'response':
            # Make a new response object
            new_response = Response()
            # Put it into the list
            self.response_objects.append(new_response)
        elif self.is_lock:
            # If we are currently dealing with a supportedlock element make
            # sure we can deal with the scope and type
            if element_name == 'lockentry':
                self.response_objects[-1].locks.append(Lock())
            elif element_name == 'lockscope' or element_name == 'locktype':
                self.current_element = element_name

        elif element_name == 'supportedlock':
            self.is_lock = True
        else:
            self.current_element = element_name

    def end_element(self, name):
        namespace, element_name = name.split(':')
        if self.is_lock:
            if element_name == 'supportedlock':
                # Closing the supportedlock element
                self.is_lock = False
            elif self.current_element == 'lockscope':
                # If a lockscope element was found, set the value here
                self.response_objects[-1].locks[-1].lockscope = element_name
                self.current_element = element_name
            elif self.current_element == 'locktype':
                # If a locktype element was found, set the value here
                self.response_objects[-1].locks[-1].locktype = element_name
                self.current_element = element_name
        elif self.current_element == 'resourcetype':
            self.response_objects[-1].resourcetype = 'resource'
        elif self.current_element == 'collection':
            self.response_objects[-1].resourcetype = 'collection'


    def char_data(self, data):
        if data.strip():
            #self.element_list[-1].text = data

            setattr(self.response_objects[-1], self.current_element, data)

    #def ns_data(self, prefix, uri):
        #print "Namespace data:", prefix, uri

    def parse(self, data):
        try:
            self.p.Parse(data, 1)
        except Exception, err:
            err


class LxmlParser(object):
    def __init__(self):
        self.element_list = []
        self.closed_elements = []
        self.response_objects = []
        self.current_element = None

        #self.p = lxml.etree.
        #self.p.StartElementHandler = self.start_element
        #self.p.EndElementHandler = self.end_element
        #self.p.CharacterDataHandler = self.char_data
        self.is_lock = False

    def parse(self, data):
        try:
            data_elements = HTML(data)
            xml_etree = ElementTree(data_elements)
            all_response_elements = xml_etree.findall("//response")
            for response in all_response_elements:
                new_response = Response()
                resp_tree = ElementTree(response)
                new_response.href = resp_tree.find('//href').text
                if resp_tree.find('//collection') is not None:
                    new_response.resourcetype = 'collection'
                else:
                    new_response.resourcetype = 'resource'
                    new_response.executable = getattr(resp_tree.find('//executable'), 'text', None)
                new_response.creationdate = getattr(resp_tree.find('//creationdate'), 'text', None)
                new_response.getcontentlength = getattr(resp_tree.find('//getcontentlength'), 'text', None)
                new_response.getlastmodified = getattr(resp_tree.find('//getlastmodified'), 'text', None)
                new_response.getetag = getattr(resp_tree.find('//getetag'), 'text', None)
                new_response.getcontenttype = getattr(resp_tree.find('//getcontenttype'), 'text', None)

                # Now we have the properties that are easy to get, lets get the lock information
                lock_tree = resp_tree.findall('//lockentry')
                for lock in lock_tree:
                    lock_tree = ElementTree(lock)
                    lock_obj = Lock()
                    lock_obj.locktype = lock_tree.find('//locktype').getchildren()[-1].tag
                    lock_obj.lockscope = lock_tree.find('//lockscope').getchildren()[-1].tag
                    new_response.locks.append(lock_obj)

                self.response_objects.append(new_response)


        except Exception, err:
            err