//===-- BreakpointResolverScripted.cpp ---------------------------*- C++ -*-===//
//
// 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(
    Breakpoint *bkpt, 
    const llvm::StringRef class_name,
    lldb::SearchDepth depth,
    StructuredDataImpl *args_data,
    ScriptInterpreter &script_interp)
    : BreakpointResolver(bkpt, BreakpointResolver::PythonResolver),
      m_class_name(class_name), m_depth(depth), m_args_ptr(args_data) {
  CreateImplementationIfNeeded();
}

void BreakpointResolverScripted::CreateImplementationIfNeeded() {
  if (m_implementation_sp)
    return;
  
  if (m_class_name.empty())
    return;
  
  if (m_breakpoint) {
    TargetSP target_sp = m_breakpoint->GetTargetSP();
    ScriptInterpreter *script_interp = target_sp->GetDebugger()
                                                .GetScriptInterpreter();
    if (!script_interp)
      return;
    lldb::BreakpointSP bkpt_sp(m_breakpoint->shared_from_this());
    m_implementation_sp = script_interp->CreateScriptedBreakpointResolver(
        m_class_name.c_str(), m_args_ptr, bkpt_sp);
  }
}

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

BreakpointResolverScripted::~BreakpointResolverScripted() {}

BreakpointResolver *
BreakpointResolverScripted::CreateFromStructuredData(
    Breakpoint *bkpt, const StructuredData::Dictionary &options_dict,
    Status &error) {
  llvm::StringRef class_name;
  bool success;
  
  if (!bkpt)
    return nullptr;

  success = options_dict.GetValueForKeyAsString(
      GetKey(OptionNames::PythonClassName), class_name);
  if (!success) {
    error.SetErrorString("BRFL::CFSD: Couldn't find class name entry.");
    return nullptr;
  }
  lldb::SearchDepth depth;
  int depth_as_int;
  success = options_dict.GetValueForKeyAsInteger(
      GetKey(OptionNames::SearchDepth), depth_as_int);
  if (!success) {
    error.SetErrorString("BRFL::CFSD: Couldn't find class name entry.");
    return nullptr;
  }
  if (depth_as_int >= (int) OptionNames::LastOptionName) {
    error.SetErrorString("BRFL::CFSD: Invalid value for search depth.");
    return nullptr;
  }
  depth = (lldb::SearchDepth) depth_as_int;
  
  StructuredDataImpl *args_data_impl = new StructuredDataImpl();
  StructuredData::Dictionary *args_dict = new StructuredData::Dictionary();
  success = options_dict.GetValueForKeyAsDictionary(
    GetKey(OptionNames::ScriptArgs), args_dict);
  if (success) {
    // FIXME: The resolver needs a copy of the ARGS dict that it can own,
    // so I need to make a copy constructor for the Dictionary so I can pass
    // that to it here.  For now the args are empty.
    //StructuredData::Dictionary *dict_copy = new StructuredData::Dictionary(args_dict);
    
  }
  ScriptInterpreter *script_interp = bkpt->GetTarget()
                                         .GetDebugger()
                                         .GetScriptInterpreter();
  return new BreakpointResolverScripted(bkpt, class_name, depth, args_data_impl,
                                      *script_interp);
}

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

  options_dict_sp->AddStringItem(GetKey(OptionNames::PythonClassName),
                                   m_class_name);
  return WrapOptionsDict(options_dict_sp);
}

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

Searcher::CallbackReturn
BreakpointResolverScripted::SearchCallback(SearchFilter &filter,
                                          SymbolContext &context, Address *addr,
                                          bool containing) {
  assert(m_breakpoint != nullptr);
  bool should_continue = true;
  if (!m_implementation_sp)
    return Searcher::eCallbackReturnStop;
  
  ScriptInterpreter *interp = GetScriptInterpreter();
  should_continue = interp->ScriptedBreakpointResolverSearchCallback(
      m_implementation_sp,
      &context);
  if (should_continue)
    return Searcher::eCallbackReturnContinue;
  else
    return Searcher::eCallbackReturnStop;
}

lldb::SearchDepth
BreakpointResolverScripted::GetDepth() {
  assert(m_breakpoint != nullptr);
  lldb::SearchDepth depth = lldb::eSearchDepthModule;
  if (m_implementation_sp) {
    ScriptInterpreter *interp = GetScriptInterpreter();
    depth = interp->ScriptedBreakpointResolverSearchDepth(
        m_implementation_sp);
  }
  return depth;
}

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

  if (m_implementation_sp) {
    ScriptInterpreter *interp = GetScriptInterpreter();
    interp->GetShortHelpForCommandObject(m_implementation_sp,
                                         short_help);
  }
  if (!short_help.empty())
    s->PutCString(short_help.c_str());
  else
    s->Printf("python class = %s", m_class_name.c_str());
}

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

lldb::BreakpointResolverSP
BreakpointResolverScripted::CopyForBreakpoint(Breakpoint &breakpoint) {
  ScriptInterpreter *script_interp = GetScriptInterpreter();
  // FIXME: Have to make a copy of the arguments from the m_args_ptr and then
  // pass that to the new resolver.
  lldb::BreakpointResolverSP ret_sp(
      new BreakpointResolverScripted(&breakpoint, m_class_name, 
                                   m_depth, nullptr, *script_interp));
  return ret_sp;
}
