//===-- BreakpointResolverScripted.cpp ------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Breakpoint/BreakpointResolverScripted.h"


#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"
#include "llvm/Support/FormatVariadic.h"

using namespace lldb;
using namespace lldb_private;

// BreakpointResolverScripted:
BreakpointResolverScripted::BreakpointResolverScripted(
    const BreakpointSP &bkpt, const llvm::StringRef class_name,
    lldb::SearchDepth depth, const StructuredDataImpl &args_data)
    : BreakpointResolver(bkpt, BreakpointResolver::PythonResolver),
      m_class_name(std::string(class_name)), m_depth(depth), m_args(args_data) {
  if (bkpt)
    CreateImplementationIfNeeded(bkpt);
}

void BreakpointResolverScripted::CreateImplementationIfNeeded(
    BreakpointSP breakpoint_sp) {
  // This version has to be called with a valid breakpoint_sp
  // But the interface might have been made before we sent the breakpoint to
  // the interface.  If so, do that here:
  assert(breakpoint_sp);
  if (m_interface_sp) {
    if (!m_breakpoint_sent) {
      m_interface_sp->SetBreakpoint(breakpoint_sp);
      m_breakpoint_sent = true;
    }
    return;
  }

  if (m_class_name.empty())
    return;

  if (!breakpoint_sp)
    return;

  TargetSP target_sp = breakpoint_sp->GetTargetSP();
  if (target_sp)
    CreateImplementationIfNeeded(*target_sp.get(), breakpoint_sp);
}

void BreakpointResolverScripted::CreateImplementationIfNeeded(
    Target &target, BreakpointSP breakpoint_sp) {
  if (m_interface_sp) {
    if (!m_breakpoint_sent && breakpoint_sp) {
      m_interface_sp->SetBreakpoint(breakpoint_sp);
      m_breakpoint_sent = true;
    }
    return;
  }

  ScriptInterpreter *script_interp =
      target.GetDebugger().GetScriptInterpreter();
  if (!script_interp)
    return;

  if (!m_interface_sp)
    m_interface_sp = script_interp->CreateScriptedBreakpointInterface();

  if (!m_interface_sp) {
    m_error = Status::FromErrorStringWithFormat(
        "BreakpointResolverScripted::%s () - ERROR: %s", __FUNCTION__,
        "Script interpreter couldn't create Scripted Breakpoint Interface");
    return;
  }

  StructuredData::ObjectSP args_obj = m_args.GetObjectSP();
  StructuredData::DictionarySP args_dict_sp;
  if (args_obj && args_obj->GetType() == lldb::eStructuredDataTypeDictionary)
    args_dict_sp =
        std::static_pointer_cast<StructuredData::Dictionary>(args_obj);
  ScriptedMetadata scripted_metadata(m_class_name, args_dict_sp);
  auto obj_or_err =
      m_interface_sp->CreatePluginObject(scripted_metadata, breakpoint_sp);
  if (!obj_or_err) {
    m_interface_sp.reset();
    std::string msg = llvm::toString(obj_or_err.takeError());
    Debugger::ReportError(
        llvm::formatv("failed to create BreakpointResolverScripted: {0}", msg)
            .str(),
        target.GetDebugger().GetID());
    m_error = Status(msg);
    return;
  }
  StructuredData::ObjectSP object_sp = *obj_or_err;
  if (!object_sp || !object_sp->IsValid()) {
    m_error = Status::FromErrorStringWithFormat(
        "ScriptedBreakpoint::%s () - ERROR: %s", __FUNCTION__,
        "Failed to create valid script object");
  }
  if (breakpoint_sp)
    m_breakpoint_sent = true;
}

bool BreakpointResolverScripted::OverridesResolver(
    Target &target, BreakpointResolverSP original_sp) {
  // At this point neither resolver has been assigned a breakpoint, so pass
  // in an empty one.
  CreateImplementationIfNeeded(target, {});
  if (!m_interface_sp)
    return false;

  StructuredData::ObjectSP serialized_sp =
      original_sp->SerializeToStructuredData();
  StructuredDataImpl impl(serialized_sp);
  return m_interface_sp->OverridesResolver(target, impl);
}

