from __future__ import annotations

import lldb
from jb_declarative_formatters.type_viz_generated_method import GeneratedMethodDefinition
from jb_debugger_logging import LOG_MESSAGE_SEPARATOR
from renderers.jb_lldb_logging_manager import RENDER_LOG


class LLDBTopLevelLazyDeclarations:
    _LOG = RENDER_LOG.getChild("lazy declarations")

    @classmethod
    def is_supported(cls):
        return hasattr(lldb.SBDebugger, "AddTopLevelLazyDeclaration")

    @classmethod
    def declare_lazy_declaration(cls, debugger: lldb.SBDebugger, lazy_declaration: GeneratedMethodDefinition):
        decl_context = ""
        if lazy_declaration.declaration_context is not None:
            decl_context = lazy_declaration.declaration_context.get_full_name_with_wildcards()

        if not hasattr(debugger, "AddTopLevelLazyDeclaration"):
            cls._LOG.warning("Cannot add declaration for method '%s::%s': LLDB does not support lazy declarations",
                             decl_context, lazy_declaration.declaration_name)
            return

        cls._LOG.debug("Adding declaration for '%s::%s':\n%s\n%s",
                       decl_context, lazy_declaration.declaration_name, lazy_declaration.definition_template, LOG_MESSAGE_SEPARATOR)

        error: lldb.SBError = debugger.AddTopLevelLazyDeclaration(decl_context, lazy_declaration.declaration_name,
                                                                  lazy_declaration.definition_template, lldb.eLanguageTypeC_plus_plus_14)
        if not error.Success():
            cls._LOG.error("Cannot add declaration for method '%s::%s': %s",
                           decl_context, lazy_declaration.declaration_name, error.description)

    @classmethod
    def remove_all_top_level_lazy_declarations(cls, debugger: lldb.SBDebugger):
        if not hasattr(debugger, "RemoveAllTopLevelLazyDeclarations"):
            return

        cls._LOG.debug("Removing all declarations")
        debugger.RemoveAllTopLevelLazyDeclarations()
