//===-- CommandObjectScripting.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 "CommandObjectScripting.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandOptionArgumentTable.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/Interfaces/ScriptedInterfaceUsages.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Utility/AnsiTerminal.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"

#include "llvm/ADT/StringMap.h"

using namespace lldb;
using namespace lldb_private;

#define LLDB_OPTIONS_scripting_run
#include "CommandOptions.inc"

class CommandObjectScriptingRun : public CommandObjectRaw {
public:
  CommandObjectScriptingRun(CommandInterpreter &interpreter)
      : CommandObjectRaw(
            interpreter, "scripting run",
            "Invoke the script interpreter with provided code and display any "
            "results.  Start the interactive interpreter if no code is "
            "supplied.",
            "scripting run [--language <scripting-language> --] "
            "[<script-code>]") {}

  ~CommandObjectScriptingRun() override = default;

  Options *GetOptions() override { return &m_options; }

  class CommandOptions : public Options {
  public:
    CommandOptions() = default;
    ~CommandOptions() override = default;
    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'l':
        language = (lldb::ScriptLanguage)OptionArgParser::ToOptionEnum(
            option_arg, GetDefinitions()[option_idx].enum_values,
            eScriptLanguageNone, error);
        if (!error.Success())
          error = Status::FromErrorStringWithFormat(
              "unrecognized value for language '%s'", option_arg.str().c_str());
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      language = lldb::eScriptLanguageNone;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::ArrayRef(g_scripting_run_options);
    }

    lldb::ScriptLanguage language = lldb::eScriptLanguageNone;
  };

protected:
  void DoExecute(llvm::StringRef command,
                 CommandReturnObject &result) override {
    // Try parsing the language option but when the command contains a raw part
    // separated by the -- delimiter.
    OptionsWithRaw raw_args(command);
    if (raw_args.HasArgs()) {
      if (!ParseOptions(raw_args.GetArgs(), result))
        return;
      command = raw_args.GetRawPart();
    }

    lldb::ScriptLanguage language =
        (m_options.language == lldb::eScriptLanguageNone)
            ? m_interpreter.GetDebugger().GetScriptLanguage()
            : m_options.language;

    if (language == lldb::eScriptLanguageNone) {
      result.AppendError(
          "the script-lang setting is set to none - scripting not available");
      return;
    }

    ScriptInterpreter *script_interpreter =
        GetDebugger().GetScriptInterpreter(true, language);

    if (script_interpreter == nullptr) {
      result.AppendError("no script interpreter");
      return;
    }

    // Script might change Python code we use for formatting. Make sure we keep
    // up to date with it.
    DataVisualization::ForceUpdate();

    if (command.empty()) {
      script_interpreter->ExecuteInterpreterLoop();
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
      return;
    }

    // We can do better when reporting the status of one-liner script execution.
    if (script_interpreter->ExecuteOneLine(command, &result))
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
    else
      result.SetStatus(eReturnStatusFailed);
  }

private:
  CommandOptions m_options;
};

#define LLDB_OPTIONS_scripting_extension_list
#include "CommandOptions.inc"

class CommandObjectScriptingExtensionList : public CommandObjectParsed {
public:
  CommandObjectScriptingExtensionList(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "scripting extension list",
            "List the available scripting extension templates, or with "
            "--instances, the instantiated scripting extensions grouped by "
            "class.",
            "scripting extension list [--language <scripting-language>] "
            "[--json] [--instances] [<extension-name> ...]") {
    AddSimpleArgumentList(eArgTypeScriptedExtension, eArgRepeatStar);
  }

  ~CommandObjectScriptingExtensionList() override = default;

