# pylint: disable=W0611
#
# Copyright (c) 2003-2013 LOGILAB S.A. (Paris, FRANCE).
# http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
"""some functions that may be useful for various checkers
"""

import re
import sys
import string

import astroid
from astroid import scoped_nodes
from logilab.common.compat import builtins

BUILTINS_NAME = builtins.__name__
COMP_NODE_TYPES = astroid.ListComp, astroid.SetComp, astroid.DictComp, astroid.GenExpr
PY3K = sys.version_info[0] == 3


class NoSuchArgumentError(Exception):
    pass

def is_inside_except(node):
    """Returns true if node is inside the name of an except handler."""
    current = node
    while current and not isinstance(current.parent, astroid.ExceptHandler):
        current = current.parent

    return current and current is current.parent.name


def get_all_elements(node):
    """Recursively returns all atoms in nested lists and tuples."""
    if isinstance(node, (astroid.Tuple, astroid.List)):
        for child in node.elts:
            for e in get_all_elements(child):
                yield e
    else:
        yield node


def clobber_in_except(node):
    """Checks if an assignment node in an except handler clobbers an existing
    variable.

    Returns (True, args for W0623) if assignment clobbers an existing variable,
    (False, None) otherwise.
    """
    if isinstance(node, astroid.AssAttr):
        return (True, (node.attrname, 'object %r' % (node.expr.as_string(),)))
    elif isinstance(node, astroid.AssName):
        name = node.name
        if is_builtin(name):
            return (True, (name, 'builtins'))
        else:
            stmts = node.lookup(name)[1]
            if (stmts and not isinstance(stmts[0].ass_type(),
                                         (astroid.Assign, astroid.AugAssign,
                                          astroid.ExceptHandler))):
                return (True, (name, 'outer scope (line %s)' % stmts[0].fromlineno))
    return (False, None)


def safe_infer(node):
    """return the inferred value for the given node.
    Return None if inference failed or if there is some ambiguity (more than
    one node has been inferred)
    """
    try:
        inferit = node.infer()
        value = inferit.next()
    except astroid.InferenceError:
        return
    try:
        inferit.next()
        return # None if there is ambiguity on the inferred node
    except astroid.InferenceError:
        return # there is some kind of ambiguity
    except StopIteration:
        return value

def is_super(node):
    """return True if the node is referencing the "super" builtin function
    """
    if getattr(node, 'name', None) == 'super' and \
           node.root().name == BUILTINS_NAME:
        return True
    return False

def is_error(node):
    """return true if the function does nothing but raising an exception"""
    for child_node in node.get_children():
        if isinstance(child_node, astroid.Raise):
            return True
        return False

def is_raising(body):
    """return true if the given statement node raise an exception"""
    for node in body:
        if isinstance(node, astroid.Raise):
            return True
    return False

def is_empty(body):
    """return true if the given node does nothing but 'pass'"""
    return len(body) == 1 and isinstance(body[0], astroid.Pass)

builtins = builtins.__dict__.copy()
SPECIAL_BUILTINS = ('__builtins__',) # '__path__', '__file__')

def is_builtin_object(node):
    """Returns True if the given node is an object from the __builtin__ module."""
    return node and node.root().name == BUILTINS_NAME

def is_builtin(name): # was is_native_builtin
    """return true if <name> could be considered as a builtin defined by python
    """
    if name in builtins:
        return True
    if name in SPECIAL_BUILTINS:
        return True
    return False

