import os
import csv
import json
import pickle
import shutil
import fnmatch
import collections

class DirWalk():
    """
    for filename in DirWalk('*.c').walk(roots):
        do a thing with the c-files in the roots directories
    """
    def __init__(self,
                 pattern='*',
                 folder_include_pattern='*',
                 folder_exclude_pattern='.git',
                 file_exclude_pattern='',
                 yield_files=True,
                 yield_folders=False):
        """
        Generator for walking the file system and filtering the results.
        """
        self.pattern = pattern
        self.folder_include_pattern = folder_include_pattern
        self.folder_exclude_pattern = folder_exclude_pattern
        self.file_exclude_pattern = file_exclude_pattern
        self.yield_files = yield_files
        self.yield_folders = yield_folders

    def walk(self, roots=None):
        """ Walk the directory looking for files matching the pattern """
        if roots is None:
            roots = []
        for root in roots:
            for dirpath, dirnames, filenames in os.walk(root):
                # Filters
                filenames[:] = [
                    i for i in filenames if self.pattern_match(i, self.pattern)
                    and not self.pattern_match(i, self.file_exclude_pattern)]
                dirnames[:] = [
                    i for i in dirnames
                    if self.pattern_match(i, self.folder_include_pattern)
                    and not self.pattern_match(i, self.folder_exclude_pattern)]
                # Yields
                if self.yield_files:
                    for filename in filenames:
                        yield os.path.normpath(os.path.join(dirpath, filename))
                if self.yield_folders:
                    for dirname in dirnames:
                        yield os.path.normpath(os.path.join(dirpath, dirname))

    @staticmethod
    def pattern_match(text, patterns):
        """ Match filename patterns """
        if not patterns:
            return False
        for pattern in patterns.split(';'):
            if fnmatch.fnmatch(text, pattern):
                return True
        return False
