# Copyright 2022-2023 Free Software Foundation, Inc.

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import gdb

from .frames import frame_for_id
from .startup import in_gdb_thread
from .server import request
from .varref import BaseReference


# Map DAP frame IDs to scopes.  This ensures that scopes are re-used.
frame_to_scope = {}


# When the inferior is re-started, we erase all scope references.  See
# the section "Lifetime of Objects References" in the spec.
@in_gdb_thread
def clear_scopes(event):
    global frame_to_scope
    frame_to_scope = {}


gdb.events.cont.connect(clear_scopes)


# A helper function to compute the value of a symbol.  SYM is either a
# gdb.Symbol, or an object implementing the SymValueWrapper interface.
# FRAME is a frame wrapper, as produced by a frame filter.  Returns a
# tuple of the form (NAME, VALUE), where NAME is the symbol's name and
# VALUE is a gdb.Value.
@in_gdb_thread
def symbol_value(sym, frame):
    inf_frame = frame.inferior_frame()
    # Make sure to select the frame first.  Ideally this would not
    # be needed, but this is a way to set the current language
    # properly so that language-dependent APIs will work.
    inf_frame.select()
    name = str(sym.symbol())
    val = sym.value()
    if val is None:
        # No synthetic value, so must read the symbol value
        # ourselves.
        val = sym.symbol().value(inf_frame)
    elif not isinstance(val, gdb.Value):
        val = gdb.Value(val)
    return (name, val)


class _ScopeReference(BaseReference):
    def __init__(self, name, hint, frame, var_list):
        super().__init__(name)
        self.hint = hint
        self.frame = frame
        self.inf_frame = frame.inferior_frame()
        self.func = frame.function()
        self.line = frame.line()
        # VAR_LIST might be any kind of iterator, but it's convenient
        # here if it is just a collection.
        self.var_list = tuple(var_list)

    def to_object(self):
        result = super().to_object()
        result["presentationHint"] = self.hint
        # How would we know?
        result["expensive"] = False
        result["namedVariables"] = len(self.var_list)
        if self.line is not None:
            result["line"] = self.line
            # FIXME construct a Source object
        return result

    def has_children(self):
        return True

    def child_count(self):
        return len(self.var_list)

    @in_gdb_thread
    def fetch_one_child(self, idx):
        return symbol_value(self.var_list[idx], self.frame)


class _RegisterReference(_ScopeReference):
    def __init__(self, name, frame):
        super().__init__(
            name, "registers", frame, frame.inferior_frame().architecture().registers()
        )

    @in_gdb_thread
    def fetch_one_child(self, idx):
        return (
            self.var_list[idx].name,
            self.inf_frame.read_register(self.var_list[idx]),
        )


@request("scopes")
def scopes(*, frameId: int, **extra):
    global frame_to_scope
    if frameId in frame_to_scope:
        scopes = frame_to_scope[frameId]
    else:
        frame = frame_for_id(frameId)
        scopes = []
        # Make sure to handle the None case as well as the empty
        # iterator case.
        args = tuple(frame.frame_args() or ())
        if args:
            scopes.append(_ScopeReference("Arguments", "arguments", frame, args))
        # Make sure to handle the None case as well as the empty
        # iterator case.
        locs = tuple(frame.frame_locals() or ())
        if locs:
            scopes.append(_ScopeReference("Locals", "locals", frame, locs))
        scopes.append(_RegisterReference("Registers", frame))
        frame_to_scope[frameId] = scopes
    return {"scopes": [x.to_object() for x in scopes]}
