#!/usr/bin/env python3

# ---------------------------------------------------------------------
# Be sure to add the python path that points to the LLDB shared library.
#
# # To use this in the embedded python interpreter using "lldb" just
# import it with the full path using the "command script import"
# command
#   (lldb) command script import /path/to/cmdtemplate.py
# ---------------------------------------------------------------------

import inspect
import lldb
import sys
from lldb.plugins.parsed_cmd import ParsedCommand

class FrameStatCommand(ParsedCommand):
    program = "framestats"

    @classmethod
    def register_lldb_command(cls, debugger, module_name):
        ParsedCommand.do_register_cmd(cls, debugger, module_name)
        print(
            'The "{0}" command has been installed, type "help {0}" or "{0} '
            '--help" for detailed help.'.format(cls.program)
        )

    def get_flags(self):
        return lldb.eCommandRequiresFrame | lldb.eCommandProcessMustBePaused

    def setup_command_definition(self):
        ov_parser = self.get_parser()
        ov_parser.add_option(
            "i",
            "in-scope",
            help = "in_scope_only = True",
            value_type = lldb.eArgTypeBoolean,
            dest = "bool_arg",
            default = True,
        )

        ov_parser.add_option(
            "i",
            "in-scope",
            help = "in_scope_only = True",
            value_type = lldb.eArgTypeBoolean,
            dest = "inscope",
            default=True,
        )
        
        ov_parser.add_option(
            "a",
            "arguments",
            help = "arguments = True",
            value_type = lldb.eArgTypeBoolean,
            dest = "arguments",
            default = True,
        )

        ov_parser.add_option(
            "l",
            "locals",
            help = "locals = True",
            value_type = lldb.eArgTypeBoolean,
            dest = "locals",
            default = True,
        )

        ov_parser.add_option(
            "s",
            "statics",
            help = "statics = True",
            value_type = lldb.eArgTypeBoolean,
            dest = "statics",
            default = True,
        )
        ov_parser.add_option(
            "t",
            "test-flag",
            help="test a flag value.",
        )

    def get_repeat_command(self, args):
        """As an example, make the command not auto-repeat:"""
        return ""

    def get_short_help(self):
        return "Example command for use in debugging"

    def get_long_help(self):
        return ("This command is meant to be an example of how to make "
            "an LLDB command that does something useful, follows "
            "best practices, and exploits the SB API. "
            "Specifically, this command computes the aggregate "
            "and average size of the variables in the current "
            "frame and allows you to tweak exactly which variables "
            "are to be accounted in the computation.")


    def __init__(self, debugger, unused):
        super().__init__(debugger, unused)

    def __call__(self, debugger, command, exe_ctx, result):
        # Always get program state from the lldb.SBExecutionContext passed
        # in as exe_ctx
        frame = exe_ctx.GetFrame()
        if not frame.IsValid():
            result.SetError("invalid frame")
            return

        ov_parser = self.get_parser()
        variables_list = frame.GetVariables(
            ov_parser.arguments, ov_parser.locals, ov_parser.statics, ov_parser.inscope
        )
        variables_count = variables_list.GetSize()
        if variables_count == 0:
            print("no variables here", file=result)
            return
        total_size = 0
        for i in range(0, variables_count):
            variable = variables_list.GetValueAtIndex(i)
            variable_type = variable.GetType()
            total_size = total_size + variable_type.GetByteSize()
            average_size = float(total_size) / variables_count
            print(
                "Your frame has %d variables. Their total size "
                "is %d bytes. The average size is %f bytes"
                % (variables_count, total_size, average_size),
                file=result,
            )
        if ov_parser.was_set("test-flag"):
            print("Got the test flag")
        else:
            print("Got no test flag")

        # not returning anything is akin to returning success


def __lldb_init_module(debugger, dict):
    # Register all classes that have a register_lldb_command method
    for _name, cls in inspect.getmembers(sys.modules[__name__]):
        if inspect.isclass(cls) and callable(
            getattr(cls, "register_lldb_command", None)
        ):
            cls.register_lldb_command(debugger, __name__)
