//===-- CommandObjectLog.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 "CommandObjectLog.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandOptionArgumentTable.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionValueEnumeration.h"
#include "lldb/Interpreter/OptionValueUInt64.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/Timer.h"

using namespace lldb;
using namespace lldb_private;

#define LLDB_OPTIONS_log_enable
#include "CommandOptions.inc"

#define LLDB_OPTIONS_log_dump
#include "CommandOptions.inc"

/// Common completion logic for log enable/disable.
static void CompleteEnableDisable(CompletionRequest &request) {
  size_t arg_index = request.GetCursorIndex();
  if (arg_index == 0) { // We got: log enable/disable x[tab]
    for (llvm::StringRef channel : Log::ListChannels())
      request.TryCompleteCurrentArg(channel);
  } else if (arg_index >= 1) { // We got: log enable/disable channel x[tab]
    llvm::StringRef channel = request.GetParsedLine().GetArgumentAtIndex(0);
    Log::ForEachChannelCategory(
        channel, [&request](llvm::StringRef name, llvm::StringRef desc) {
          request.TryCompleteCurrentArg(name, desc);
        });
  }
}

class CommandObjectLogEnable : public CommandObjectParsed {
public:
  // Constructors and Destructors
  CommandObjectLogEnable(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "log enable",
                            "Enable logging for a single log channel.",
                            nullptr) {
    CommandArgumentEntry arg1;
    CommandArgumentEntry arg2;
    CommandArgumentData channel_arg;
    CommandArgumentData category_arg;

    // Define the first (and only) variant of this arg.
    channel_arg.arg_type = eArgTypeLogChannel;
    channel_arg.arg_repetition = eArgRepeatPlain;

    // There is only one variant this argument could be; put it into the
    // argument entry.
    arg1.push_back(channel_arg);

    category_arg.arg_type = eArgTypeLogCategory;
    category_arg.arg_repetition = eArgRepeatPlus;

    arg2.push_back(category_arg);

    // Push the data for the first argument into the m_arguments vector.
    m_arguments.push_back(arg1);
    m_arguments.push_back(arg2);
  }

  ~CommandObjectLogEnable() 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 'f':
        log_file.SetFile(option_arg, FileSpec::Style::native);
        FileSystem::Instance().Resolve(log_file);
        break;
      case 'h':
        handler = (LogHandlerKind)OptionArgParser::ToOptionEnum(
            option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
        if (!error.Success())
          return Status::FromErrorStringWithFormatv(
              "unrecognized value for log handler '{0}'", option_arg);
        break;
      case 'b':
        return buffer_size.SetValueFromString(option_arg,
                                              eVarSetOperationAssign);
      case 'v':
        log_options |= LLDB_LOG_OPTION_VERBOSE;
        break;
      case 's':
        log_options |= LLDB_LOG_OPTION_PREPEND_SEQUENCE;
        break;
      case 'T':
        log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP;
        break;
      case 'p':
        log_options |= LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD;
        break;
      case 'n':
        log_options |= LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
        break;
      case 'S':
        log_options |= LLDB_LOG_OPTION_BACKTRACE;
        break;
      case 'a':
        log_options |= LLDB_LOG_OPTION_APPEND;
        break;
      case 'F':
        log_options |= LLDB_LOG_OPTION_PREPEND_FILE_FUNCTION;
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      log_file.Clear();
      buffer_size.Clear();
      handler = eLogHandlerStream;
      log_options = 0;
    }

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

    FileSpec log_file;
    OptionValueUInt64 buffer_size;
    LogHandlerKind handler = eLogHandlerStream;
    uint32_t log_options = 0;
  };

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    CompleteEnableDisable(request);
  }

