//===-- ScriptInterpreterLua.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 "ScriptInterpreterLua.h"
#include "Lua.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Host/StreamFile.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StringList.h"
#include "lldb/Utility/Timer.h"
#include "lldb/lldb-forward.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/FormatAdapters.h"
#include <memory>
#include <vector>

using namespace lldb;
using namespace lldb_private;

LLDB_PLUGIN_DEFINE(ScriptInterpreterLua)

enum ActiveIOHandler {
  eIOHandlerNone,
  eIOHandlerBreakpoint,
  eIOHandlerWatchpoint
};

class IOHandlerLuaInterpreter : public IOHandlerDelegate,
                                public IOHandlerEditline {
public:
  IOHandlerLuaInterpreter(Debugger &debugger,
                          ScriptInterpreterLua &script_interpreter,
                          ActiveIOHandler active_io_handler = eIOHandlerNone)
      : IOHandlerEditline(debugger, IOHandler::Type::LuaInterpreter, "lua",
                          llvm::StringRef(">>> "), llvm::StringRef("..> "),
                          true, debugger.GetUseColor(), 0, *this),
        m_script_interpreter(script_interpreter),
        m_active_io_handler(active_io_handler) {
    llvm::cantFail(m_script_interpreter.GetLua().ChangeIO(
        debugger.GetOutputFileSP()->GetStream(),
        debugger.GetErrorFileSP()->GetStream()));
    llvm::cantFail(m_script_interpreter.EnterSession(debugger.GetID()));
  }

  ~IOHandlerLuaInterpreter() override {
    llvm::cantFail(m_script_interpreter.LeaveSession());
  }

  void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
    const char *instructions = nullptr;
    switch (m_active_io_handler) {
    case eIOHandlerNone:
      break;
    case eIOHandlerWatchpoint:
      instructions = "Enter your Lua command(s). Type 'quit' to end.\n"
                     "The commands are compiled as the body of the following "
                     "Lua function\n"
                     "function (frame, wp) end\n";
      SetPrompt(llvm::StringRef("..> "));
      break;
    case eIOHandlerBreakpoint:
      instructions = "Enter your Lua command(s). Type 'quit' to end.\n"
                     "The commands are compiled as the body of the following "
                     "Lua function\n"
                     "function (frame, bp_loc, ...) end\n";
      SetPrompt(llvm::StringRef("..> "));
      break;
    }
    if (instructions == nullptr)
      return;
    if (interactive) {
      if (lldb::LockableStreamFileSP output_sp =
              io_handler.GetOutputStreamFileSP()) {
        LockedStreamFile locked_stream = output_sp->Lock();
        locked_stream << instructions;
      }
    }
  }

  bool IOHandlerIsInputComplete(IOHandler &io_handler,
                                StringList &lines) override {
    size_t last = lines.GetSize() - 1;
    if (IsQuitCommand(lines.GetStringAtIndex(last))) {
      if (m_active_io_handler == eIOHandlerBreakpoint ||
          m_active_io_handler == eIOHandlerWatchpoint)
        lines.DeleteStringAtIndex(last);
      return true;
    }
    StreamString str;
    lines.Join("\n", str);
    if (llvm::Error E =
            m_script_interpreter.GetLua().CheckSyntax(str.GetString())) {
      std::string error_str = toString(std::move(E));
      // Lua always errors out to incomplete code with '<eof>'
      return error_str.find("<eof>") == std::string::npos;
    }
    // The breakpoint and watchpoint handler only exits with a explicit 'quit'
    return m_active_io_handler != eIOHandlerBreakpoint &&
           m_active_io_handler != eIOHandlerWatchpoint;
  }

  void IOHandlerInputComplete(IOHandler &io_handler,
                              std::string &data) override {
    switch (m_active_io_handler) {
    case eIOHandlerBreakpoint: {
      auto *bp_options_vec =
          static_cast<std::vector<std::reference_wrapper<BreakpointOptions>> *>(
              io_handler.GetUserData());
      for (BreakpointOptions &bp_options : *bp_options_vec) {
        Status error = m_script_interpreter.SetBreakpointCommandCallback(
            bp_options, data.c_str(), /*is_callback=*/false);
        if (error.Fail()) {
          LockedStreamFile locked_stream =
              io_handler.GetErrorStreamFileSP()->Lock();
          locked_stream << error.AsCString() << '\n';
        }
      }
      io_handler.SetIsDone(true);
    } break;
    case eIOHandlerWatchpoint: {
      auto *wp_options =
          static_cast<WatchpointOptions *>(io_handler.GetUserData());
      m_script_interpreter.SetWatchpointCommandCallback(wp_options,
                                                        data.c_str(),
                                                        /*is_callback=*/false);
      io_handler.SetIsDone(true);
    } break;
    case eIOHandlerNone:
      if (IsQuitCommand(data)) {
        io_handler.SetIsDone(true);
        return;
      }
      if (llvm::Error error = m_script_interpreter.GetLua().Run(data)) {
        LockedStreamFile locked_stream =
            io_handler.GetErrorStreamFileSP()->Lock();
        locked_stream << toString(std::move(error));
      }
      break;
    }
  }

