import os
import re
import imp
import hashlib

from collections import defaultdict

def init_analyzer(parameters):
    if isinstance(parameters,str):
        class_str = parameters
        kwargs = {}
    else:
        class_str = parameters[0]
        kwargs = parameters[1]
    (module_name,separator,class_name) = class_str.rpartition(".")
    module = __import__(module_name,globals(),locals(),[class_name],-1)
    return getattr(module,class_name)(**kwargs)

def get_files_list(path,with_sha = False):
    files = []
    for (dirpath,dirnames,filenames) in os.walk(path):
        files.extend([(dirpath+"/"+f)[len(path):] for f in filenames])
    return files

def apply_filter(filename,patterns):
    return reduce(lambda x,y:x or y,[True if re.search(pattern,filename) else False for pattern in patterns],False)

def analyze_string(string,filename,analyzers):
    file_stats = {}
    file_issues = {}
    for language,language_parameters in analyzers.items():
        if 'patterns' in language_parameters and not apply_filter(filename,language_parameters['patterns']):
            continue
        for analyzer_name,analyzer_parameters in language_parameters['analyzers'].items():
            analyzer = init_analyzer(analyzer_parameters)
            file_stats[analyzer_name],file_issues[analyzer_name] = analyzer.analyze(string)
        break
    return file_stats,file_issues

def analyze_file(filename,analyzers):
    with open(filename,"r") as input_file:
        content = input_file.read()
    return analyze_string(content,filename,analyzers)

def aggregate_statistics(file_stats,analyzers,aggregators):
    results = defaultdict(lambda : defaultdict(lambda:{}))
    items_by_key = defaultdict(lambda : [])
    for name,aggregator in aggregators.items():
        for path,item in file_stats.items():
            keys = aggregator(path,item)
            for key in keys:
                items_by_key[key].append(item)
    for language,language_parameters in analyzers.items():
        for analyzer_name,analyzer_parameters in language_parameters['analyzers'].items():
            analyzer = init_analyzer(analyzer_parameters)
            for key in items_by_key:
                results[language][analyzer_name][key] = analyzer.aggregate( [f[analyzer_name] for f in items_by_key[key] if analyzer_name in f])
            results[language][analyzer_name] = dict(results[language][analyzer_name])
        results[language] = dict(results[language])
    return dict(results)    
