//===-- CommandObjectMultiword.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/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/Options.h"
#include <optional>

using namespace lldb;
using namespace lldb_private;

// CommandObjectMultiword

CommandObjectMultiword::CommandObjectMultiword(CommandInterpreter &interpreter,
                                               const char *name,
                                               const char *help,
                                               const char *syntax,
                                               uint32_t flags)
    : CommandObject(interpreter, name, help, syntax, flags),
      m_can_be_removed(false) {}

CommandObjectMultiword::~CommandObjectMultiword() = default;

CommandObjectSP
CommandObjectMultiword::GetSubcommandSPExact(llvm::StringRef sub_cmd) {
  if (m_subcommand_dict.empty())
    return {};

  auto pos = m_subcommand_dict.find(sub_cmd);
  if (pos == m_subcommand_dict.end())
    return {};

  return pos->second;
}

CommandObjectSP CommandObjectMultiword::GetSubcommandSP(llvm::StringRef sub_cmd,
                                                        StringList *matches) {
  if (m_subcommand_dict.empty())
    return {};

  CommandObjectSP return_cmd_sp = GetSubcommandSPExact(sub_cmd);
  if (return_cmd_sp) {
    if (matches)
      matches->AppendString(sub_cmd);
    return return_cmd_sp;
  }

  CommandObject::CommandMap::iterator pos;

  StringList local_matches;
  if (matches == nullptr)
    matches = &local_matches;
  int num_matches =
      AddNamesMatchingPartialString(m_subcommand_dict, sub_cmd, *matches);

  if (num_matches == 1) {
    // Cleaner, but slightly less efficient would be to call back into this
    // function, since I now know I have an exact match...

    sub_cmd = matches->GetStringAtIndex(0);
    pos = m_subcommand_dict.find(sub_cmd);
    if (pos != m_subcommand_dict.end())
      return_cmd_sp = pos->second;
  }

  return return_cmd_sp;
}

CommandObject *
CommandObjectMultiword::GetSubcommandObject(llvm::StringRef sub_cmd,
                                            StringList *matches) {
  return GetSubcommandSP(sub_cmd, matches).get();
}

bool CommandObjectMultiword::LoadSubCommand(llvm::StringRef name,
                                            const CommandObjectSP &cmd_obj_sp) {
  if (cmd_obj_sp)
    lldbassert((&GetCommandInterpreter() == &cmd_obj_sp->GetCommandInterpreter()) &&
           "tried to add a CommandObject from a different interpreter");

  return m_subcommand_dict.try_emplace(std::string(name), cmd_obj_sp).second;
}

llvm::Error CommandObjectMultiword::LoadUserSubcommand(
    llvm::StringRef name, const CommandObjectSP &cmd_obj_sp, bool can_replace) {
  Status result;
  if (cmd_obj_sp)
    lldbassert((&GetCommandInterpreter() == &cmd_obj_sp->GetCommandInterpreter()) &&
           "tried to add a CommandObject from a different interpreter");
  if (!IsUserCommand()) {
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
                              "can't add a user subcommand to a builtin container command.");
  }
  // Make sure this a user command if it isn't already:
  cmd_obj_sp->SetIsUserCommand(true);

  std::string str_name(name);

  auto [pos, inserted] = m_subcommand_dict.try_emplace(str_name, cmd_obj_sp);
  if (inserted)
    return llvm::Error::success();

  const char *error_str = nullptr;
  if (!can_replace)
    error_str = "sub-command already exists";
  if (!(*pos).second->IsUserCommand())
    error_str = "can't replace a builtin subcommand";

  if (error_str) {
    return llvm::createStringError(llvm::inconvertibleErrorCode(), error_str);
  }
  pos->second = cmd_obj_sp;
  return llvm::Error::success();
}