protected:
  void DoExecute(Args &args, CommandReturnObject &result) override {
    if (args.GetArgumentCount() < 2) {
      result.AppendErrorWithFormat(
          "%s takes a log channel and one or more log types.\n",
          m_cmd_name.c_str());
      return;
    }

    if (m_options.handler == eLogHandlerCircular &&
        m_options.buffer_size.GetCurrentValue() == 0) {
      result.AppendError(
          "the circular buffer handler requires a non-zero buffer size.\n");
      return;
    }

    if ((m_options.handler != eLogHandlerCircular &&
         m_options.handler != eLogHandlerStream) &&
        m_options.buffer_size.GetCurrentValue() != 0) {
      result.AppendError("a buffer size can only be specified for the circular "
                         "and stream buffer handler.\n");
      return;
    }

    if (m_options.handler != eLogHandlerStream && m_options.log_file) {
      result.AppendError(
          "a file name can only be specified for the stream handler.\n");
      return;
    }

    // Store into a std::string since we're about to shift the channel off.
    const std::string channel = std::string(args[0].ref());
    args.Shift(); // Shift off the channel
    char log_file[PATH_MAX];
    if (m_options.log_file)
      m_options.log_file.GetPath(log_file, sizeof(log_file));
    else
      log_file[0] = '\0';

    std::string error;
    llvm::raw_string_ostream error_stream(error);
    bool success = GetDebugger().EnableLog(
        channel, args.GetArgumentArrayRef(), log_file, m_options.log_options,
        m_options.buffer_size.GetCurrentValue(), m_options.handler,
        error_stream);
    result.GetErrorStream() << error;

    if (success)
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
    else
      result.SetStatus(eReturnStatusFailed);
  }

  CommandOptions m_options;
};

class CommandObjectLogDisable : public CommandObjectParsed {
public:
  // Constructors and Destructors
  CommandObjectLogDisable(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "log disable",
                            "Disable one or more log channel categories.",
                            nullptr) {
    CommandArgumentEntry arg1;
    CommandArgumentEntry arg2;
    CommandArgumentData channel_arg;
    CommandArgumentData category_arg;

    // Define the first (and only) variant of this arg.
    channel_arg.arg_type = eArgTypeLogChannel;
    channel_arg.arg_repetition = eArgRepeatPlain;

    // There is only one variant this argument could be; put it into the
    // argument entry.
    arg1.push_back(channel_arg);

    category_arg.arg_type = eArgTypeLogCategory;
    category_arg.arg_repetition = eArgRepeatPlus;

    arg2.push_back(category_arg);

    // Push the data for the first argument into the m_arguments vector.
    m_arguments.push_back(arg1);
    m_arguments.push_back(arg2);
  }

  ~CommandObjectLogDisable() override = default;

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    CompleteEnableDisable(request);
  }

protected:
  void DoExecute(Args &args, CommandReturnObject &result) override {
    if (args.empty()) {
      result.AppendErrorWithFormat(
          "%s takes a log channel and one or more log types.\n",
          m_cmd_name.c_str());
      return;
    }

    const std::string channel = std::string(args[0].ref());
    args.Shift(); // Shift off the channel
    if (channel == "all") {
      Log::DisableAllLogChannels();
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
    } else {
      std::string error;
      llvm::raw_string_ostream error_stream(error);
      if (Log::DisableLogChannel(channel, args.GetArgumentArrayRef(),
                                 error_stream))
        result.SetStatus(eReturnStatusSuccessFinishNoResult);
      result.GetErrorStream() << error;
    }
  }
};

class CommandObjectLogList : public CommandObjectParsed {
public:
  // Constructors and Destructors
  CommandObjectLogList(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "log list",
                            "List the log categories for one or more log "
                            "channels.  If none specified, lists them all.",
                            nullptr) {
    AddSimpleArgumentList(eArgTypeLogChannel, eArgRepeatStar);
  }

  ~CommandObjectLogList() override = default;

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    for (llvm::StringRef channel : Log::ListChannels())
      request.TryCompleteCurrentArg(channel);
  }

protected:
  void DoExecute(Args &args, CommandReturnObject &result) override {
    std::string output;
    llvm::raw_string_ostream output_stream(output);
    if (args.empty()) {
      Log::ListAllLogChannels(output_stream);
      result.SetStatus(eReturnStatusSuccessFinishResult);
    } else {
      bool success = true;
      for (const auto &entry : args.entries())
        success =
            success && Log::ListChannelCategories(entry.ref(), output_stream);
      if (success)
        result.SetStatus(eReturnStatusSuccessFinishResult);
    }
    result.GetOutputStream() << output;
  }
};
class CommandObjectLogDump : public CommandObjectParsed {
public:
  CommandObjectLogDump(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "log dump",
                            "dump circular buffer logs", nullptr) {
    AddSimpleArgumentList(eArgTypeLogChannel);
  }

