//===-- 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"

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();
    m_error = Status::FromError(obj_or_err.takeError());
    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);
}
