#!/usr/bin/env python

# ---------------------------------------------------------------------
# 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__)