  ~CommandObjectLogDump() 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 'f':
        log_file.SetFile(option_arg, FileSpec::Style::native);
        FileSystem::Instance().Resolve(log_file);
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      log_file.Clear();
    }

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

    FileSpec log_file;
  };

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    CompleteEnableDisable(request);
  }

protected:
  void DoExecute(Args &args, CommandReturnObject &result) override {
    if (args.empty()) {
      result.AppendErrorWithFormat(
          "%s takes a log channel and one or more log types.\n",
          m_cmd_name.c_str());
      return;
    }

    std::unique_ptr<llvm::raw_ostream> stream_up;
    if (m_options.log_file) {
      const File::OpenOptions flags = File::eOpenOptionWriteOnly |
                                      File::eOpenOptionCanCreate |
                                      File::eOpenOptionTruncate;
      llvm::Expected<FileUP> file = FileSystem::Instance().Open(
          m_options.log_file, flags, lldb::eFilePermissionsFileDefault, false);
      if (!file) {
        result.AppendErrorWithFormat("Unable to open log file '%s': %s",
                                     m_options.log_file.GetPath().c_str(),
                                     llvm::toString(file.takeError()).c_str());
        return;
      }
      stream_up = std::make_unique<llvm::raw_fd_ostream>(
          (*file)->GetDescriptor(), /*shouldClose=*/true);
    } else {
      stream_up = std::make_unique<llvm::raw_fd_ostream>(
          GetDebugger().GetOutputFileSP()->GetDescriptor(),
          /*shouldClose=*/false);
    }

    const std::string channel = std::string(args[0].ref());
    std::string error;
    llvm::raw_string_ostream error_stream(error);
    if (Log::DumpLogChannel(channel, *stream_up, error_stream)) {
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
    } else {
      result.SetStatus(eReturnStatusFailed);
      result.GetErrorStream() << error;
    }
  }

  CommandOptions m_options;
};

class CommandObjectLogTimerEnable : public CommandObjectParsed {
public:
  // Constructors and Destructors
  CommandObjectLogTimerEnable(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "log timers enable",
                            "enable LLDB internal performance timers",
                            "log timers enable <depth>") {
    AddSimpleArgumentList(eArgTypeCount, eArgRepeatOptional);
  }

  ~CommandObjectLogTimerEnable() override = default;

protected:
  void DoExecute(Args &args, CommandReturnObject &result) override {
    result.SetStatus(eReturnStatusFailed);

    if (args.GetArgumentCount() == 0) {
      Timer::SetDisplayDepth(UINT32_MAX);
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
    } else if (args.GetArgumentCount() == 1) {
      uint32_t depth;
      if (args[0].ref().consumeInteger(0, depth)) {
        result.AppendError(
            "Could not convert enable depth to an unsigned integer.");
      } else {
        Timer::SetDisplayDepth(depth);
        result.SetStatus(eReturnStatusSuccessFinishNoResult);
      }
    }

    if (!result.Succeeded()) {
      result.AppendError("Missing subcommand");
      result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
    }
  }
};

class CommandObjectLogTimerDisable : public CommandObjectParsed {
public:
  // Constructors and Destructors
  CommandObjectLogTimerDisable(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "log timers disable",
                            "disable LLDB internal performance timers",
                            nullptr) {}

  ~CommandObjectLogTimerDisable() override = default;

protected:
  void DoExecute(Args &args, CommandReturnObject &result) override {
    Timer::DumpCategoryTimes(result.GetOutputStream());
    Timer::SetDisplayDepth(0);
    result.SetStatus(eReturnStatusSuccessFinishResult);

    if (!result.Succeeded()) {
      result.AppendError("Missing subcommand");
      result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
    }
  }
};

