#! /usr/bin/env python
from __future__ import print_function
import os
import re
from abjad.tools import systemtools


directory_name_blacklist = (
    'demos',
    )

file_name_blacklist = (
    'ez_setup.py',
    'getters.py',
    'predicates.py',
    'setup.py',
    )

class_definition_pattern = re.compile(r'^class\s+(\w+)')
function_definition_pattern = re.compile(r'^def\s+(\w+)')


def find_multifunction_modules():

    multifunction_modules = []
    for directory, subdirectory_names, file_names in os.walk('.'):
        subdirectory_names_to_remove = []
        for subdirectory_name in subdirectory_names:
            if subdirectory_name in directory_name_blacklist:
                subdirectory_names_to_remove.append(subdirectory_name)
        for subdirectory_name in subdirectory_names_to_remove:
            subdirectory_names.remove(subdirectory_name)
        for file_name in file_names:
            if file_name.endswith('.py') and \
                file_name not in file_name_blacklist:
                if not file_name.startswith('test_'):
                    result = has_multiple_public_function_definitions(
                        directory,
                        file_name
                        )
                    if result:
                        file_path = os.path.join(directory, file_name)
                        result_pair = (file_path, result)
                        multifunction_modules.append(result_pair)

    total = len(multifunction_modules)
    if total:
        print('Printing modles with multiple public functions ...')
        print()
        for module_name, function_names in multifunction_modules:
            print(module_name)
            for function_name in function_names:
                print('\t' + function_name)
            print()

    print('Total modules with multiple public functions: {}'.format(total))
    print()


def has_multiple_public_function_definitions(path, file_name):
    function_names = []
    full_name = os.path.join(path, file_name)
    with open(full_name, 'r') as file_pointer:
        for line in file_pointer:
            match = class_definition_pattern.match(line)
            if match is not None:
                return False
            match = function_definition_pattern.match(line)
            if match is not None:
                function_name = match.groups()[0]
                if not function_name.startswith('_'):
                    function_names.append(function_name)
    if 1 < len(function_names):
        return function_names
    else:
        return False


if __name__ == '__main__':
    systemtools.IOManager.clear_terminal()
    find_multifunction_modules()
