# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of astroid.
#
# astroid is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the
# Free Software Foundation, either version 2.1 of the License, or (at your
# option) any later version.
#
# astroid is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
# for more details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with astroid. If not, see <http://www.gnu.org/licenses/>.
"""this module contains some utilities to navigate in the tree or to
extract information from it
"""
from __future__ import print_function

__docformat__ = "restructuredtext en"

from astroid.exceptions import AstroidBuildingException
from astroid.builder import parse


class ASTWalker(object):
    """a walker visiting a tree in preorder, calling on the handler:

    * visit_<class name> on entering a node, where class name is the class of
    the node in lower case

    * leave_<class name> on leaving a node, where class name is the class of
    the node in lower case
    """

    def __init__(self, handler):
        self.handler = handler
        self._cache = {}

    def walk(self, node, _done=None):
        """walk on the tree from <node>, getting callbacks from handler"""
        if _done is None:
            _done = set()
        if node in _done:
            raise AssertionError((id(node), node, node.parent))
        _done.add(node)
        self.visit(node)
        for child_node in node.get_children():
            self.handler.set_context(node, child_node)
            assert child_node is not node
            self.walk(child_node, _done)
        self.leave(node)
        assert node.parent is not node

    def get_callbacks(self, node):
        """get callbacks from handler for the visited node"""
        klass = node.__class__
        methods = self._cache.get(klass)
        if methods is None:
            handler = self.handler
            kid = klass.__name__.lower()
            e_method = getattr(handler, 'visit_%s' % kid,
                               getattr(handler, 'visit_default', None))
            l_method = getattr(handler, 'leave_%s' % kid,
                               getattr(handler, 'leave_default', None))
            self._cache[klass] = (e_method, l_method)
        else:
            e_method, l_method = methods
        return e_method, l_method

    def visit(self, node):
        """walk on the tree from <node>, getting callbacks from handler"""
        method = self.get_callbacks(node)[0]
        if method is not None:
            method(node)

    def leave(self, node):
        """walk on the tree from <node>, getting callbacks from handler"""
        method = self.get_callbacks(node)[1]
        if method is not None:
            method(node)


class LocalsVisitor(ASTWalker):
    """visit a project by traversing the locals dictionary"""
    def __init__(self):
        ASTWalker.__init__(self, self)
        self._visited = {}

    def visit(self, node):
        """launch the visit starting from the given node"""
        if node in self._visited:
            return
        self._visited[node] = 1 # FIXME: use set ?
        methods = self.get_callbacks(node)
        if methods[0] is not None:
            methods[0](node)
        if 'locals' in node.__dict__: # skip Instance and other proxy
            for local_node in node.values():
                self.visit(local_node)
        if methods[1] is not None:
            return methods[1](node)


def _check_children(node):
    """a helper function to check children - parent relations"""
    for child in node.get_children():
        ok = False
        if child is None:
            print("Hm, child of %s is None" % node)
            continue
        if not hasattr(child, 'parent'):
            print(" ERROR: %s has child %s %x with no parent" % (
                node, child, id(child)))
        elif not child.parent:
            print(" ERROR: %s has child %s %x with parent %r" % (
                node, child, id(child), child.parent))
        elif child.parent is not node:
            print(" ERROR: %s %x has child %s %x with wrong parent %s" % (
                node, id(node), child, id(child), child.parent))
        else:
            ok = True
        if not ok:
            print("lines;", node.lineno, child.lineno)
            print("of module", node.root(), node.root().name)
            raise AstroidBuildingException
        _check_children(child)


class TreeTester(object):
    '''A helper class to see _ast tree and compare with astroid tree

    indent: string for tree indent representation
    lineno: bool to tell if we should print the line numbers

    >>> tester = TreeTester('print')
    >>> print tester.native_tree_repr()

    <Module>
    .   body = [
    .   <Print>
    .   .   nl = True
    .   ]
    >>> print tester.astroid_tree_repr()
    Module()
        body = [
        Print()
            dest =
            values = [
            ]
        ]
    '''

    indent = '.   '
    lineno = False

    def __init__(self, sourcecode):
        self._string = ''
        self.sourcecode = sourcecode
        self._ast_node = None
        self.build_ast()

    def build_ast(self):
        """build the _ast tree from the source code"""
        self._ast_node = parse(self.sourcecode)

    def native_tree_repr(self, node=None, indent=''):
        """get a nice representation of the _ast tree"""
        self._string = ''
        if node is None:
            node = self._ast_node
        self._native_repr_tree(node, indent)
        return self._string


    def _native_repr_tree(self, node, indent, _done=None):
        """recursive method for the native tree representation"""
        from _ast import Load as _Load, Store as _Store, Del as _Del
        from _ast import AST as Node
        if _done is None:
            _done = set()
        if node in _done:
            self._string += '\nloop in tree: %r (%s)' % (
                node, getattr(node, 'lineno', None))
            return
        _done.add(node)
        self._string += '\n' + indent +  '<%s>' % node.__class__.__name__
        indent += self.indent
        if not hasattr(node, '__dict__'):
            self._string += '\n' + self.indent + " ** node has no __dict__ " + str(node)
            return
        node_dict = node.__dict__
        if hasattr(node, '_attributes'):
            for a in node._attributes:
                attr = node_dict[a]
                if attr is None:
                    continue
                if a in ("lineno", "col_offset") and not self.lineno:
                    continue
                self._string += '\n' +  indent + a + " = " + repr(attr)
        for field in node._fields or ():
            attr = node_dict[field]
            if attr is None:
                continue
            if isinstance(attr, list):
                if not attr:
                    continue
                self._string += '\n' + indent + field + ' = ['
                for elt in attr:
                    self._native_repr_tree(elt, indent, _done)
                self._string += '\n' + indent + ']'
                continue
            if isinstance(attr, (_Load, _Store, _Del)):
                continue
            if isinstance(attr, Node):
                self._string += '\n' + indent + field + " = "
                self._native_repr_tree(attr, indent, _done)
            else:
                self._string += '\n' + indent + field + " = " + repr(attr)


    def build_astroid_tree(self):
        """build astroid tree from the _ast tree
        """
        from astroid.builder import AstroidBuilder
        tree = AstroidBuilder().string_build(self.sourcecode)
        return tree

    def astroid_tree_repr(self, ids=False):
        """build the astroid tree and return a nice tree representation"""
        mod = self.build_astroid_tree()
        return mod.repr_tree(ids)


__all__ = ('LocalsVisitor', 'ASTWalker',)

