from abc import ABCMeta, abstractmethod

import lldb


class ScriptedFrameProvider(metaclass=ABCMeta):
    """
    The base class for a scripted frame provider.

    A scripted frame provider allows you to provide custom stack frames for a
    thread, which can be used to augment or replace the standard unwinding
    mechanism. This is useful for:

    - Providing frames for custom calling conventions or languages
    - Reconstructing missing frames from crash dumps or core files
    - Adding diagnostic or synthetic frames for debugging
    - Visualizing state machines or async execution contexts

    Most of the base class methods are `@abstractmethod` that need to be
    overwritten by the inheriting class.

    Example usage:

    .. code-block:: python

        # Attach a frame provider to a thread
        thread = process.GetSelectedThread()
        error = thread.SetScriptedFrameProvider(
                        "my_module.MyFrameProvider",
                        lldb.SBStructuredData()
        )
    """

    @staticmethod
    def applies_to_thread(thread):
        """Determine if this frame provider should be used for a given thread.

        This static method is called before creating an instance of the frame
        provider to determine if it should be applied to a specific thread.
        Override this method to provide custom filtering logic.

        Args:
            thread (lldb.SBThread): The thread to check.

        Returns:
            bool: True if this frame provider should be used for the thread,
                False otherwise. The default implementation returns True for
                all threads.

        Example:

        .. code-block:: python

            @staticmethod
            def applies_to_thread(thread):
                # Only apply to thread 1
                return thread.GetIndexID() == 1
        """
        return True

    @staticmethod
    @abstractmethod
    def get_description():
        """Get a description of this frame provider.

        This method should return a human-readable string describing what
        this frame provider does. The description is used for debugging
        and display purposes.

        Returns:
            str: A description of the frame provider.

        Example:

        .. code-block:: python

            def get_description(self):
                return "Crash log frame provider for thread 1"
        """
        pass

    @staticmethod
    def get_priority():
        """Get the priority of this frame provider.

        This static method is called to determine the evaluation order when
        multiple frame providers could apply to the same thread. Lower numbers
        indicate higher priority (like Unix nice values).

        Returns:
            int or None: Priority value where 0 is highest priority.
                Return None for default priority (UINT32_MAX - lowest priority).

        Example:

        .. code-block:: python

            @staticmethod
            def get_priority():
                # High priority - runs before most providers
                return 10

            @staticmethod
            def get_priority():
                # Default priority - runs last
                return None
        """
        return None  # Default/lowest priority

    def __init__(self, input_frames, args):
        """Construct a scripted frame provider.

        Args:
            input_frames (lldb.SBFrameList): The frame list to use as input.
                This allows you to access frames by index. The frames are
                materialized lazily as you access them.
            args (lldb.SBStructuredData): A Dictionary holding arbitrary
                key/value pairs used by the scripted frame provider.
        """
        self.input_frames = None
        self.args = None
        self.thread = None
        self.target = None
        self.process = None

        if isinstance(input_frames, lldb.SBFrameList) and input_frames.IsValid():
            self.input_frames = input_frames
            self.thread = input_frames.GetThread()
            if self.thread and self.thread.IsValid():
                self.process = self.thread.GetProcess()
                if self.process and self.process.IsValid():
                    self.target = self.process.GetTarget()

        if isinstance(args, lldb.SBStructuredData) and args.IsValid():
            self.args = args

    @abstractmethod
    def get_frame_at_index(self, index):
        """Get a single stack frame at the given index.

        This method is called lazily when a specific frame is needed in the
        thread's backtrace (e.g., via the 'bt' command). Each frame is
        requested individually as needed.

        Args:
            index (int): The frame index to retrieve (0 for youngest/top frame).

        Returns:
            Dict or None: A frame dictionary describing the stack frame, or None
                if no frame exists at this index. The dictionary should contain:

            Required fields:
            - idx (int): The synthetic frame index (0 for youngest/top frame)
            - pc (int): The program counter address for the synthetic frame

            Alternatively, you can return:
            - A ScriptedFrame object for full control over frame behavior
            - An integer representing an input frame index to reuse
            - None to indicate no more frames exist

        Example:

        .. code-block:: python

            def get_frame_at_index(self, index):
                # Return None when there are no more frames
                if index >= self.total_frames:
                    return None

                # Re-use an input frame by returning its index
                if self.should_use_input_frame(index):
                    return index  # Returns input frame at this index

                # Or create a custom frame dictionary
                if index == 0:
                    return {
                        "idx": 0,
                        "pc": 0x100001234,
                    }

                return None

        Note:
            The frames are indexed from 0 (youngest/top) to N (oldest/bottom).
            This method will be called repeatedly with increasing indices until
            None is returned.
        """
        pass
