import time
import sys

from .lib import ConversionTable, Converter

class Emitter(object):
    # XXX ABC me!
    def __init__(self, min_level):
        self.min_level = min_level

    def filter(self, msg):
        return True

    def format(self, msg):
        raise NotImplementedError

    def output(self, msg, fields, text):
        raise NotImplementedError

    def emit(self, msg):
        if self.filter(msg):
            s = self.format(msg)
            self.output(msg, s)

class StandardEmitter(Emitter):

    def __init__(self, min_level, separator=':', traceback_prefix='\nTRACE ',
                 conversion=None, **kwargs):
        super(StandardEmitter, self).__init__(min_level, **kwargs)
        self.separator = separator
        self.traceback_prefix = traceback_prefix

        if conversion is not None:
            self.conversion = conversion
        else:
            # XXX move this def out of init
            self.conversion = ConversionTable([
                Converter('time', time.ctime, '{1}'.format, True),
                Converter('level', str, '{1}'.format, True),
                Converter('name', str, '{1}'.format),
            ])

            self.conversion.genericValue = str
            self.conversion.genericItem = "{0}={1}".format
            self.conversion.aggregate = self.separator.join

    def format(self, msg):
        fields = self.format_fields(msg)
        text = self.format_text(msg)
        trace = self.format_traceback(msg)
        return "{fields}{self.separator}{text}{trace}".format(**locals()) # XXX gross?

    def format_text(self, msg):
        if msg.suppress_newlines:
            return msg.text.replace('\n', '\\n')
        else:
            return msg.text

    def format_traceback(self, msg):
        if msg.traceback is not None:
            # XXX this could be faster
            l = msg.traceback.split('\n')
            l = [""] + l[:-1]
            return self.traceback_prefix.join(l)
        else:
            return ""

    def format_fields(self, msg):
        return self.conversion.convert(msg.fields)

    def output(self, msg, s):
        print>>sys.stderr, s
@@ -81,24 +81,141 @@
 er(object):%0A
+    %22%22%22%0A    Emits!%0A%0A    :ivar min_level: only emit if greater than this%0A    :type min_level: Levels.LogLevel%0A    %22%22%22%0A
     # XXX AB
@@ -218,17 +218,17 @@
 X ABC me
-!
+?
 %0A    def
@@ -330,47 +330,268 @@
     
-return True%0A%0A    def format(self, msg):
+%22%22%22return True if the message should be emitted%0A%0A        I could be %3Csome_regex%3E.match, perhaps%0A        %22%22%22%0A        return True%0A%0A    def format(self, msg):%0A        %22%22%22%0A        :returns: the formatted message, ready for output%0A        :rtype: string%0A        %22%22%22
 %0A   
@@ -652,22 +652,47 @@
 sg, 
-fields, text):
+s):%0A        %22%22%22write out the message%22%22%22
 %0A   
@@ -740,32 +740,110 @@
 mit(self, msg):%0A
+        %22%22%22emit a message.%0A%0A        This is the only external API%0A        %22%22%22%0A
         if self.
@@ -1073,24 +1073,254 @@
  **kwargs):%0A
+        %22%22%22%0A        Interesting trick:%0A        Setting traceback_prefix to '%5C%5Cn' rolls it up to a single line.%0A%0A        :ivar conversion: helper to turn a message to a string%0A        :type conversion: ConversionTable%0A%0A        %22%22%22%0A
         supe
@@ -1671,16 +1671,20 @@
 ter(
+key=
 'time', 
 time
@@ -1683,20 +1683,45 @@
 e', 
-time.ctime, 
+convertValue=time.ctime, convertItem=
 '%7B1%7D
@@ -1722,32 +1722,41 @@
 m='%7B1%7D'.format, 
+required=
 True),%0A         

document emitter api