  Options *GetOptions() override { return &m_options; }

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
        GetCommandInterpreter(), lldb::eScriptedExtensionCompletion, request,
        nullptr);
  }

  class CommandOptions : public Options {
  public:
    CommandOptions() = default;
    ~CommandOptions() override = default;
    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'l':
        m_language = (lldb::ScriptLanguage)OptionArgParser::ToOptionEnum(
            option_arg, GetDefinitions()[option_idx].enum_values,
            eScriptLanguageNone, error);
        if (!error.Success())
          error = Status::FromErrorStringWithFormatv(
              "unrecognized value for language '{0}'", option_arg);
        break;
      case 'j':
        m_json_format = true;
        break;
      case 'i':
        m_instances = true;
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_language = lldb::eScriptLanguageDefault;
      m_json_format = false;
      m_instances = false;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::ArrayRef(g_scripting_extension_list_options);
    }

    lldb::ScriptLanguage m_language = lldb::eScriptLanguageDefault;
    bool m_json_format = false;
    bool m_instances = false;
  };

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    if (m_options.m_instances) {
      ListInstances(command, result);
      return;
    }

    llvm::StringMap<std::vector<size_t>> grouped_by_extension;
    for (size_t i = 0; i < PluginManager::GetNumScriptedInterfaces(); i++) {
      lldb::ScriptedExtension extension =
          PluginManager::GetScriptedInterfaceExtensionAtIndex(i);
      if (extension == eScriptedExtensionInvalid)
        continue;

      llvm::StringLiteral extension_name =
          ScriptInterpreter::ExtensionToString(extension);
      if (grouped_by_extension.contains(extension_name))
        grouped_by_extension[extension_name].push_back(i);
      else
        grouped_by_extension[extension_name] = {i};
    }

    if (command.GetArgumentCount() > 0) {
      llvm::StringMap<std::vector<size_t>> filtered;
      for (const Args::ArgEntry &arg : command.entries()) {
        lldb::ScriptedExtension extension =
            ScriptInterpreter::StringToExtension(arg.ref());
        if (extension == eScriptedExtensionInvalid) {
          result.AppendErrorWithFormat("no scripted extension named '%s'",
                                       arg.c_str());
          return;
        }
        llvm::StringLiteral extension_name =
            ScriptInterpreter::ExtensionToString(extension);
        auto it = grouped_by_extension.find(extension_name);
        if (it != grouped_by_extension.end())
          filtered[extension_name] = it->second;
      }
      grouped_by_extension = std::move(filtered);
    }

    if (m_options.m_json_format)
      OutputJsonFormat(grouped_by_extension, result);
    else
      OutputTextFormat(grouped_by_extension, result);
  }