private:
  ScriptInterpreterLua &m_script_interpreter;
  ActiveIOHandler m_active_io_handler;

  bool IsQuitCommand(llvm::StringRef cmd) { return cmd.rtrim() == "quit"; }
};

ScriptInterpreterLua::ScriptInterpreterLua(Debugger &debugger)
    : ScriptInterpreter(debugger, eScriptLanguageLua),
      m_lua(std::make_unique<Lua>()) {}

ScriptInterpreterLua::~ScriptInterpreterLua() = default;

StructuredData::DictionarySP ScriptInterpreterLua::GetInterpreterInfo() {
  auto info = std::make_shared<StructuredData::Dictionary>();
  info->AddStringItem("language", "lua");
  return info;
}

bool ScriptInterpreterLua::ExecuteOneLine(llvm::StringRef command,
                                          CommandReturnObject *result,
                                          const ExecuteScriptOptions &options) {
  if (command.empty()) {
    if (result)
      result->AppendError("empty command passed to lua\n");
    return false;
  }

  llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
      io_redirect_or_error = ScriptInterpreterIORedirect::Create(
          options.GetEnableIO(), m_debugger, result);
  if (!io_redirect_or_error) {
    if (result)
      result->AppendErrorWithFormatv(
          "failed to redirect I/O: {0}\n",
          llvm::fmt_consume(io_redirect_or_error.takeError()));
    else
      llvm::consumeError(io_redirect_or_error.takeError());
    return false;
  }

  ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;

  if (llvm::Error e =
          m_lua->ChangeIO(io_redirect.GetOutputFile()->GetStream(),
                          io_redirect.GetErrorFile()->GetStream())) {
    result->AppendErrorWithFormatv("lua failed to redirect I/O: {0}\n",
                                   llvm::toString(std::move(e)));
    return false;
  }

  if (llvm::Error e = m_lua->Run(command)) {
    result->AppendErrorWithFormatv(
        "lua failed attempting to evaluate '{0}': {1}\n", command,
        llvm::toString(std::move(e)));
    return false;
  }

  io_redirect.Flush();
  return true;
}

void ScriptInterpreterLua::ExecuteInterpreterLoop() {
  LLDB_SCOPED_TIMER();

  // At the moment, the only time the debugger does not have an input file
  // handle is when this is called directly from lua, in which case it is
  // both dangerous and unnecessary (not to mention confusing) to try to embed
  // a running interpreter loop inside the already running lua interpreter
  // loop, so we won't do it.
  if (!m_debugger.GetInputFile().IsValid())
    return;

  IOHandlerSP io_handler_sp(new IOHandlerLuaInterpreter(m_debugger, *this));
  m_debugger.RunIOHandlerAsync(io_handler_sp);
}