void BreakpointResolverScripted::NotifyBreakpointSet() {
  CreateImplementationIfNeeded(GetBreakpoint());
}

BreakpointResolverSP BreakpointResolverScripted::CreateFromStructuredData(
    const StructuredData::Dictionary &options_dict, Status &error) {
  llvm::StringRef class_name;
  bool success;

  success = options_dict.GetValueForKeyAsString(
      GetKey(OptionNames::PythonClassName), class_name);
  if (!success) {
    error =
        Status::FromErrorString("BRFL::CFSD: Couldn't find class name entry.");
    return nullptr;
  }
  // The Python function will actually provide the search depth, this is a
  // placeholder.
  lldb::SearchDepth depth = lldb::eSearchDepthTarget;

  StructuredDataImpl args_data_impl;
  StructuredData::Dictionary *args_dict = nullptr;
  if (options_dict.GetValueForKeyAsDictionary(GetKey(OptionNames::ScriptArgs),
                                              args_dict))
    args_data_impl.SetObjectSP(args_dict->shared_from_this());
  return std::make_shared<BreakpointResolverScripted>(nullptr, class_name,
                                                      depth, args_data_impl);
}

StructuredData::ObjectSP
BreakpointResolverScripted::SerializeToStructuredData() {
  StructuredData::DictionarySP options_dict_sp(
      new StructuredData::Dictionary());

  options_dict_sp->AddStringItem(GetKey(OptionNames::PythonClassName),
                                   m_class_name);
  if (m_args.IsValid())
    options_dict_sp->AddItem(GetKey(OptionNames::ScriptArgs),
                             m_args.GetObjectSP());

  return WrapOptionsDict(options_dict_sp);
}

ScriptInterpreter *BreakpointResolverScripted::GetScriptInterpreter() {
  return GetBreakpoint()->GetTarget().GetDebugger().GetScriptInterpreter();
}

Searcher::CallbackReturn BreakpointResolverScripted::SearchCallback(
    SearchFilter &filter, SymbolContext &context, Address *addr) {
  bool should_continue = true;
  if (!m_interface_sp)
    return Searcher::eCallbackReturnStop;

  should_continue = m_interface_sp->ResolverCallback(context);
  if (should_continue)
    return Searcher::eCallbackReturnContinue;

  return Searcher::eCallbackReturnStop;
}

lldb::SearchDepth
BreakpointResolverScripted::GetDepth() {
  lldb::SearchDepth depth = lldb::eSearchDepthModule;
  if (m_interface_sp)
    depth = m_interface_sp->GetDepth();

  return depth;
}

void BreakpointResolverScripted::GetDescription(Stream *s) {
  StructuredData::GenericSP generic_sp;
  std::optional<std::string> short_help;

  CreateImplementationIfNeeded(GetBreakpoint());

  if (m_interface_sp) {
    short_help = m_interface_sp->GetShortHelp();
  }
  if (short_help && !short_help->empty())
    s->PutCString(short_help->c_str());
  else
    s->Printf("python class = %s", m_class_name.c_str());
}

std::optional<std::string> BreakpointResolverScripted::GetLocationDescription(
    lldb::BreakpointLocationSP bp_loc_sp, lldb::DescriptionLevel level) {
  CreateImplementationIfNeeded(GetBreakpoint());
  if (m_interface_sp)
    return m_interface_sp->GetLocationDescription(bp_loc_sp, level);
  return {};
}

lldb::BreakpointLocationSP
BreakpointResolverScripted::WasHit(lldb::StackFrameSP frame_sp,
                                   lldb::BreakpointLocationSP bp_loc_sp) {
  if (m_interface_sp)
    return m_interface_sp->WasHit(frame_sp, bp_loc_sp);
  return {};
}

void BreakpointResolverScripted::Dump(Stream *s) const {}

lldb::BreakpointResolverSP
BreakpointResolverScripted::CopyForBreakpoint(BreakpointSP &breakpoint) {
  return std::make_shared<BreakpointResolverScripted>(breakpoint, m_class_name,
                                                      m_depth, m_args);
}