private:
  static std::string GetSeparator(const Debugger &debugger, bool use_color) {
    return ansi::FormatAnsiTerminalCodes(debugger.GetDividerAnsiPrefix(),
                                         use_color) +
           std::string(std::min<uint64_t>(debugger.GetTerminalWidth(), 80),
                       '-') +
           ansi::FormatAnsiTerminalCodes(debugger.GetDividerAnsiSuffix(),
                                         use_color);
  }

  void ListInstances(Args &command, CommandReturnObject &result) {
    std::vector<lldb::ScriptedExtension> extensions;
    for (const Args::ArgEntry &arg : command.entries()) {
      lldb::ScriptedExtension extension =
          ScriptInterpreter::StringToExtension(arg.ref());
      if (extension == eScriptedExtensionInvalid) {
        result.AppendErrorWithFormat("no scripted extension named '%s'",
                                     arg.c_str());
        return;
      }
      extensions.push_back(extension);
    }

    std::vector<ScriptedInstanceGroup> groups;
    if (ScriptInterpreter *script_interpreter =
            GetDebugger().GetScriptInterpreter(/*can_create=*/false,
                                               m_options.m_language))
      groups =
          script_interpreter->GetScriptedInstanceRegistry()->GetInstanceGroups(
              extensions);

    if (m_options.m_json_format) {
      StructuredData::Array groups_array;
      for (const ScriptedInstanceGroup &group : groups)
        groups_array.AddItem(group.ToStructuredData());
      groups_array.Dump(result.GetOutputStream());
      result.GetOutputStream().EOL();
      result.SetStatus(eReturnStatusSuccessFinishResult);
      return;
    }

    Stream &s = result.GetOutputStream();
    const bool use_color = s.AsRawOstream().colors_enabled();
    const Debugger &debugger = GetDebugger();
    const std::string separator = GetSeparator(debugger, use_color);

    s.PutCString("Instantiated scripted extensions:");
    if (groups.empty())
      s << " None";
    s.EOL();
    for (const ScriptedInstanceGroup &group : groups) {
      s << separator << '\n';
      group.Dump(s, debugger, use_color);
    }
    result.SetStatus(eReturnStatusSuccessFinishResult);
  }

  std::vector<std::string>
  GetLanguagesForExtension(const std::vector<size_t> &indices) {
    std::vector<std::string> languages;
    for (const size_t idx : indices) {
      lldb::ScriptLanguage lang =
          PluginManager::GetScriptedInterfaceLanguageAtIndex(idx);
      if (lang != m_options.m_language)
        continue;
      languages.push_back(ScriptInterpreter::LanguageToString(lang));
    }
    return languages;
  }

  void OutputJsonFormat(
      const llvm::StringMap<std::vector<size_t>> &grouped_by_extension,
      CommandReturnObject &result) {
    llvm::json::Array extensions;
    for (const auto &extension_pair : grouped_by_extension) {
      // llvm::json::Value's StringRef constructor does not copy the
      // underlying characters, so every string handed to the JSON structure
      // below must be an owned std::string -- otherwise it dangles by the
      // time the object tree is serialized at the end of this function.
      llvm::json::Array languages;
      for (const std::string &lang :
           GetLanguagesForExtension(extension_pair.second))
        languages.push_back(lang);
      if (languages.empty())
        continue;

      llvm::StringRef desc =
          PluginManager::GetScriptedInterfaceDescriptionAtIndex(
              extension_pair.second[0]);
      ScriptedInterfaceUsages usages =
          PluginManager::GetScriptedInterfaceUsagesAtIndex(
              extension_pair.second[0]);

      llvm::json::Array api_usages;
      for (llvm::StringRef usage : usages.GetSBAPIUsages())
        api_usages.push_back(usage.str());

      llvm::json::Array cmd_usages;
      for (llvm::StringRef usage : usages.GetCommandInterpreterUsages())
        cmd_usages.push_back(usage.str());

      extensions.push_back(llvm::json::Object{
          {"name", extension_pair.first().str()},
          {"description", desc.str()},
          {"languages", std::move(languages)},
          {"api_usages", std::move(api_usages)},
          {"command_interpreter_usages", std::move(cmd_usages)},
      });
    }

    std::string str;
    llvm::raw_string_ostream os(str);
    os << llvm::formatv("{0:2}", llvm::json::Value(std::move(extensions)));
    result.AppendMessage(str);
    result.SetStatus(eReturnStatusSuccessFinishResult);
  }

  void OutputTextFormat(
      const llvm::StringMap<std::vector<size_t>> &grouped_by_extension,
      CommandReturnObject &result) {
    Stream &s = result.GetOutputStream();
    const bool use_color = s.AsRawOstream().colors_enabled();
    const Debugger &debugger = GetDebugger();
    auto ansi_code = [use_color](llvm::StringRef code) {
      return ansi::FormatAnsiTerminalCodes(code, use_color);
    };
    const std::string label_prefix = ansi_code(debugger.GetLabelAnsiPrefix());
    const std::string label_suffix = ansi_code(debugger.GetLabelAnsiSuffix());
    const std::string title_prefix = ansi_code(debugger.GetTitleAnsiPrefix());
    const std::string title_suffix = ansi_code(debugger.GetTitleAnsiSuffix());
    const std::string separator = GetSeparator(debugger, use_color);

    s.PutCString("Available scripted extension templates:");

    auto print_field = [&](llvm::StringRef key, llvm::StringRef value,
                           bool is_title = false) {
      if (value.empty())
        return;
      s.IndentMore();
      s.Indent();
      s << label_prefix << key << ": " << label_suffix;
      if (is_title)
        s << title_prefix << value << title_suffix;
      else
        s << value;
      s << '\n';
      s.IndentLess();
    };

    size_t num_listed_interface = 0;
    for (const auto &extension_pair : grouped_by_extension) {
      std::vector<std::string> languages =
          GetLanguagesForExtension(extension_pair.second);
      if (languages.empty())
        continue;
      num_listed_interface++;

      s.EOL();
      s << separator;
      s.EOL();

      llvm::StringRef desc =
          PluginManager::GetScriptedInterfaceDescriptionAtIndex(
              extension_pair.second[0]);
      ScriptedInterfaceUsages usages =
          PluginManager::GetScriptedInterfaceUsagesAtIndex(
              extension_pair.second[0]);

      print_field("Name", extension_pair.first(), /*is_title=*/true);
      print_field("Description", desc);
      print_field("Language", llvm::join(languages, ""));
      usages.Dump(s, ScriptedInterfaceUsages::UsageKind::API, use_color);
      usages.Dump(s, ScriptedInterfaceUsages::UsageKind::CommandInterpreter,
                  use_color);
    }

    if (!num_listed_interface)
      s << " None\n";

    result.SetStatus(eReturnStatusSuccessFinishResult);
  }