bool ScriptInterpreterLua::LoadScriptingModule(
    const char *filename, const LoadScriptOptions &options,
    lldb_private::Status &error, StructuredData::ObjectSP *module_sp,
    FileSpec extra_search_dir, lldb::TargetSP loaded_into_target_sp) {

  if (llvm::Error e = m_lua->LoadModule(filename)) {
    error = Status::FromErrorStringWithFormatv(
        "lua failed to import '{0}': {1}\n", filename,
        llvm::toString(std::move(e)));
    return false;
  }
  return true;
}

void ScriptInterpreterLua::Initialize() {
  static llvm::once_flag g_once_flag;

  llvm::call_once(g_once_flag, []() {
    PluginManager::RegisterPlugin(GetPluginNameStatic(),
                                  GetPluginDescriptionStatic(),
                                  lldb::eScriptLanguageLua, CreateInstance);
  });
}

void ScriptInterpreterLua::Terminate() {}

llvm::Error ScriptInterpreterLua::EnterSession(user_id_t debugger_id) {
  if (m_session_is_active)
    return llvm::Error::success();

  const char *fmt_str =
      "lldb.debugger = lldb.SBDebugger.FindDebuggerWithID({0}); "
      "lldb.target = lldb.debugger:GetSelectedTarget(); "
      "lldb.process = lldb.target:GetProcess(); "
      "lldb.thread = lldb.process:GetSelectedThread(); "
      "lldb.frame = lldb.thread:GetSelectedFrame()";
  return m_lua->Run(llvm::formatv(fmt_str, debugger_id).str());
}

llvm::Error ScriptInterpreterLua::LeaveSession() {
  if (!m_session_is_active)
    return llvm::Error::success();

  m_session_is_active = false;

  llvm::StringRef str = "lldb.debugger = nil; "
                        "lldb.target = nil; "
                        "lldb.process = nil; "
                        "lldb.thread = nil; "
                        "lldb.frame = nil";
  return m_lua->Run(str);
}

bool ScriptInterpreterLua::BreakpointCallbackFunction(
    void *baton, StoppointCallbackContext *context, user_id_t break_id,
    user_id_t break_loc_id) {
  assert(context);

  ExecutionContext exe_ctx(context->exe_ctx_ref);
  Target *target = exe_ctx.GetTargetPtr();
  if (target == nullptr)
    return true;

  StackFrameSP stop_frame_sp(exe_ctx.GetFrameSP());
  BreakpointSP breakpoint_sp = target->GetBreakpointByID(break_id);
  BreakpointLocationSP bp_loc_sp(breakpoint_sp->FindLocationByID(break_loc_id));

  Debugger &debugger = target->GetDebugger();
  ScriptInterpreterLua *lua_interpreter = static_cast<ScriptInterpreterLua *>(
      debugger.GetScriptInterpreter(true, eScriptLanguageLua));
  Lua &lua = lua_interpreter->GetLua();

  CommandDataLua *bp_option_data = static_cast<CommandDataLua *>(baton);
  llvm::Expected<bool> BoolOrErr = lua.CallBreakpointCallback(
      baton, stop_frame_sp, bp_loc_sp, bp_option_data->m_extra_args_sp);
  if (llvm::Error E = BoolOrErr.takeError()) {
    *debugger.GetAsyncErrorStream() << toString(std::move(E));
    return true;
  }

  return *BoolOrErr;
}

bool ScriptInterpreterLua::WatchpointCallbackFunction(
    void *baton, StoppointCallbackContext *context, user_id_t watch_id) {
  assert(context);

  ExecutionContext exe_ctx(context->exe_ctx_ref);
  Target *target = exe_ctx.GetTargetPtr();
  if (target == nullptr)
    return true;

  StackFrameSP stop_frame_sp(exe_ctx.GetFrameSP());
  WatchpointSP wp_sp = target->GetWatchpointList().FindByID(watch_id);

  Debugger &debugger = target->GetDebugger();
  ScriptInterpreterLua *lua_interpreter = static_cast<ScriptInterpreterLua *>(
      debugger.GetScriptInterpreter(true, eScriptLanguageLua));
  Lua &lua = lua_interpreter->GetLua();

  llvm::Expected<bool> BoolOrErr =
      lua.CallWatchpointCallback(baton, stop_frame_sp, wp_sp);
  if (llvm::Error E = BoolOrErr.takeError()) {
    *debugger.GetAsyncErrorStream() << toString(std::move(E));
    return true;
  }

  return *BoolOrErr;
}