llvm::Error CommandObjectMultiword::RemoveUserSubcommand(llvm::StringRef cmd_name,
                                                    bool must_be_multiword) {
  CommandMap::iterator pos;
  std::string str_name(cmd_name);

  pos = m_subcommand_dict.find(str_name);
  if (pos == m_subcommand_dict.end()) {
    return llvm::createStringError(llvm::inconvertibleErrorCode(),"subcommand '%s' not found.",
                                   str_name.c_str());
  }
  if (!(*pos).second->IsUserCommand()) {
    return llvm::createStringError(llvm::inconvertibleErrorCode(),"subcommand '%s' not a user command.",
                                   str_name.c_str());
  }

  if (must_be_multiword && !(*pos).second->IsMultiwordObject()) {
    return llvm::createStringError(llvm::inconvertibleErrorCode(),"subcommand '%s' is not a container command",
                                   str_name.c_str());
  }
  if (!must_be_multiword && (*pos).second->IsMultiwordObject()) {
    return llvm::createStringError(llvm::inconvertibleErrorCode(),"subcommand '%s' is not a user command",
                                   str_name.c_str());
  }

  m_subcommand_dict.erase(pos);

  return llvm::Error::success();
}

void CommandObjectMultiword::Execute(const char *args_string,
                                     CommandReturnObject &result) {
  Args args(args_string);
  const size_t argc = args.GetArgumentCount();
  if (argc == 0) {
    this->CommandObject::GenerateHelpText(result);
    return;
  }

  auto sub_command = args[0].ref();
  if (sub_command.empty()) {
    result.AppendError("need to specify a non-empty subcommand");
    return;
  }

  if (m_subcommand_dict.empty()) {
    result.AppendErrorWithFormat("'%s' does not have any subcommands.\n",
                                 GetCommandName().str().c_str());
    return;
  }

  StringList matches;
  CommandObject *sub_cmd_obj = GetSubcommandObject(sub_command, &matches);
  if (sub_cmd_obj != nullptr) {
    // Now call CommandObject::Execute to process options in `rest_of_line`.
    // From there the command-specific version of Execute will be called, with
    // the processed arguments.

    args.Shift();
    sub_cmd_obj->Execute(args_string, result);
    return;
  }

  std::string error_msg;
  const size_t num_subcmd_matches = matches.GetSize();
  if (num_subcmd_matches > 0) {
    error_msg.assign("ambiguous command ");
    error_msg.append("'");
    error_msg.append(std::string(GetCommandName()));
    error_msg.append(" ");
    error_msg.append(std::string(sub_command));
    error_msg.append("'.");

    error_msg.append(" Possible completions:");
    for (const std::string &match : matches) {
      error_msg.append("\n\t");
      error_msg.append(match);
    }
  } else {
    // Try to offer some alternatives to help correct the command.
    error_msg.assign(
        llvm::Twine("\"" + sub_command + "\" is not a valid subcommand of \"" +
                    GetCommandName() + "\"." + GetSubcommandsHintText() +
                    " Use \"help " + GetCommandName() + "\" to find out more.")
            .str());
  }
  result.AppendError(error_msg);
}

std::string CommandObjectMultiword::GetSubcommandsHintText() {
  if (m_subcommand_dict.empty())
    return "";
  const size_t maxCount = 5;
  size_t i = 0;
  std::string buffer = " Valid subcommand";
  buffer.append(m_subcommand_dict.size() > 1 ? "s are:" : " is");
  CommandMap::iterator pos;
  for (pos = m_subcommand_dict.begin();
       pos != m_subcommand_dict.end() && i < maxCount; ++pos, ++i) {
    buffer.append(" ");
    buffer.append(pos->first);
    buffer.append(",");
  }
  if (i < m_subcommand_dict.size())
    buffer.append(" and others");
  else
    buffer.pop_back();

  buffer.append(".");
  return buffer;
}