private:
  CommandOptions m_options;
};

#define LLDB_OPTIONS_scripting_extension_generate
#include "CommandOptions.inc"

class CommandObjectScriptingExtensionGenerate : public CommandObjectParsed {
public:
  CommandObjectScriptingExtensionGenerate(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "scripting extension generate",
                            "Generate a scripting extension template. ",
                            "scripting extension generate") {
    AddSimpleArgumentList(eArgTypeScriptedExtension, eArgRepeatPlus);
  }

  ~CommandObjectScriptingExtensionGenerate() override = default;

  Options *GetOptions() override { return &m_options; }

  class CommandOptions : public Options {
  public:
    CommandOptions() = default;
    ~CommandOptions() override = default;
    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const char short_option =
          g_scripting_extension_generate_options[option_idx].short_option;

      switch (short_option) {
      case 'a':
        m_generate_non_abstract_methods = true;
        break;
      case 'l':
        m_language = (lldb::ScriptLanguage)OptionArgParser::ToOptionEnum(
            option_arg, GetDefinitions()[option_idx].enum_values,
            eScriptLanguageNone, error);
        if (!error.Success())
          error = Status::FromErrorStringWithFormatv(
              "unrecognized value for language '{0}'", option_arg);
        break;
      case 'n':
        m_generated_class_prefix = option_arg.str();
        break;
      case 'o':
        m_output_filepath = option_arg.str();
        break;
      case 'e': {
        bool success;
        m_open_editor = OptionArgParser::ToBoolean(option_arg, true, &success)
                            ? eLazyBoolYes
                            : eLazyBoolNo;
        if (!success)
          error = Status::FromErrorStringWithFormatv(
              "invalid boolean value for -e: '{0}'", option_arg);
      } break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_generate_non_abstract_methods = false;
      m_language = lldb::eScriptLanguageNone;
      m_generated_class_prefix.clear();
      m_output_filepath.clear();
      m_open_editor = eLazyBoolCalculate;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::ArrayRef(g_scripting_extension_generate_options);
    }

