##===-- debuggerdriver.py ------------------------------------*- Python -*-===##
##
##                     The LLVM Compiler Infrastructure
##
## This file is distributed under the University of Illinois Open Source
## License. See LICENSE.TXT for details.
##
##===----------------------------------------------------------------------===##


import lldb
import lldbutil
import sys
from threading import Thread

class DebuggerDriver(Thread):
    """ Drives the debugger and responds to events. """
    def __init__(self, debugger, event_queue):
        Thread.__init__(self)
        self.event_queue = event_queue
        # This is probably not great because it does not give liblldb a chance to clean up
        self.daemon = True
        self.initialize(debugger)

    def initialize(self, debugger):
        self.done = False
        self.debugger = debugger
        self.listener = debugger.GetListener()
        if not self.listener.IsValid():
            raise "Invalid listener"

        self.listener.StartListeningForEventClass(self.debugger,
                                             lldb.SBTarget.GetBroadcasterClassName(),
                                             lldb.SBTarget.eBroadcastBitBreakpointChanged
                                           #| lldb.SBTarget.eBroadcastBitModuleLoaded
                                           #| lldb.SBTarget.eBroadcastBitModuleUnloaded
                                           | lldb.SBTarget.eBroadcastBitWatchpointChanged
                                           #| lldb.SBTarget.eBroadcastBitSymbolLoaded
                                           )

        self.listener.StartListeningForEventClass(self.debugger,
                                             lldb.SBThread.GetBroadcasterClassName(),
                                             lldb.SBThread.eBroadcastBitStackChanged
                                           #  lldb.SBThread.eBroadcastBitBreakpointChanged
                                           |  lldb.SBThread.eBroadcastBitThreadSuspended
                                           | lldb.SBThread.eBroadcastBitThreadResumed
                                           | lldb.SBThread.eBroadcastBitSelectedFrameChanged
                                           | lldb.SBThread.eBroadcastBitThreadSelected
                                           )

        self.listener.StartListeningForEventClass(self.debugger,
                                             lldb.SBProcess.GetBroadcasterClassName(),
                                             lldb.SBProcess.eBroadcastBitStateChanged
                                           | lldb.SBProcess.eBroadcastBitInterrupt
                                           | lldb.SBProcess.eBroadcastBitSTDOUT
                                           | lldb.SBProcess.eBroadcastBitSTDERR
                                           | lldb.SBProcess.eBroadcastBitProfileData
                                           )
        self.listener.StartListeningForEventClass(self.debugger,
                                             lldb.SBCommandInterpreter.GetBroadcasterClass(),
                                             lldb.SBCommandInterpreter.eBroadcastBitThreadShouldExit
                                           | lldb.SBCommandInterpreter.eBroadcastBitResetPrompt
                                           | lldb.SBCommandInterpreter.eBroadcastBitQuitCommandReceived
                                           | lldb.SBCommandInterpreter.eBroadcastBitAsynchronousOutputData
                                           | lldb.SBCommandInterpreter.eBroadcastBitAsynchronousErrorData
                                           )
    def createTarget(self, target_image, args=None):
        self.handleCommand("target create %s" % target_image)
        if args is not None:
          self.handleCommand("settings set target.run-args %s" % args)

    def attachProcess(self, pid):
        self.handleCommand("process attach -p %d" % pid)
        pass

    def loadCore(self, corefile):
        self.handleCommand("target create -c %s" % corefile)
        pass

    def setDone(self):
        self.done = True

    def isDone(self):
        return self.done

    def getPrompt(self):
        return self.debugger.GetPrompt()

    def getCommandInterpreter(self):
        return self.debugger.GetCommandInterpreter()

    def getSourceManager(self):
        return self.debugger.GetSourceManager()

    def setSize(self, width, height):
        # FIXME: respect height
        self.debugger.SetTerminalWidth(width)

    def getTarget(self):
        return self.debugger.GetTargetAtIndex(0)

    def handleCommand(self, cmd):
        ret = lldb.SBCommandReturnObject()
        self.getCommandInterpreter().HandleCommand(cmd, ret)
        return ret

    def eventLoop(self):
        while not self.isDone():
            event = lldb.SBEvent()
            got_event = self.listener.WaitForEvent(lldb.UINT32_MAX, event)
            if got_event and not event.IsValid():
                self.winAddStr("Warning: Invalid or no event...")
                continue
            elif not event.GetBroadcaster().IsValid():
                continue

            self.event_queue.put(event)

    def run(self):
        self.eventLoop()

    def terminate(self):
        lldb.SBDebugger.Terminate()
        sys.exit(0)

def createDriver(debugger, event_queue):
    driver = DebuggerDriver(debugger, event_queue)
    #driver.start()
    # if pid specified:
    # - attach to pid
    # else if core file specified
    # - create target from corefile
    # else
    # - create target from file
    # - settings append target.run-args <args-from-cmdline>
    # source .lldbinit file

    return driver