void CommandObjectMultiword::GenerateHelpText(Stream &output_stream) {
  // First time through here, generate the help text for the object and push it
  // to the return result object as well

  CommandObject::GenerateHelpText(output_stream);
  output_stream.PutCString("\nThe following subcommands are supported:\n\n");

  CommandMap::iterator pos;
  uint32_t max_len = FindLongestCommandWord(m_subcommand_dict);

  if (max_len)
    max_len += 4; // Indent the output by 4 spaces.

  for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos) {
    std::string indented_command("    ");
    indented_command.append(pos->first);
    if (pos->second->WantsRawCommandString()) {
      std::string help_text(std::string(pos->second->GetHelp()));
      help_text.append("  Expects 'raw' input (see 'help raw-input'.)");
      m_interpreter.OutputFormattedHelpText(output_stream, indented_command,
                                            "--", help_text, max_len);
    } else
      m_interpreter.OutputFormattedHelpText(output_stream, indented_command,
                                            "--", pos->second->GetHelp(),
                                            max_len);
  }

  output_stream.PutCString("\nFor more help on any particular subcommand, type "
                           "'help <command> <subcommand>'.\n");
}

void CommandObjectMultiword::HandleCompletion(CompletionRequest &request) {
  auto arg0 = request.GetParsedLine()[0].ref();
  if (request.GetCursorIndex() == 0) {
    StringList new_matches, descriptions;
    AddNamesMatchingPartialString(m_subcommand_dict, arg0, new_matches,
                                  &descriptions);
    request.AddCompletions(new_matches, descriptions);

    if (new_matches.GetSize() == 1 &&
        new_matches.GetStringAtIndex(0) != nullptr &&
        (arg0 == new_matches.GetStringAtIndex(0))) {
      StringList temp_matches;
      CommandObject *cmd_obj = GetSubcommandObject(arg0, &temp_matches);
      if (cmd_obj != nullptr) {
        if (request.GetParsedLine().GetArgumentCount() != 1) {
          request.GetParsedLine().Shift();
          request.AppendEmptyArgument();
          cmd_obj->HandleCompletion(request);
        }
      }
    }
    return;
  }

  StringList new_matches;
  CommandObject *sub_command_object = GetSubcommandObject(arg0, &new_matches);

  // The subcommand is ambiguous. The completion isn't meaningful.
  if (!sub_command_object)
    return;

  // Remove the one match that we got from calling GetSubcommandObject.
  new_matches.DeleteStringAtIndex(0);
  request.AddCompletions(new_matches);
  request.ShiftArguments();
  sub_command_object->HandleCompletion(request);
}

std::optional<std::string>
CommandObjectMultiword::GetRepeatCommand(Args &current_command_args,
                                         uint32_t index) {
  index++;
  if (current_command_args.GetArgumentCount() <= index)
    return std::nullopt;
  CommandObject *sub_command_object =
      GetSubcommandObject(current_command_args[index].ref());
  if (sub_command_object == nullptr)
    return std::nullopt;
  return sub_command_object->GetRepeatCommand(current_command_args, index);
}

CommandObjectProxy::CommandObjectProxy(CommandInterpreter &interpreter,
                                       const char *name, const char *help,
                                       const char *syntax, uint32_t flags)
    : CommandObject(interpreter, name, help, syntax, flags) {}

CommandObjectProxy::~CommandObjectProxy() = default;

Options *CommandObjectProxy::GetOptions() {
  CommandObject *proxy_command = GetProxyCommandObject();
  if (proxy_command)
    return proxy_command->GetOptions();
  return CommandObject::GetOptions();
}

llvm::StringRef CommandObjectProxy::GetHelp() {
  CommandObject *proxy_command = GetProxyCommandObject();
  if (proxy_command)
    return proxy_command->GetHelp();
  return CommandObject::GetHelp();
}

llvm::StringRef CommandObjectProxy::GetSyntax() {
  CommandObject *proxy_command = GetProxyCommandObject();
  if (proxy_command)
    return proxy_command->GetSyntax();
  return CommandObject::GetSyntax();
}