    bool m_generate_non_abstract_methods = false;
    lldb::ScriptLanguage m_language = lldb::eScriptLanguageNone;
    std::string m_generated_class_prefix;
    std::string m_output_filepath;
    LazyBool m_open_editor = eLazyBoolCalculate;
  };

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    // If `-l <lang>` was already given, complete only extensions available
    // in that language. Bare `-l` (no value yet) and any parse failures
    // fall back to language-agnostic completion.
    lldb::ScriptLanguage language = lldb::eScriptLanguageUnknown;
    llvm::ArrayRef<OptionDefinition> defs = m_options.GetDefinitions();
    for (const OptionArgElement &elem : opt_element_vector) {
      if (elem.opt_defs_index < 0 ||
          static_cast<size_t>(elem.opt_defs_index) >= defs.size())
        continue;
      if (defs[elem.opt_defs_index].short_option != 'l' ||
          elem.opt_arg_pos <= 0)
        continue;
      llvm::StringRef value =
          request.GetParsedLine().GetArgumentAtIndex(elem.opt_arg_pos);
      Status error;
      auto candidate =
          static_cast<lldb::ScriptLanguage>(OptionArgParser::ToOptionEnum(
              value, defs[elem.opt_defs_index].enum_values,
              lldb::eScriptLanguageUnknown, error));
      if (error.Success())
        language = candidate;
      break;
    }
    PluginManager::AutoCompleteScriptedExtension(
        request.GetCursorArgumentPrefix(), request, language);
    lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
        GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr);
  }

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    if (command.GetArgumentCount() == 0) {
      result.SetError(
          Status::FromErrorString("specify extension name to generate"));
      return;
    }

    std::vector<ScriptInterpreter::ExtensionTemplateRequest> extension_requests;

    for (size_t i = 0; i < command.GetArgumentCount(); i++) {
      llvm::StringRef extension_name = command.GetArgumentAtIndex(i);
      llvm::SmallVector<llvm::StringRef> extension_components;
      extension_name.split(extension_components, ".");
      lldb::ScriptedExtension extension =
          ScriptInterpreter::StringToExtension(extension_components.back());
      if (extension == eScriptedExtensionInvalid) {
        result.SetError(Status::FromErrorStringWithFormatv(
            "unknown scripted extension: '{0}'", extension_name));
        return;
      }
      extension_requests.push_back({extension_name, extension_components});
    }

    lldb::ScriptLanguage language =
        (m_options.m_language == lldb::eScriptLanguageNone)
            ? m_interpreter.GetDebugger().GetScriptLanguage()
            : m_options.m_language;

    if (language == lldb::eScriptLanguageNone) {
      result.AppendError(
          "the script-lang setting is set to none - scripting not available");
      return;
    }

    ScriptInterpreter *script_interpreter =
        GetDebugger().GetScriptInterpreter(true, language);

    if (script_interpreter == nullptr) {
      result.AppendError("no script interpreter");
      return;
    }

    auto generated_file_or_err = script_interpreter->GenerateExtensionTemplate(
        m_options.m_generated_class_prefix, extension_requests,
        m_options.m_generate_non_abstract_methods, m_options.m_output_filepath);
    if (!generated_file_or_err) {
      result.SetError(generated_file_or_err.takeError());
      return;
    }

    bool should_open_editor = false;
    switch (m_options.m_open_editor) {
    case eLazyBoolYes:
      should_open_editor = true;
      break;
    case eLazyBoolNo:
      should_open_editor = false;
      break;
    case eLazyBoolCalculate:
      should_open_editor = result.GetInteractive();
      break;
    }

    if (should_open_editor) {
      if (llvm::Error err = Host::OpenFileInExternalEditor(
              "", *generated_file_or_err, 1, true)) {
        LLDB_LOG_ERROR(GetLog(LLDBLog::Host), std::move(err),
                       "OpenFileInExternalEditor failed: {0}");
      }
    }
    result.AppendMessageWithFormatv(
        "Generated scripting extension template: {0}",
        generated_file_or_err->GetPath());
    result.SetStatus(eReturnStatusSuccessFinishNoResult);
  }

private:
  CommandOptions m_options;
};

class CommandObjectMultiwordScriptingExtension : public CommandObjectMultiword {
public:
  CommandObjectMultiwordScriptingExtension(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "scripting extension",
            "Commands for operating on the scripting extensions.",
            "scripting extension [<subcommand-options>]") {
    LoadSubCommand(
        "list",
        CommandObjectSP(new CommandObjectScriptingExtensionList(interpreter)));
    LoadSubCommand("generate",
                   CommandObjectSP(new CommandObjectScriptingExtensionGenerate(
                       interpreter)));
  }

  ~CommandObjectMultiwordScriptingExtension() override = default;
};

CommandObjectMultiwordScripting::CommandObjectMultiwordScripting(
    CommandInterpreter &interpreter)
    : CommandObjectMultiword(
          interpreter, "scripting",
          "Commands for operating on the scripting functionalities.",
          "scripting <subcommand> [<subcommand-options>]") {
  LoadSubCommand("run",
                 CommandObjectSP(new CommandObjectScriptingRun(interpreter)));
  LoadSubCommand("extension",
                 CommandObjectSP(new CommandObjectMultiwordScriptingExtension(
                     interpreter)));
}

CommandObjectMultiwordScripting::~CommandObjectMultiwordScripting() = default;