void ScriptInterpreterLua::CollectDataForBreakpointCommandCallback(
    std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
    CommandReturnObject &result) {
  IOHandlerSP io_handler_sp(
      new IOHandlerLuaInterpreter(m_debugger, *this, eIOHandlerBreakpoint));
  io_handler_sp->SetUserData(&bp_options_vec);
  m_debugger.RunIOHandlerAsync(io_handler_sp);
}

void ScriptInterpreterLua::CollectDataForWatchpointCommandCallback(
    WatchpointOptions *wp_options, CommandReturnObject &result) {
  IOHandlerSP io_handler_sp(
      new IOHandlerLuaInterpreter(m_debugger, *this, eIOHandlerWatchpoint));
  io_handler_sp->SetUserData(wp_options);
  m_debugger.RunIOHandlerAsync(io_handler_sp);
}

Status ScriptInterpreterLua::SetBreakpointCommandCallbackFunction(
    BreakpointOptions &bp_options, const char *function_name,
    StructuredData::ObjectSP extra_args_sp) {
  const char *fmt_str = "return {0}(frame, bp_loc, ...)";
  std::string oneliner = llvm::formatv(fmt_str, function_name).str();
  return RegisterBreakpointCallback(bp_options, oneliner.c_str(),
                                    extra_args_sp);
}

Status ScriptInterpreterLua::SetBreakpointCommandCallback(
    BreakpointOptions &bp_options, const char *command_body_text,
    bool is_callback) {
  return RegisterBreakpointCallback(bp_options, command_body_text, {});
}

Status ScriptInterpreterLua::RegisterBreakpointCallback(
    BreakpointOptions &bp_options, const char *command_body_text,
    StructuredData::ObjectSP extra_args_sp) {
  auto data_up = std::make_unique<CommandDataLua>(extra_args_sp);
  llvm::Error err =
      m_lua->RegisterBreakpointCallback(data_up.get(), command_body_text);
  if (err)
    return Status::FromError(std::move(err));
  auto baton_sp =
      std::make_shared<BreakpointOptions::CommandBaton>(std::move(data_up));
  bp_options.SetCallback(ScriptInterpreterLua::BreakpointCallbackFunction,
                         baton_sp);
  return {};
}

void ScriptInterpreterLua::SetWatchpointCommandCallback(
    WatchpointOptions *wp_options, const char *command_body_text,
    bool is_callback) {
  RegisterWatchpointCallback(wp_options, command_body_text, {});
}

Status ScriptInterpreterLua::RegisterWatchpointCallback(
    WatchpointOptions *wp_options, const char *command_body_text,
    StructuredData::ObjectSP extra_args_sp) {
  auto data_up = std::make_unique<WatchpointOptions::CommandData>();
  llvm::Error err =
      m_lua->RegisterWatchpointCallback(data_up.get(), command_body_text);
  if (err)
    return Status::FromError(std::move(err));
  auto baton_sp =
      std::make_shared<WatchpointOptions::CommandBaton>(std::move(data_up));
  wp_options->SetCallback(ScriptInterpreterLua::WatchpointCallbackFunction,
                          baton_sp);
  return {};
}

lldb::ScriptInterpreterSP
ScriptInterpreterLua::CreateInstance(Debugger &debugger) {
  return std::make_shared<ScriptInterpreterLua>(debugger);
}

llvm::StringRef ScriptInterpreterLua::GetPluginDescriptionStatic() {
  return "Lua script interpreter";
}

Lua &ScriptInterpreterLua::GetLua() { return *m_lua; }
