# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of logilab-common.
#
# logilab-common 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.
#
# logilab-common 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 logilab-common.  If not, see <http://www.gnu.org/licenses/>.
"""Customized version of pdb's default debugger.

- sets up a history file
- uses ipython if available to colorize lines of code
- overrides list command to search for current block instead
  of using 5 lines of context




"""

from __future__ import print_function

__docformat__ = "restructuredtext en"

try:
    import readline
except ImportError:
    readline = None
import os
import os.path as osp
import sys
from pdb import Pdb
import inspect

from logilab.common.compat import StringIO

try:
    from IPython import PyColorize
except ImportError:
    def colorize(source, *args):
        """fallback colorize function"""
        return source
    def colorize_source(source, *args):
        return source
else:
    def colorize(source, start_lineno, curlineno):
        """colorize and annotate source with linenos
        (as in pdb's list command)
        """
        parser = PyColorize.Parser()
        output = StringIO()
        parser.format(source, output)
        annotated = []
        for index, line in enumerate(output.getvalue().splitlines()):
            lineno = index + start_lineno
            if lineno == curlineno:
                annotated.append('%4s\t->\t%s' % (lineno, line))
            else:
                annotated.append('%4s\t\t%s' % (lineno, line))
        return '\n'.join(annotated)

    def colorize_source(source):
        """colorize given source"""
        parser = PyColorize.Parser()
        output = StringIO()
        parser.format(source, output)
        return output.getvalue()


def getsource(obj):
    """Return the text of the source code for an object.

    The argument may be a module, class, method, function, traceback, frame,
    or code object.  The source code is returned as a single string.  An
    IOError is raised if the source code cannot be retrieved."""
    lines, lnum = inspect.getsourcelines(obj)
    return ''.join(lines), lnum


################################################################
class Debugger(Pdb):
    """custom debugger

    - sets up a history file
    - uses ipython if available to colorize lines of code
    - overrides list command to search for current block instead
      of using 5 lines of context
    """
    def __init__(self, tcbk=None):
        Pdb.__init__(self)
        self.reset()
        if tcbk:
            while tcbk.tb_next is not None:
                tcbk = tcbk.tb_next
        self._tcbk = tcbk
        self._histfile = os.path.expanduser("~/.pdbhist")

    def setup_history_file(self):
        """if readline is available, read pdb history file
        """
        if readline is not None:
            try:
                # XXX try..except shouldn't be necessary
                # read_history_file() can accept None
                readline.read_history_file(self._histfile)
            except IOError:
                pass

    def start(self):
        """starts the interactive mode"""
        self.interaction(self._tcbk.tb_frame, self._tcbk)

    def setup(self, frame, tcbk):
        """setup hook: set up history file"""
        self.setup_history_file()
        Pdb.setup(self, frame, tcbk)

    def set_quit(self):
        """quit hook: save commands in the history file"""
        if readline is not None:
            readline.write_history_file(self._histfile)
        Pdb.set_quit(self)

    def complete_p(self, text, line, begin_idx, end_idx):
        """provide variable names completion for the ``p`` command"""
        namespace = dict(self.curframe.f_globals)
        namespace.update(self.curframe.f_locals)
        if '.' in text:
            return self.attr_matches(text, namespace)
        return [varname for varname in namespace if varname.startswith(text)]


    def attr_matches(self, text, namespace):
        """implementation coming from rlcompleter.Completer.attr_matches
        Compute matches when text contains a dot.

        Assuming the text is of the form NAME.NAME....[NAME], and is
        evaluatable in self.namespace, it will be evaluated and its attributes
        (as revealed by dir()) are used as possible completions.  (For class
        instances, class members are also considered.)

        WARNING: this can still invoke arbitrary C code, if an object
        with a __getattr__ hook is evaluated.

        """
        import re
        m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text)
        if not m:
            return
        expr, attr = m.group(1, 3)
        object = eval(expr, namespace)
        words = dir(object)
        if hasattr(object, '__class__'):
            words.append('__class__')
            words = words + self.get_class_members(object.__class__)
        matches = []
        n = len(attr)
        for word in words:
            if word[:n] == attr and word != "__builtins__":
                matches.append("%s.%s" % (expr, word))
        return matches

    def get_class_members(self, klass):
        """implementation coming from rlcompleter.get_class_members"""
        ret = dir(klass)
        if hasattr(klass, '__bases__'):
            for base in klass.__bases__:
                ret = ret + self.get_class_members(base)
        return ret

    ## specific / overridden commands
    def do_list(self, arg):
        """overrides default list command to display the surrounding block
        instead of 5 lines of context
        """
        self.lastcmd = 'list'
        if not arg:
            try:
                source, start_lineno = getsource(self.curframe)
                print(colorize(''.join(source), start_lineno,
                               self.curframe.f_lineno))
            except KeyboardInterrupt:
                pass
            except IOError:
                Pdb.do_list(self, arg)
        else:
            Pdb.do_list(self, arg)
    do_l = do_list

    def do_open(self, arg):
        """opens source file corresponding to the current stack level"""
        filename = self.curframe.f_code.co_filename
        lineno = self.curframe.f_lineno
        cmd = 'emacsclient --no-wait +%s %s' % (lineno, filename)
        os.system(cmd)

    do_o = do_open

def pm():
    """use our custom debugger"""
    dbg = Debugger(sys.last_traceback)
    dbg.start()

def set_trace():
    Debugger().set_trace(sys._getframe().f_back)