def is_defined_before(var_node):
    """return True if the variable node is defined by a parent node (list,
    set, dict, or generator comprehension, lambda) or in a previous sibling
    node on the same line (statement_defining ; statement_using)
    """
    varname = var_node.name
    _node = var_node.parent
    while _node:
        if isinstance(_node, COMP_NODE_TYPES):
            for ass_node in _node.nodes_of_class(astroid.AssName):
                if ass_node.name == varname:
                    return True
        elif isinstance(_node, astroid.For):
            for ass_node in _node.target.nodes_of_class(astroid.AssName):
                if ass_node.name == varname:
                    return True
        elif isinstance(_node, astroid.With):
            for expr, vars in _node.items:
                if expr.parent_of(var_node):
                    break
                if (vars and
                        isinstance(vars, astroid.AssName) and
                        vars.name == varname):
                    return True
        elif isinstance(_node, (astroid.Lambda, astroid.Function)):
            if _node.args.is_argument(varname):
                return True
            if getattr(_node, 'name', None) == varname:
                return True
            break
        elif isinstance(_node, astroid.ExceptHandler):
            if isinstance(_node.name, astroid.AssName):
                ass_node = _node.name
                if ass_node.name == varname:
                    return True
        _node = _node.parent
    # possibly multiple statements on the same line using semi colon separator
    stmt = var_node.statement()
    _node = stmt.previous_sibling()
    lineno = stmt.fromlineno
    while _node and _node.fromlineno == lineno:
        for ass_node in _node.nodes_of_class(astroid.AssName):
            if ass_node.name == varname:
                return True
        for imp_node in _node.nodes_of_class((astroid.From, astroid.Import)):
            if varname in [name[1] or name[0] for name in imp_node.names]:
                return True
        _node = _node.previous_sibling()
    return False

def is_func_default(node):
    """return true if the given Name node is used in function default argument's
    value
    """
    parent = node.scope()
    if isinstance(parent, astroid.Function):
        for default_node in parent.args.defaults:
            for default_name_node in default_node.nodes_of_class(astroid.Name):
                if default_name_node is node:
                    return True
    return False

def is_func_decorator(node):
    """return true if the name is used in function decorator"""
    parent = node.parent
    while parent is not None:
        if isinstance(parent, astroid.Decorators):
            return True
        if (parent.is_statement or
                isinstance(parent, astroid.Lambda) or
                isinstance(parent, (scoped_nodes.ComprehensionScope,
                                    scoped_nodes.ListComp))):
            break
        parent = parent.parent
    return False

def is_ancestor_name(frame, node):
    """return True if `frame` is a astroid.Class node with `node` in the
    subtree of its bases attribute
    """
    try:
        bases = frame.bases
    except AttributeError:
        return False
    for base in bases:
        if node in base.nodes_of_class(astroid.Name):
            return True
    return False

def assign_parent(node):
    """return the higher parent which is not an AssName, Tuple or List node
    """
    while node and isinstance(node, (astroid.AssName,
                                     astroid.Tuple,
                                     astroid.List)):
        node = node.parent
    return node

def overrides_an_abstract_method(class_node, name):
    """return True if pnode is a parent of node"""
    for ancestor in class_node.ancestors():
        if name in ancestor and isinstance(ancestor[name], astroid.Function) and \
               ancestor[name].is_abstract(pass_is_abstract=False):
            return True
    return False

def overrides_a_method(class_node, name):
    """return True if <name> is a method overridden from an ancestor"""
    for ancestor in class_node.ancestors():
        if name in ancestor and isinstance(ancestor[name], astroid.Function):
            return True
    return False

PYMETHODS = set(('__new__', '__init__', '__del__', '__hash__',
                 '__str__', '__repr__',
                 '__len__', '__iter__',
                 '__delete__', '__get__', '__set__',
                 '__getitem__', '__setitem__', '__delitem__', '__contains__',
                 '__getattribute__', '__getattr__', '__setattr__', '__delattr__',
                 '__call__',
                 '__enter__', '__exit__',
                 '__cmp__', '__ge__', '__gt__', '__le__', '__lt__', '__eq__',
                 '__nonzero__', '__neg__', '__invert__',
                 '__mul__', '__imul__', '__rmul__',
                 '__div__', '__idiv__', '__rdiv__',
                 '__add__', '__iadd__', '__radd__',
                 '__sub__', '__isub__', '__rsub__',
                 '__pow__', '__ipow__', '__rpow__',
                 '__mod__', '__imod__', '__rmod__',
                 '__and__', '__iand__', '__rand__',
                 '__or__', '__ior__', '__ror__',
                 '__xor__', '__ixor__', '__rxor__',
                 # XXX To be continued
                ))

def check_messages(*messages):
    """decorator to store messages that are handled by a checker method"""

    def store_messages(func):
        func.checks_msgs = messages
        return func
    return store_messages

