from lldb import SBCommandReturnObject, SBDebugger, SBExecutionContext
from reveallldb.commands.argument_parser import RevealCommandArgumentParser
from reveallldb.reveal_loader import RevealLoader
import shlex

class RevealCommand:
    program = 'reveal'

    @classmethod
    def register_lldb_command(cls, debugger, module_name):
        parser = RevealCommandArgumentParser()
        cls.__doc__ = parser.format_help()
        command = 'command script add -c %s.%s %s' % (module_name, cls.__name__, cls.program)
        debugger.HandleCommand(command)
        
    @classmethod
    def create_options(cls):
        return RevealCommandArgumentParser()

    def get_short_help(self):
        return "Commands for loading and controlling Reveal Server in the current debugging session"

    def get_long_help(self):
        return self.help_string

    def __init__(self, debugger, unused):
        self.parser = self.create_options()
        self.help_string = self.parser.format_help()

    def __call__(self, debugger: SBDebugger, command, exe_ctx: SBExecutionContext, result: SBCommandReturnObject):
        parser = RevealCommandArgumentParser()
        command_args = shlex.split(command)

        try:
            args = parser.parse_args(command_args)
        except:
            parser.print_help()
            return

        frame = exe_ctx.process.GetThreadAtIndex(0).GetSelectedFrame()
        if not frame.IsValid():
            # We should probably show an error message here, but in reality this should never happen.
            result.SetError("The process is not in a valid state to run any of Reveal's commands. Please check that you've launched your app with LLDB.")
            return

        try:
            loader = RevealLoader(frame)
            args.func(loader, args, debugger, command, exe_ctx, result)
        except Exception as e:
            result.SetError(str(e))
