//===-- 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());
  }
  error_msg.append("\n");
  result.AppendRawError(error_msg.c_str());
}

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());
}
