//===-- 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 "LuaState.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.GetLuaState().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.GetLuaState().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.GetLuaState().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_state(std::make_unique<LuaState>()) {}

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_state->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_state->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_state->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() {
  PluginManager::RegisterPlugin(GetPluginNameStatic(),
                                GetPluginDescriptionStatic(),
                                lldb::eScriptLanguageLua, CreateInstance);
}

void ScriptInterpreterLua::Terminate() {
  PluginManager::UnregisterPlugin(CreateInstance);
}

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_state->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_state->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));
  LuaState &lua_state = lua_interpreter->GetLuaState();

  CommandDataLua *bp_option_data = static_cast<CommandDataLua *>(baton);
  llvm::Expected<bool> BoolOrErr = lua_state.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));
  LuaState &lua_state = lua_interpreter->GetLuaState();

  llvm::Expected<bool> BoolOrErr =
      lua_state.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_state->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_state->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";
}

LuaState &ScriptInterpreterLua::GetLuaState() { return *m_lua_state; }