llvm::StringRef CommandObjectProxy::GetHelpLong() {
  CommandObject *proxy_command = GetProxyCommandObject();
  if (proxy_command)
    return proxy_command->GetHelpLong();
  return CommandObject::GetHelpLong();
}

bool CommandObjectProxy::IsRemovable() const {
  const CommandObject *proxy_command =
      const_cast<CommandObjectProxy *>(this)->GetProxyCommandObject();
  if (proxy_command)
    return proxy_command->IsRemovable();
  return false;
}

bool CommandObjectProxy::IsMultiwordObject() {
  CommandObject *proxy_command = GetProxyCommandObject();
  if (proxy_command)
    return proxy_command->IsMultiwordObject();
  return false;
}

CommandObjectMultiword *CommandObjectProxy::GetAsMultiwordCommand() {
  CommandObject *proxy_command = GetProxyCommandObject();
  if (proxy_command)
    return proxy_command->GetAsMultiwordCommand();
  return nullptr;
}

void CommandObjectProxy::GenerateHelpText(Stream &result) {
  CommandObject *proxy_command = GetProxyCommandObject();
  if (proxy_command)
    proxy_command->GenerateHelpText(result);
  else
    CommandObject::GenerateHelpText(result);
}

lldb::CommandObjectSP
CommandObjectProxy::GetSubcommandSP(llvm::StringRef sub_cmd,
                                    StringList *matches) {
  CommandObject *proxy_command = GetProxyCommandObject();
  if (proxy_command)
    return proxy_command->GetSubcommandSP(sub_cmd, matches);
  return lldb::CommandObjectSP();
}

CommandObject *CommandObjectProxy::GetSubcommandObject(llvm::StringRef sub_cmd,
                                                       StringList *matches) {
  CommandObject *proxy_command = GetProxyCommandObject();
  if (proxy_command)
    return proxy_command->GetSubcommandObject(sub_cmd, matches);
  return nullptr;
}

bool CommandObjectProxy::LoadSubCommand(
    llvm::StringRef cmd_name, const lldb::CommandObjectSP &command_sp) {
  CommandObject *proxy_command = GetProxyCommandObject();
  if (proxy_command)
    return proxy_command->LoadSubCommand(cmd_name, command_sp);
  return false;
}

bool CommandObjectProxy::WantsRawCommandString() {
  CommandObject *proxy_command = GetProxyCommandObject();
  if (proxy_command)
    return proxy_command->WantsRawCommandString();
  return false;
}

bool CommandObjectProxy::WantsCompletion() {
  CommandObject *proxy_command = GetProxyCommandObject();
  if (proxy_command)
    return proxy_command->WantsCompletion();
  return false;
}

void CommandObjectProxy::HandleCompletion(CompletionRequest &request) {
  CommandObject *proxy_command = GetProxyCommandObject();
  if (proxy_command)
    proxy_command->HandleCompletion(request);
}

void CommandObjectProxy::HandleArgumentCompletion(
    CompletionRequest &request, OptionElementVector &opt_element_vector) {
  CommandObject *proxy_command = GetProxyCommandObject();
  if (proxy_command)
    proxy_command->HandleArgumentCompletion(request, opt_element_vector);
}

std::optional<std::string>
CommandObjectProxy::GetRepeatCommand(Args &current_command_args,
                                     uint32_t index) {
  CommandObject *proxy_command = GetProxyCommandObject();
  if (proxy_command)
    return proxy_command->GetRepeatCommand(current_command_args, index);
  return std::nullopt;
}

llvm::StringRef CommandObjectProxy::GetUnsupportedError() {
  return "command is not implemented";
}

void CommandObjectProxy::Execute(const char *args_string,
                                 CommandReturnObject &result) {
  if (CommandObject *proxy_command = GetProxyCommandObject())
    proxy_command->Execute(args_string, result);
  else
    result.AppendError(GetUnsupportedError());
}
