class Output(object):
    """
    Handles output
    """
    INDENT = "    "
    
    def __init__(self, info, verbose, debug):
        
        self._info = set( info + verbose + debug )
        self._verbose = set( verbose + debug )
        self._debug = set( debug )
        self._level = 0
        
        
    def info(self, msg):
        
        self.write_message_onto( msg = msg, streams = self._info )
        
        
    def verbose(self, msg):
        
        self.write_message_onto( msg = msg, streams = self._verbose )
        
        
    def debug(self, msg):
        
        self.write_message_onto( msg = msg, streams = self._debug )
        
        
    def indent(self):
        
        self._level += 1
        
        
    def dedent(self):
        
        self._level = max( 0, self._level - 1 )
        
        
    def basedent(self):
        
        self._level = 0
            
    
    def write_message_onto(self, msg, streams):
        
        lines = msg.split( "\n" )
        
        for s in streams:
            for l in lines:
                s.write( "%s%s\n" % ( self.INDENT * self._level, l ) )

                
class SingleStreamOutput(object):
    """
    Handles output
    """
    
    INDENT = "    "
    
    DEBUG = 0
    VERBOSE = 1
    INFO = 2
    WARNING = 3
    
    def __init__(self, stream, level):
        
        if stream is None:
            self._stream = self.__class__
        
        else:
            self._stream = stream
            
        self._level = level
        self._indent = 0
        
        
    def warning(self, msg):
        
        self.log( msg = msg, level = self.WARNING )
        
    
    def info(self, msg):
        
        self.log( msg = msg, level = self.INFO )
        
        
    def verbose(self, msg):
        
        self.log( msg = msg, level = self.VERBOSE )
        
        
    def debug(self, msg):
        
        self.log( msg = msg, level = self.DEBUG )
        
        
    def log(self, msg, level):
        
        if self._level <= level:
            for l in msg.split( "\n" ):
                self._stream.write( "%s%s\n" % ( self.INDENT * self._indent, l ) )
        
        
    def indent(self):
        
        self._indent += 1
        
        
    def dedent(self):
        
        self._indent = max( 0, self._indent - 1 )
        
        
    def basedent(self):
        
        self._indent = 0
        
        
    @classmethod
    def Debug(cls, stream = None):
        
        return cls( stream = stream, level = cls.DEBUG )
    
    
    @classmethod
    def Verbose(cls, stream = None):
        
        return cls( stream = stream, level = cls.VERBOSE )
    
    
    @classmethod
    def Info(cls, stream = None):
        
        return cls( stream = stream, level = cls.INFO )
    
    
    @classmethod
    def Warning(cls, stream = None):
        
        return cls( stream = stream, level = cls.WARNING )
        
    
    # This simulates the empty stream
    @staticmethod
    def write(message):
        pass

    
def title(text):
        
    separator = "#" * ( len( text ) + 4 )
    return "\n".join( [ "", separator, "# %s #" % text, separator, "" ] )
    

def subtitle(text):
    
    return "\n".join( [ "", text, "=" * len( text ), "" ] )
    
    
def underlined(text):
    
    return "\n".join( [ "", text, "-" * len( text ), "" ] )
    
    
def heading(text):
    
    return "\n".join( [ "", text, "" ] )
    
    
def section_close(text):
    
    return "\n".join( [ "", text, "" ] )