class IncompleteFormatString(Exception):
    """A format string ended in the middle of a format specifier."""
    pass

class UnsupportedFormatCharacter(Exception):
    """A format character in a format string is not one of the supported
    format characters."""
    def __init__(self, index):
        Exception.__init__(self, index)
        self.index = index

def parse_format_string(format_string):
    """Parses a format string, returning a tuple of (keys, num_args), where keys
    is the set of mapping keys in the format string, and num_args is the number
    of arguments required by the format string.  Raises
    IncompleteFormatString or UnsupportedFormatCharacter if a
    parse error occurs."""
    keys = set()
    num_args = 0
    def next_char(i):
        i += 1
        if i == len(format_string):
            raise IncompleteFormatString
        return (i, format_string[i])
    i = 0
    while i < len(format_string):
        char = format_string[i]
        if char == '%':
            i, char = next_char(i)
            # Parse the mapping key (optional).
            key = None
            if char == '(':
                depth = 1
                i, char = next_char(i)
                key_start = i
                while depth != 0:
                    if char == '(':
                        depth += 1
                    elif char == ')':
                        depth -= 1
                    i, char = next_char(i)
                key_end = i - 1
                key = format_string[key_start:key_end]

            # Parse the conversion flags (optional).
            while char in '#0- +':
                i, char = next_char(i)
            # Parse the minimum field width (optional).
            if char == '*':
                num_args += 1
                i, char = next_char(i)
            else:
                while char in string.digits:
                    i, char = next_char(i)
            # Parse the precision (optional).
            if char == '.':
                i, char = next_char(i)
                if char == '*':
                    num_args += 1
                    i, char = next_char(i)
                else:
                    while char in string.digits:
                        i, char = next_char(i)
            # Parse the length modifier (optional).
            if char in 'hlL':
                i, char = next_char(i)
            # Parse the conversion type (mandatory).
            if PY3K:
                flags = 'diouxXeEfFgGcrs%a'
            else:
                flags = 'diouxXeEfFgGcrs%'
            if char not in flags:
                raise UnsupportedFormatCharacter(i)
            if key:
                keys.add(key)
            elif char != '%':
                num_args += 1
        i += 1
    return keys, num_args


def is_attr_protected(attrname):
    """return True if attribute name is protected (start with _ and some other
    details), False otherwise.
    """
    return attrname[0] == '_' and not attrname == '_' and not (
        attrname.startswith('__') and attrname.endswith('__'))

def node_frame_class(node):
    """return klass node for a method node (or a staticmethod or a
    classmethod), return null otherwise
    """
    klass = node.frame()

    while klass is not None and not isinstance(klass, astroid.Class):
        if klass.parent is None:
            klass = None
        else:
            klass = klass.parent.frame()

    return klass

def is_super_call(expr):
    """return True if expression node is a function call and if function name
    is super. Check before that you're in a method.
    """
    return (isinstance(expr, astroid.CallFunc) and
            isinstance(expr.func, astroid.Name) and
            expr.func.name == 'super')

def is_attr_private(attrname):
    """Check that attribute name is private (at least two leading underscores,
    at most one trailing underscore)
    """
    regex = re.compile('^_{2,}.*[^_]+_?$')
    return regex.match(attrname)

def get_argument_from_call(callfunc_node, position=None, keyword=None):
    """Returns the specified argument from a function call.

    :param callfunc_node: Node representing a function call to check.
    :param int position: position of the argument.
    :param str keyword: the keyword of the argument.

    :returns: The node representing the argument, None if the argument is not found.
    :raises ValueError: if both position and keyword are None.
    :raises NoSuchArgumentError: if no argument at the provided position or with
    the provided keyword.
    """
    if position is None and keyword is None:
        raise ValueError('Must specify at least one of: position or keyword.')
    try:
        if position is not None and not isinstance(callfunc_node.args[position], astroid.Keyword):
            return callfunc_node.args[position]
    except IndexError, error:
        raise NoSuchArgumentError(error)
    if keyword:
        for arg in callfunc_node.args:
            if isinstance(arg, astroid.Keyword) and arg.arg == keyword:
                return arg.value
    raise NoSuchArgumentError
