import ast

import code_aggregators,file_aggregators,issue_generators
from ast_helpers import Node,AnalysisNodeVisitor,sanitize

from collections import defaultdict

class AstAnalyzer():

    code_aggregators = {
        'docstrings' : code_aggregators.docstrings,
#        'imports' : code_aggregators.imports,
        'classes' : code_aggregators.classes,
        'functions' : code_aggregators.functions,
        'variables' : code_aggregators.variables,
    }

    file_aggregators = {
        'docstrings' : file_aggregators.docstrings,
#        'imports' : file_aggregators.imports,
        'classes' : file_aggregators.classes,
        'functions' : file_aggregators.functions,
        'variables' : file_aggregators.variables,
    }

    issue_generators = {
        'complexity' : issue_generators.complexity
    }

    def _get_flat_nodes_list(self,root_node):
        nodes = [root_node]
        for child in root_node['children']:
            nodes.extend(self._get_flat_nodes_list(child))
        return nodes

    def aggregate(self,items):

        stats = defaultdict(lambda : {})

        for aggregator_name,aggregator_function in self.file_aggregators.items():
            stats[aggregator_name] = aggregator_function([item[aggregator_name] for item in items])

        return dict(stats)

    def analyze(self,content):
        try:
            p = ast.parse(content,mode='exec')
        except:
            return {},[{'type':'syntax error'}]
        fileNode = Node(attributes = {'type':'file','docstring':sanitize(ast.get_docstring(p,clean = True))})
        visitor = AnalysisNodeVisitor(parentNode = fileNode)
        visitor.visit(p)
        flat_nodes = self._get_flat_nodes_list(fileNode.to_dict())

        stats = {}
        issues = []

        for aggregator_name,aggregator_function in self.code_aggregators.items():
            stats[aggregator_name] = aggregator_function(flat_nodes)

        for issue_generator_name,issue_generator in self.issue_generators.items():
            issues.extend(issue_generator(flat_nodes))

        return stats,issues

