
#
# This file defines the layer that talks to lldb
#

from __future__ import print_function

import os
import re
import sys
import lldb
import vim
from vim_ui import UI

# =================================================
# Convert some enum value to its string counterpart
# =================================================

# Shamelessly copy/pasted from lldbutil.py in the test suite


def state_type_to_str(enum):
    """Returns the stateType string given an enum."""
    if enum == lldb.eStateInvalid:
        return "invalid"
    elif enum == lldb.eStateUnloaded:
        return "unloaded"
    elif enum == lldb.eStateConnected:
        return "connected"
    elif enum == lldb.eStateAttaching:
        return "attaching"
    elif enum == lldb.eStateLaunching:
        return "launching"
    elif enum == lldb.eStateStopped:
        return "stopped"
    elif enum == lldb.eStateRunning:
        return "running"
    elif enum == lldb.eStateStepping:
        return "stepping"
    elif enum == lldb.eStateCrashed:
        return "crashed"
    elif enum == lldb.eStateDetached:
        return "detached"
    elif enum == lldb.eStateExited:
        return "exited"
    elif enum == lldb.eStateSuspended:
        return "suspended"
    else:
        raise Exception("Unknown StateType enum")


class StepType:
    INSTRUCTION = 1
    INSTRUCTION_OVER = 2
    INTO = 3
    OVER = 4
    OUT = 5


