# -*- coding: utf-8 -*-

# Copyright (c) 2003 Detlev Offenbach <detlev@die-offenbachs.de>
#

"""
Module implementing the handler class for reading an XML project session file.
"""

import codecs
import sys
import os
from types import UnicodeType

from xml.sax.handler import ContentHandler

from qt import qApp

class SessionHandler(ContentHandler):
    """
    Class implementing a sax handler to read an XML project session file.
    """
    def __init__(self, project):
        self.elements = {
            'Filename' : (self.defaultStartElement, self.endFilename),
            'ActiveWindow' : (self.defaultStartElement, self.endFilename),
            'Breakpoint' : (self.startBreakpoint, self.endBreakpoint),
            'BpFilename' : (self.defaultStartElement, self.endBFilename),
            'Linenumber' : (self.startLinenumber, self.defaultEndElement),
            'Condition' : (self.defaultStartElement, self.endCondition),
            'Enabled' : (self.startEnabled, self.defaultEndElement),
            'Count' : (self.startCount, self.defaultEndElement),
            'CommandLine' : (self.defaultStartElement, self.endCommandLine),
            'WorkingDirectory' : (self.defaultStartElement, self.endWorkingDirectory),
            'ReportExceptions' : (self.startReportExceptions, self.defaultEndElement),
            'Exceptions' : (self.startExceptions, self.endExceptions),
            'Exception' : (self.defaultStartElement, self.endException),
            'Bookmark' : (self.startBookmark, self.endBookmark),
            'BmFilename' : (self.defaultStartElement, self.endBFilename),
        }
    
        self.project = project
        self.vm = qApp.mainWidget().getViewManager()
        self.dbg = qApp.mainWidget().getDebugger()
        
        self.encoder = codecs.lookup(sys.getdefaultencoding())[0] # encode,decode,reader,writer
        
    def utf8_to_code(self, text):
        if type(text) is not UnicodeType:
            text = unicode(text, "utf-8")
        return self.encoder(text)[0] # result,size
        
    def unescape(self, text):
        return text.replace("&gt;",">").replace("&lt;","<").replace("&amp;","&")
        
    def startDocument(self):
        self.buffer = ""
        
        # clear all breakpoints and bookmarks first (in case we are rereading a session file)
        files = self.project.getSources(1)
        for file in files:
            editor = self.vm.getOpenEditor(file)
            if editor is not None:
                editor.handleClearBreakpoints()
                editor.handleClearBookmarks()
        
    def startElement(self, name, attrs):
        try:
            self.elements[name][0](attrs)
        except KeyError:
            pass
            
    def endElement(self, name):
        try:
            self.elements[name][1]()
        except KeyError:
            pass
            
    def characters(self, chars):
        self.buffer += chars
        
    ###################################################
    ## below follow the individual handler functions
    ###################################################
    
    def defaultStartElement(self, attrs):
        self.buffer = ""
        
    def defaultEndElement(self):
        pass
        
    def endFilename(self):
        self.buffer = self.utf8_to_code(self.buffer)
        self.vm.handleOpen(self.buffer)
        
    def startBreakpoint(self, attrs):
        self.filename = ""
        self.lineno = 0
        self.bpCond = ""
        self.bpTemp = 0
        self.bpEnabled = 1
        self.bpCount = 0
        
    def endBreakpoint(self):
        self.dbg.newBreakpointWithProperties(self.filename, self.lineno,
            (self.bpCond, self.bpTemp, self.bpEnabled, self.bpCount))
            
    def endBFilename(self):
        self.filename = self.utf8_to_code(self.buffer)
        
    def startLinenumber(self, attrs):
        self.lineno = int(attrs["value"])
        
    def endCondition(self):
        cond = self.utf8_to_code(self.buffer)
        cond = self.unescape(cond)
        if cond == 'None' or cond == '':
            self.bpCond = None
        else:
            self.bpCond = cond
            
    def startEnabled(self, attrs):
        self.bpEnabled = int(attrs["value"])
        
    def startCount(self, attrs):
        self.bpCount = int(attrs["value"])
        
    def endCommandLine(self):
        self.buffer = self.utf8_to_code(self.buffer)
        self.buffer = self.unescape(self.buffer)
        self.dbg.setArgvHistory(self.buffer)
        self.project.dbgCmdline = self.buffer
        
    def endWorkingDirectory(self):
        self.buffer = self.utf8_to_code(self.buffer)
        self.dbg.setWdHistory(self.buffer)
        self.project.dbgWd = self.buffer
        
    def startReportExceptions(self, attrs):
        exc = int(attrs["value"])
        self.dbg.setExceptionReporting(exc)
        self.project.dbgReportExceptions = exc
        
    def startExceptions(self, attrs):
        self.dbgExcList = []
        
    def endExceptions(self):
        self.dbg.setExcList(self.dbgExcList)
        
    def endException(self):
        self.buffer = self.utf8_to_code(self.buffer)
        self.dbgExcList.append(self.buffer)
        
    def startBookmark(self, attrs):
        self.filename = ""
        self.lineno = 0
        
    def endBookmark(self):
        editor = self.vm.getOpenEditor(self.filename)
        if editor is not None:
            editor.handleBookmark(self.lineno)
