import logging, logrecv
from xml.dom.minidom import parseString

# executed on import
CONFIG = 0
logging.addLevelName(CONFIG, 'CONFIG')

# CONFIG on telephone... pick a better number ;)
DEFAULT_CONFIG_PORT = 26644

class Hub(logging.Filterer):
    def __init__(self):
        logging.Filterer.__init__(self)
        self.actions = []
        self.loop_back = LoopbackHandler(self)
        self.config_port = ConfigPort(self)

    def addAction(self, action):
        self.actions.append(action)

    def removeAction(self, action):
        self.actions.remove(action)

    def handleLogRecord(self, record):
        '''Pass record through the following steps:
           1. Filter
           2. Check for configuration changes
           3. Pass the LogRecord on to the Actions
        '''
        if not self.filter(record):
            return
        if record.level == CONFIG:
            self.applyConfig(record.message)
            return
        for action in self.actions:
            action.handleLogRecord(record)

    def handleConfigMessage(self, record):
        '''Do something with the CONFIG message
        '''
        self.applyConfig(record.message)

    def applyConfig(self, config):
        '''Handle a config XML string
        '''
        dom = parseString(config)

    def getLoopBack(self):
        return self.loop_back

    def getConfigPort(self):
        return self.config_port


class Receiver(logging.Filterer):
    def __init__(self, hub):
        '''Pass on LogRecords from my input to the Hub
        '''
        self.hub = hub
        logging.Filterer.__init__(self)

    def handleLogRecord(self, record):
        '''Do something with the LogRecord
        '''
        if not self.filter(record):
            return
        self.hub.handleLogRecord(record)

class Action(logging.Filterer):
    def __init__(self):
        self.handlers = []
        logging.Filterer.__init__(self)

    def handleLogRecord(self, record):
        '''First see if it should be discarded or modified.

           If not discarded, forward the record on to the handlers
           defined in the forward attribute.
        '''
        if not self.filter(record):
            return

        # all OK, forward
        for handler in self.handlers:
            handler.handle(record)

    def addHandler(self, hdlr):
        """
        Add the specified handler to this logger.
        """
        if not (hdlr in self.handlers):
            self.handlers.append(hdlr)

    def removeHandler(self, hdlr):
        """
        Remove the specified handler from this logger.
        """
        if hdlr in self.handlers:
            self.handlers.remove(hdlr)

class LoopbackHandler(Receiver, logging.Handler):
    def __init__(self, hub, level=0):
        '''Register the hub for looping the messages back
        '''
        Receiver.__init__(self, hub)
        logging.Handler.__init__(self, level)

    def emit(self, record):
        '''Pass the record on to the hub
        '''
        self.handleLogRecord(record)


class LogRecordStreamHandler(logrecv.LogRecordStreamHandler):
    '''Basic TCP stream listener
    '''
    def handleLogRecord(self, record):
        '''pass the record back to the server's Receiver functionality
        '''
        self.server.handleLogRecord(record)

class LogRecordDatagramHandler(logrecv.LogRecordDatagramHandler):
    '''Basic TCP stream listener
    '''
    def handleLogRecord(self, record):
        '''pass the record back to the server's Receiver functionality
        '''
        self.server.handleLogRecord(record)


class TCPReceiver(Receiver, logrecv.LogRecordSocketReceiver):
    def __init__(self, hub, host='localhost',
            port=logging.DEFAULT_TCP_LOGGING_PORT,
            handler=LogRecordStreamHandler):
        Receiver.__init__(self, hub)
        logrecv.LogRecordSocketReceiver.__init__(self, host, port, handler)

class UDPReceiver(Receiver, logrecv.LogRecordDatagramReceiver):
    def __init__(self, hub, host='localhost',
            port=logging.DEFAULT_UDP_LOGGING_PORT,
            handler=LogRecordDatagramHandler):
        Receiver.__init__(self, hub)
        logrecv.LogRecordDatagramReceiver.__init__(self, host, port, handler)


class ConfigPort(Receiver, logrecv.LogRecordSocketReceiver):
    '''Listen for CONFIG events on the network.
    '''
    def __init__(self, hub, host='localhost', port=DEFAULT_CONFIG_PORT,
            handler=LogRecordStreamHandler):
        Receiver.__init__(self, hub)
        logrecv.LogRecordSocketReceiver.__init__(self, host, port, handler)
        filter = logging.Filter()
        filter.level = [CONFIG]
        self.addFilter(filter)