class LLDBController(object):
    """ Handles Vim and LLDB events such as commands and lldb events. """

    # Timeouts (sec) for waiting on new events. Because vim is not multi-threaded, we are restricted to
    # servicing LLDB events from the main UI thread. Usually, we only process events that are already
    # sitting on the queue. But in some situations (when we are expecting an event as a result of some
    # user interaction) we want to wait for it. The constants below set these wait period in which the
    # Vim UI is "blocked". Lower numbers will make Vim more responsive, but LLDB will be delayed and higher
    # numbers will mean that LLDB events are processed faster, but the Vim UI may appear less responsive at
    # times.
    eventDelayStep = 2
    eventDelayLaunch = 1
    eventDelayContinue = 1

    def __init__(self):
        """ Creates the LLDB SBDebugger object and initializes the UI class. """
        self.target = None
        self.process = None
        self.load_dependent_modules = True

        self.dbg = lldb.SBDebugger.Create()
        self.commandInterpreter = self.dbg.GetCommandInterpreter()

        self.ui = UI()

    def completeCommand(self, a, l, p):
        """ Returns a list of viable completions for command a with length l and cursor at p  """

        assert l[0] == 'L'
        # Remove first 'L' character that all commands start with
        l = l[1:]

        # Adjust length as string has 1 less character
        p = int(p) - 1

        result = lldb.SBStringList()
        num = self.commandInterpreter.HandleCompletion(l, p, 1, -1, result)

        if num == -1:
            # FIXME: insert completion character... what's a completion
            # character?
            pass
        elif num == -2:
            # FIXME: replace line with result.GetStringAtIndex(0)
            pass

        if result.GetSize() > 0:
            results = [_f for _f in [result.GetStringAtIndex(x)
                                    for x in range(result.GetSize())] if _f]
            return results
        else:
            return []

    def doStep(self, stepType):
        """ Perform a step command and block the UI for eventDelayStep seconds in order to process
            events on lldb's event queue.
            FIXME: if the step does not complete in eventDelayStep seconds, we relinquish control to
                   the main thread to avoid the appearance of a "hang". If this happens, the UI will
                   update whenever; usually when the user moves the cursor. This is somewhat annoying.
        """
        if not self.process:
            sys.stderr.write("No process to step")
            return

        t = self.process.GetSelectedThread()
        if stepType == StepType.INSTRUCTION:
            t.StepInstruction(False)
        if stepType == StepType.INSTRUCTION_OVER:
            t.StepInstruction(True)
        elif stepType == StepType.INTO:
            t.StepInto()
        elif stepType == StepType.OVER:
            t.StepOver()
        elif stepType == StepType.OUT:
            t.StepOut()

        self.processPendingEvents(self.eventDelayStep, True)

    def doSelect(self, command, args):
        """ Like doCommand, but suppress output when "select" is the first argument."""
        a = args.split(' ')
        return self.doCommand(command, args, "select" != a[0], True)

    def doProcess(self, args):
        """ Handle 'process' command. If 'launch' is requested, use doLaunch() instead
            of the command interpreter to start the inferior process.
        """
        a = args.split(' ')
        if len(args) == 0 or (len(a) > 0 and a[0] != 'launch'):
            self.doCommand("process", args)
            #self.ui.update(self.target, "", self)
        else:
            self.doLaunch('-s' not in args, "")

    def doAttach(self, process_name):
        """ Handle process attach.  """
        error = lldb.SBError()

        self.processListener = lldb.SBListener("process_event_listener")
        self.target = self.dbg.CreateTarget('')
        self.process = self.target.AttachToProcessWithName(
            self.processListener, process_name, False, error)
        if not error.Success():
            sys.stderr.write("Error during attach: " + str(error))
            return

        self.ui.activate()
        self.pid = self.process.GetProcessID()

        print("Attached to %s (pid=%d)" % (process_name, self.pid))

    def doDetach(self):
        if self.process is not None and self.process.IsValid():
            pid = self.process.GetProcessID()
            state = state_type_to_str(self.process.GetState())
            self.process.Detach()
            self.processPendingEvents(self.eventDelayLaunch)

    def doLaunch(self, stop_at_entry, args):
        """ Handle process launch.  """
        error = lldb.SBError()

        fs = self.target.GetExecutable()
        exe = os.path.join(fs.GetDirectory(), fs.GetFilename())
        if self.process is not None and self.process.IsValid():
            pid = self.process.GetProcessID()
            state = state_type_to_str(self.process.GetState())
            self.process.Destroy()

        launchInfo = lldb.SBLaunchInfo(args.split(' '))
        self.process = self.target.Launch(launchInfo, error)
        if not error.Success():
            sys.stderr.write("Error during launch: " + str(error))
            return

        # launch succeeded, store pid and add some event listeners
        self.pid = self.process.GetProcessID()
        self.processListener = lldb.SBListener("process_event_listener")
        self.process.GetBroadcaster().AddListener(
            self.processListener, lldb.SBProcess.eBroadcastBitStateChanged)

        print("Launched %s %s (pid=%d)" % (exe, args, self.pid))

        if not stop_at_entry:
            self.doContinue()
        else:
            self.processPendingEvents(self.eventDelayLaunch)

    def doTarget(self, args):
        """ Pass target command to interpreter, except if argument is not one of the valid options, or
            is create, in which case try to create a target with the argument as the executable. For example:
              target list        ==> handled by interpreter
              target create blah ==> custom creation of target 'blah'
              target blah        ==> also creates target blah
        """
        target_args = [  # "create",
            "delete",
            "list",
            "modules",
            "select",
            "stop-hook",
            "symbols",
            "variable"]

        a = args.split(' ')
        if len(args) == 0 or (len(a) > 0 and a[0] in target_args):
            self.doCommand("target", args)
            return
        elif len(a) > 1 and a[0] == "create":
            exe = a[1]
        elif len(a) == 1 and a[0] not in target_args:
            exe = a[0]

        err = lldb.SBError()
        self.target = self.dbg.CreateTarget(
            exe, None, None, self.load_dependent_modules, err)
        if not self.target:
            sys.stderr.write(
                "Error creating target %s. %s" %
                (str(exe), str(err)))
            return

        self.ui.activate()
        self.ui.update(self.target, "created target %s" % str(exe), self)

    def doContinue(self):
        """ Handle 'contiue' command.
            FIXME: switch to doCommand("continue", ...) to handle -i ignore-count param.
        """
        if not self.process or not self.process.IsValid():
            sys.stderr.write("No process to continue")
            return

        self.process.Continue()
        self.processPendingEvents(self.eventDelayContinue)

    def doBreakpoint(self, args):
        """ Handle breakpoint command with command interpreter, except if the user calls
            "breakpoint" with no other args, in which case add a breakpoint at the line
            under the cursor.
        """
        a = args.split(' ')
        if len(args) == 0:
            show_output = False

            # User called us with no args, so toggle the bp under cursor
            cw = vim.current.window
            cb = vim.current.buffer
            name = cb.name
            line = cw.cursor[0]

            # Since the UI is responsbile for placing signs at bp locations, we have to
            # ask it if there already is one or more breakpoints at (file,
            # line)...
            if self.ui.haveBreakpoint(name, line):
                bps = self.ui.getBreakpoints(name, line)
                args = "delete %s" % " ".join([str(b.GetID()) for b in bps])
                self.ui.deleteBreakpoints(name, line)
            else:
                args = "set -f %s -l %d" % (name, line)
        else:
            show_output = True

        self.doCommand("breakpoint", args, show_output)
        return

    def doRefresh(self):
        """ process pending events and update UI on request """
        status = self.processPendingEvents()

    def doShow(self, name):
        """ handle :Lshow <name> """
        if not name:
            self.ui.activate()
            return

        if self.ui.showWindow(name):
            self.ui.update(self.target, "", self)

    def doHide(self, name):
        """ handle :Lhide <name> """
        if self.ui.hideWindow(name):
            self.ui.update(self.target, "", self)

    def doExit(self):
        self.dbg.Terminate()
        self.dbg = None

    def getCommandResult(self, command, command_args):
        """ Run cmd in the command interpreter and returns (success, output) """
        result = lldb.SBCommandReturnObject()
        cmd = "%s %s" % (command, command_args)

        self.commandInterpreter.HandleCommand(cmd, result)
        return (result.Succeeded(), result.GetOutput()
                if result.Succeeded() else result.GetError())

    def doCommand(
            self,
            command,
            command_args,
            print_on_success=True,
            goto_file=False):
        """ Run cmd in interpreter and print result (success or failure) on the vim status line. """
        (success, output) = self.getCommandResult(command, command_args)
        if success:
            self.ui.update(self.target, "", self, goto_file)
            if len(output) > 0 and print_on_success:
                print(output)
        else:
            sys.stderr.write(output)

    def getCommandOutput(self, command, command_args=""):
        """ runs cmd in the command interpreter andreturns (status, result) """
        result = lldb.SBCommandReturnObject()
        cmd = "%s %s" % (command, command_args)
        self.commandInterpreter.HandleCommand(cmd, result)
        return (result.Succeeded(), result.GetOutput()
                if result.Succeeded() else result.GetError())

    def processPendingEvents(self, wait_seconds=0, goto_file=True):
        """ Handle any events that are queued from the inferior.
            Blocks for at most wait_seconds, or if wait_seconds == 0,
            process only events that are already queued.
        """

        status = None
        num_events_handled = 0

        if self.process is not None:
            event = lldb.SBEvent()
            old_state = self.process.GetState()
            new_state = None
            done = False
            if old_state == lldb.eStateInvalid or old_state == lldb.eStateExited:
                # Early-exit if we are in 'boring' states
                pass
            else:
                while not done and self.processListener is not None:
                    if not self.processListener.PeekAtNextEvent(event):
                        if wait_seconds > 0:
                            # No events on the queue, but we are allowed to wait for wait_seconds
                            # for any events to show up.
                            self.processListener.WaitForEvent(
                                wait_seconds, event)
                            new_state = lldb.SBProcess.GetStateFromEvent(event)

                            num_events_handled += 1

                        done = not self.processListener.PeekAtNextEvent(event)
                    else:
                        # An event is on the queue, process it here.
                        self.processListener.GetNextEvent(event)
                        new_state = lldb.SBProcess.GetStateFromEvent(event)

                        # continue if stopped after attaching
                        if old_state == lldb.eStateAttaching and new_state == lldb.eStateStopped:
                            self.process.Continue()

                        # If needed, perform any event-specific behaviour here
                        num_events_handled += 1

        if num_events_handled == 0:
            pass
        else:
            if old_state == new_state:
                status = ""
            self.ui.update(self.target, status, self, goto_file)


def returnCompleteCommand(a, l, p):
    """ Returns a "\n"-separated string with possible completion results
        for command a with length l and cursor at p.
    """
    separator = "\n"
    results = ctrl.completeCommand(a, l, p)
    vim.command('return "%s%s"' % (separator.join(results), separator))


def returnCompleteWindow(a, l, p):
    """ Returns a "\n"-separated string with possible completion results
        for commands that expect a window name parameter (like hide/show).
        FIXME: connect to ctrl.ui instead of hardcoding the list here
    """
    separator = "\n"
    results = [
        'breakpoints',
        'backtrace',
        'disassembly',
        'locals',
        'threads',
        'registers']
    vim.command('return "%s%s"' % (separator.join(results), separator))

global ctrl
ctrl = LLDBController()
