# -*- coding: utf-8 -*-
# Hah, don't you love the pervasiveness of Emacs?
from xml.sax.handler import ContentHandler

class MurrayHandler(ContentHandler):
    """
    FIXME()
    """

    # Basic element <stream:stream/>
    __inStream = False

    # The three Stooges... errr... building blocks of Jabber/XMPP
    __inMessage = False
    __inPresence = False
    __inIQ = False

    # <message/>
    __inBody = False
    __inHTML = False
    __inThread = False
    __inError = False

    # <presence/>
    __inShow = False
    __inStatus = False
    __inPriority = False

    # <iq/>
    __inQuery = False
    __inUsername = False
    __inPassword = False

    # Holds the current characters if told to do so.  See
    # characters().
    __currentCharacters = {}

    # Always holds the current <element/>
    __currentElement = ""

    # Always holds the current type (e.g. as in <presence type="available"/>)
    __currentType = ""

    
    __currentTo = ""
    __currentXMLNameSpace = ""
    __recordCharacters = False

    def __init__(self, vader):
        self.vader = vader

    def startElement(self, name, attrs):
        """FIXME()"""

        # FIXME(Eigene exception anstatt RuntimeError? sax ErrorHandler?)

        print "Start element:", name

        # Prepare an array element to hold the current element's text.
        # If there was anything in it now it is not.
        self.__currentElement = name
        self.__currentCharacters[self.__currentElement] = ""

        if name == "stream:stream" and not self.__inStream:
            self.__handleStreamStart(attrs)

        elif name == "message":
            self.__handleMessageStart(attrs)

        elif name == "body":
            self.__handleBodyStart(attrs)

        elif name == "thread":
            self.__handleThreadStart(attrs)

        elif name == "html":
            self.__handleHTMLStart(attrs)

        elif name == "error":
            self.__handleErrorStart(attrs)

        elif name == "presence":
            self.__handlePresenceStart(attrs)

        elif name == "iq":
            self.__handleIQStart(attrs)

        elif name == "query":
            self.__handleQueryStart(attrs)

        elif name == "username":
            self.__handleUsernameStart(attrs)

        elif name == "password":
            self.__handlePasswordStart(attrs)


    def endElement(self, name):
        """FIXME()"""

        if name == "stream:stream" and self.__inStream:
            self.__handleStreamEnd()

        elif name == "message":
            self.__handleMessageEnd()

        elif name == "body":
            self.__handleBodyEnd()

        elif name == "html":
            self.__handleHTMLEnd()

        elif name == "error":
            self.__handleErrorEnd()

        elif name == "presence":
            self.__handlePresenceEnd()

        elif name == "iq":
            self.__handleIQEnd()

        elif name == "body":
            self.__handleBodyEnd()

        elif name == "query":
            self.__handleQueryEnd()

        elif name == "username":
            self.__handleUsernameEnd()

        elif name == "password":
            self.__handlePasswordEnd()

        print "End element:", name


    def characters(self, characters):
        """FIXME() (x)HTML will get eaten by the SAX parser.  Well,
        tough tuckers..."""

        if self.__recordCharacters:
            self.__currentCharacters[self.__currentElement] += characters

    def __handleMessageStart(self, attrs):
        """FIXME()"""
        if self.__inStream:
            self.__inMessage = True
            self.__currentType = attrs['type'] if attrs.has_key('type') else None
            self.__currentTo = attrs['to'] if attrs.has_key('to') else None
            self.__currentID = attrs['id'] if attrs.has_key('id') else None
        else:
            raise RuntimeError

    def __handleMessageEnd(self):
        """FIXME()"""
        if self.__inStream:
            self.__currentType = ""
            self.__currentID = ""
            self.__currentTo = ""
            self.__currentXMLNameSpace = ""
            self.__inMessage = False
            print self.__currentCharacters['body'] if self.__currentCharacters.has_key('body') else "No <body/>?"
            self.vader.sendMessage(id, self.__currentType, self.__currentTo,
                                   self.__currentCharacters['body'],
                                   self.__currentCharacters['subject'],
                                   self.__currentCharacters['thread'],
                                   self.__currentCharacters['error'])
        else:
            raise RuntimeError

    def __handleHTMLStart(self, attrs):
        """If an <html> tag is encountered in a message throw a
        RuntimeError.  HTML gets eaten by the SAX parser anyway, so
        doing this is not as evil as it sounds...  The state gets set
        to ease future incooperating of HTML parsing."""
        if self.__inStream and self.__inMessage:
            self.__inHTML = True
            raise RuntimeError
        else:
            raise RuntimeError

    def __handleHTMLEnd(self):
        """If an </html> tag is encountered clear the __inHTML state.
        But see __handleHTMLStart()."""
        if self.__inStream and self.__inMessage:
            self.__inHTML = False
        else:
            raise RuntimeError
        

    def __handlePresenceStart(self, attrs):
        """FIXME()"""
        if self.__inStream:
            self.__inPresence = True
            self.__currentType = attrs['type'] if attrs.has_key('type') else None
            self.__currentTo = attrs['to'] if attrs.has_key('to') else None
            self.__currentID = attrs['id'] if attrs.has_key('id') else None
        else:
            raise RuntimeError

    def __handlePresenceEnd(self):
        """FIXME()"""
        if self.__inStream:
            if __currentType == "probe":
                pass
            
            elif __currentType == "subscribe":
                pass

            elif __currentType == "unsubscribe":
                pass

            elif __currentType == "subscribed":
                pass

            elif __currentType == "unsubscribed":
                pass
            
            elif __currentType == "unavailable":
                pass

            else: # "available"
                status = self.__currentCharacters['status'] \
                         if self.__currentCharacters.has_key('status') \
                         else None
                show = self.__currentCharacters['show'] \
                       if self.__currentCharacters.has_key('show') \
                       else None
                priority = self.__currentCharacters['priority'] \
                           if self.__currentCharacters.has_key('priority') \
                           else None
                
                vader.sendPresence(id, self.__currentType, to, show, status, priority)

            self.__currentType = ""
            self.__currentID = ""
            self.__currentTo = ""
            self.__inPresence = False
        else:
            raise RuntimeError


    def __handleIQStart(self, attrs):
        """FIXME()"""
        if self.__inStream:
            self.__inIQ = True
            self.__currentType = attrs['type'] if attrs.has_key('type') else None
            self.__currentID = attrs['id'] if attrs.has_key('id') else None
        else:
            raise RuntimeError

    def __handleIQEnd(self):
        """FIXME(An Info/Query can have four types (get, set, result
        and error) and the contained query is qualified by a XML
        namespace."""

        if self.__inStream:
            # Query for the needed registration infos
            if not self.vader.getSession() \
                   and self.__inIQ \
                   and self.__currentType == "get" \
                   and self.__currentXMLNameSpace == "jabber:iq:register":
                self.vader.sendRegistrationRequirements(
                    self.__currentID
                    )

            # Passing the needed registration infos
            elif not self.vader.getSession() \
                     and self.__inIQ \
                     and self.__currentType == "set" \
                     and self.__currentXMLNameSpace == "jabber:iq:register":
                self.vader.sendRegistrationResult(
                    self.__currentID,
                    self.__currentCharacters['username'],
                    self.__currentCharacters['password']
                    )

            # Query for the needed authentication infos
            elif not self.vader.getSession() \
                     and self.__inIQ \
                     and self.__currentType == "get" \
                     and self.__currentXMLNameSpace == "jabber:iq:auth":
                self.vader.sendAuthenticationInfo(
                    self.__currentID,
                    self.__currentCharacters['username']
                    )

            # Passing of the needed authentication infos
            elif not self.vader.getSession() \
                     and self.__inIQ \
                     and self.__currentType == "set" \
                     and self.__currentXMLNameSpace == "jabber:iq:auth":
                self.vader.sendAuthenticationResult(
                    self.__currentID,
                    self.__currentCharacters['username'],
                    self.__currentCharacters['password']
                    )

            # Send the roster
            elif self.vader.getSession() \
                 and self.__inIQ \
                 and self.currentType == "get" \
                 and self.currentXMLNameSpace == "jabber:iq:roster":
                self.vader.sendRoster(
                    self.__currentID
                    )

            self.__inIQ = False
            self.__currentType = ""
            self.__currentID = ""
            self.__currentXMLNameSpace = ""

        else:
            raise RuntimeError

    def __handleSubjectStart(self, attrs):
        """FIXME()"""
        if self.__inStream and self.__inMessage:
            self.__inSubject = True
            self.__recordCharacters = True
        else:
            raise RuntimeError

    def __handleSubjectEnd(self):
        """FIXME()"""
        if self.__inStream and self.__inMessage:
            self.__inSubject = False
            self.__recordCharacters = False
        else:
            raise RuntimeError

    def __handleErrorStart(self, attrs):
        """FIXME(code etc. aufzeichnen)"""
        if self.__inStream and self.__inMessage:
            self.__inError = True
            self.__recordCharacters = True
        else:
            raise RuntimeError

    def __handleErrorEnd(self):
        """FIXME()"""
        if self.__inStream and self.__inMessage:
            self.__inError = False
            self.__recordCharacters = False
        else:
            raise RuntimeError

    def __handleThreadStart(self, attrs):
        """FIXME()"""
        if self.__inStream and self.__inMessage:
            self.__inThread = True
            self.__recordCharacters = True
        else:
            raise RuntimeError

    def __handleThreadEnd(self):
        """FIXME()"""
        if self.__inStream and self.__inMessage:
            self.__inThread = False
            self.__recordCharacters = False
        else:
            raise RuntimeError

    def __handleBodyStart(self, attrs):
        """FIXME()"""
        if self.__inStream and self.__inMessage:
            self.__inBody = True
            self.__recordCharacters = True
        else:
            raise RuntimeError

    def __handleBodyEnd(self):
        """FIXME()"""
        if self.__inStream and self.__inMessage:
            self.__inBody = False
            self.__recordCharacters = False
        else:
            raise RuntimeError

    def __handleStreamEnd(self):
        """FIXME()"""
        self.__inStream = False
        self.vader.requestSend(self.vader.murrayxmlcreator.destroyStream())

    def __handleStreamStart(self, attrs):
        """FIXME()"""
        self.__inStream = True
        self.vader.requestSend(
            self.vader.murrayxmlcreator.createStream(self.vader.getConnectionID())
            )

    def __handleQueryStart(self, attrs):
        """FIXME(Should be encountered only in <iq/>s...)"""
        self.__inQuery = True
        self.__currentXMLNameSpace = attrs['xmlns']

    def __handleQueryEnd(self):
        """FIXME()"""
        self.__inQuery = False

    def __handlePasswordStart(self, attrs):
        """FIXME()"""
        if self.__inStream \
           and self.__inIQ \
           and self.__inQuery:
            self.__inPassword = True
            self.__recordCharacters = True

    def __handlePasswordEnd(self):
        """FIXME()"""
        if self.__inStream \
           and self.__inIQ \
           and self.__inQuery:
            self.__inPassword = False
            self.__recordCharacters = False
            # password in self.__currentCharacters['password']

    def __handleUsernameStart(self, attrs):
        """FIXME()"""

        # FIXME(nicht immer den username mitschreiben, nur wenn
        # entsprechend sinnvoll, z.B. in xmlns="jabber:iq:auth" oder
        # xmlns="jabber:iq:register")
        if self.__inStream \
           and self.__inIQ \
           and self.__inQuery:
            self.__inUsername = True
            self.__recordCharacters = True

    def __handleUsernameEnd(self):
        """FIXME()"""
        if self.__inStream \
           and self.__inIQ \
           and self.__inQuery:
            self.__inUsername = False
            self.__recordCharacters = False
            # username in self.__currentCharacters['username']

    def __handleShowStart(self, attrs):
        """FIXME()"""
        if self.__inStream and self.__inPresence:
            self.__inShow = True
            self.__recordCharacters = True
        else:
            raise RuntimeError

    def __handleShowEnd(self):
        """FIXME()"""
        if self.__inStream and self.__inPresence:
            self.__inShow = False
            self.__recordCharacters = False
        else:
            raise RuntimeError

    def __handleStatusStart(self, attrs):
        """FIXME()"""
        if self.__inStream and self.__inPresence:
            self.__inStatus = True
            self.__recordCharacters = True
        else:
            raise RuntimeError

    def __handleStatusEnd(self):
        """FIXME()"""
        if self.__inStream and self.__inPresence:
            self.__inStatus = False
            self.__recordCharacters = False
        else:
            raise RuntimeError

    def __handlePriorityStart(self, attrs):
        """FIXME()"""
        if self.__inStream and self.__inPresence:
            self.__inPriority = True
            self.__recordCharacters = True
        else:
            raise RuntimeError

    def __handlePriorityEnd(self):
        """FIXME()"""
        if self.__inStream and self.__inPresence:
            self.__inPriority = False
            self.__recordCharacters = False
        else:
            raise RuntimeError

