import collections
import os.path
from zope import component
from zope import interface
from zope.component.factory import Factory
from sparc.configuration import container
import mellon

@interface.implementer(mellon.IByteMellonFile)
class MellonByteFileFromFilePathAndConfig(object):
    
    def __init__(self, file_path, config):
        self.file_path = file_path
        self.config = config
        
    def __str__(self):
        return "byte file at location {}".format(self.file_path)

    def __iter__(self):
        with open(self.file_path, 'rb') as stream:
            file_ = component.createObject(u'mellon.byte_file_from_stream', stream, self.config)
            for snippet in file_:
                yield snippet
mellonByteFileFromFilePathAndConfigFactory = Factory(MellonByteFileFromFilePathAndConfig)

@interface.implementer(mellon.IUnicodeMellonFile)
class MellonUnicodeFileFromFilePathAndConfig(object):
    
    def __init__(self, file_path, config):
        self.file_path = file_path
        self.config = config
        
    def __str__(self):
        return "Unicode file at location {}".format(self.file_path)

    def __iter__(self):
        _end = 0
        _buffer = collections.deque()
        _eof_buffer = collections.deque()
        with open(str(self.file_path), 'rU') as stream:
            file_ = component.createObject(u'mellon.unicode_file_from_stream', stream, self.config)
            for snippet in file_:
                yield snippet
mellonUnicodeFileFromFilePathAndConfigFactory = Factory(MellonUnicodeFileFromFilePathAndConfig)

@interface.implementer(mellon.IMellonFileProvider)
class MellonFileProviderForRecursiveDirectoryConfig(object):
    
    def __init__(self, config):
        """Init
        
        Args:
            config: sparc.configuration.container.ISparcAppPyContainerConfiguration
                    provider with 
                    mellon.factories.filesystem[configure.yaml:FileSystemDir]
                    and mellon[configure.yaml:MellonSnippet] entries.
        """
        self.config = config
    
    def __iter__(self):
        base_path = container.IPyContainerConfigValue(self.config).\
                                            get('FileSystemDir')['directory']
        for d, dirs, files in os.walk(base_path):
            for f in files:
                path = os.path.join(d, f)
                if not os.path.isfile(path):
                    continue
                #get interface-assigned string (IPath)
                path = component.createObject(u'mellon.filesystem_path', path)
                if mellon.IBinaryChecker(path).check():
                    yield component.createObject(\
                        u'mellon.factories.filesystem.byte_file', path, self.config)
                else:
                    yield component.createObject(\
                        u'mellon.factories.filesystem.unicode_file', path, self.config)
    
mellonFileProviderForRecursiveDirectoryConfigFactory = Factory(MellonFileProviderForRecursiveDirectoryConfig)
interface.alsoProvides(mellonFileProviderForRecursiveDirectoryConfigFactory, mellon.IMellonFileProviderFactory)

[(9, 'zope.interface.implementer', 'interface.implementer', False, 'from zope import interface\n'), (24, 'zope.component.factory.Factory', 'Factory', False, 'from zope.component.factory import Factory\n'), (26, 'zope.interface.implementer', 'interface.implementer', False, 'from zope import interface\n'), (44, 'zope.component.factory.Factory', 'Factory', False, 'from zope.component.factory import Factory\n'), (46, 'zope.interface.implementer', 'interface.implementer', False, 'from zope import interface\n'), (77, 'zope.component.factory.Factory', 'Factory', False, 'from zope.component.factory import Factory\n'), (78, 'zope.interface.alsoProvides', 'interface.alsoProvides', False, 'from zope import interface\n'), (38, 'collections.deque', 'collections.deque', False, 'import collections\n'), (39, 'collections.deque', 'collections.deque', False, 'import collections\n'), (21, 'zope.component.createObject', 'component.createObject', False, 'from zope import component\n'), (41, 'zope.component.createObject', 'component.createObject', False, 'from zope import component\n'), (69, 'zope.component.createObject', 'component.createObject', False, 'from zope import component\n'), (61, 'sparc.configuration.container.IPyContainerConfigValue', 'container.IPyContainerConfigValue', False, 'from sparc.configuration import container\n'), (70, 'mellon.IBinaryChecker', 'mellon.IBinaryChecker', False, 'import mellon\n'), (71, 'zope.component.createObject', 'component.createObject', False, 'from zope import component\n'), (74, 'zope.component.createObject', 'component.createObject', False, 'from zope import component\n')]