class CommandObjectLogTimerDump : public CommandObjectParsed {
public:
  // Constructors and Destructors
  CommandObjectLogTimerDump(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "log timers dump",
                            "dump LLDB internal performance timers", nullptr) {}

  ~CommandObjectLogTimerDump() override = default;

protected:
  void DoExecute(Args &args, CommandReturnObject &result) override {
    Timer::DumpCategoryTimes(result.GetOutputStream());
    result.SetStatus(eReturnStatusSuccessFinishResult);

    if (!result.Succeeded()) {
      result.AppendError("Missing subcommand");
      result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
    }
  }
};

class CommandObjectLogTimerReset : public CommandObjectParsed {
public:
  // Constructors and Destructors
  CommandObjectLogTimerReset(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "log timers reset",
                            "reset LLDB internal performance timers", nullptr) {
  }

  ~CommandObjectLogTimerReset() override = default;

protected:
  void DoExecute(Args &args, CommandReturnObject &result) override {
    Timer::ResetCategoryTimes();
    result.SetStatus(eReturnStatusSuccessFinishResult);

    if (!result.Succeeded()) {
      result.AppendError("Missing subcommand");
      result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
    }
  }
};

class CommandObjectLogTimerIncrement : public CommandObjectParsed {
public:
  // Constructors and Destructors
  CommandObjectLogTimerIncrement(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "log timers increment",
                            "increment LLDB internal performance timers",
                            "log timers increment <bool>") {
    AddSimpleArgumentList(eArgTypeBoolean);
  }

  ~CommandObjectLogTimerIncrement() override = default;

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    request.TryCompleteCurrentArg("true");
    request.TryCompleteCurrentArg("false");
  }

protected:
  void DoExecute(Args &args, CommandReturnObject &result) override {
    result.SetStatus(eReturnStatusFailed);

    if (args.GetArgumentCount() == 1) {
      bool success;
      bool increment =
          OptionArgParser::ToBoolean(args[0].ref(), false, &success);

      if (success) {
        Timer::SetQuiet(!increment);
        result.SetStatus(eReturnStatusSuccessFinishNoResult);
      } else
        result.AppendError("Could not convert increment value to boolean.");
    }

    if (!result.Succeeded()) {
      result.AppendError("Missing subcommand");
      result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
    }
  }
};

class CommandObjectLogTimer : public CommandObjectMultiword {
public:
  CommandObjectLogTimer(CommandInterpreter &interpreter)
      : CommandObjectMultiword(interpreter, "log timers",
                               "Enable, disable, dump, and reset LLDB internal "
                               "performance timers.",
                               "log timers < enable <depth> | disable | dump | "
                               "increment <bool> | reset >") {
    LoadSubCommand("enable", CommandObjectSP(
                                 new CommandObjectLogTimerEnable(interpreter)));
    LoadSubCommand("disable", CommandObjectSP(new CommandObjectLogTimerDisable(
                                  interpreter)));
    LoadSubCommand("dump",
                   CommandObjectSP(new CommandObjectLogTimerDump(interpreter)));
    LoadSubCommand(
        "reset", CommandObjectSP(new CommandObjectLogTimerReset(interpreter)));
    LoadSubCommand(
        "increment",
        CommandObjectSP(new CommandObjectLogTimerIncrement(interpreter)));
  }

  ~CommandObjectLogTimer() override = default;
};

CommandObjectLog::CommandObjectLog(CommandInterpreter &interpreter)
    : CommandObjectMultiword(interpreter, "log",
                             "Commands controlling LLDB internal logging.",
                             "log <subcommand> [<command-options>]") {
  LoadSubCommand("enable",
                 CommandObjectSP(new CommandObjectLogEnable(interpreter)));
  LoadSubCommand("disable",
                 CommandObjectSP(new CommandObjectLogDisable(interpreter)));
  LoadSubCommand("list",
                 CommandObjectSP(new CommandObjectLogList(interpreter)));
  LoadSubCommand("dump",
                 CommandObjectSP(new CommandObjectLogDump(interpreter)));
  LoadSubCommand("timers",
                 CommandObjectSP(new CommandObjectLogTimer(interpreter)));
}

CommandObjectLog::~CommandObjectLog() = default;
