//===-- 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())
          error.SetErrorStringWithFormat(
              "unrecognized value for log handler '%s'",
              option_arg.str().c_str());
        break;
      case 'b':
        error =
            buffer_size.SetValueFromString(option_arg, eVarSetOperationAssign);
        break;
      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::makeArrayRef(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:
  bool 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 false;
    }

    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 false;
    }

    // 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_stream.str();

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

  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:
  bool 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 false;
    }

    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_stream.str();
    }
    return result.Succeeded();
  }
};

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) {
    CommandArgumentEntry arg;
    CommandArgumentData channel_arg;

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

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

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

  ~CommandObjectLogList() override = default;

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

protected:
  bool 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_stream.str();
    return result.Succeeded();
  }
};
class CommandObjectLogDump : public CommandObjectParsed {
public:
  CommandObjectLogDump(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "log dump",
                            "dump circular buffer logs", nullptr) {
    CommandArgumentEntry arg1;
    CommandArgumentData channel_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);

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

  ~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::makeArrayRef(g_log_dump_options);
    }

    FileSpec log_file;
  };

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

protected:
  bool 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 false;
    }

    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.GetCString(),
                                     llvm::toString(file.takeError()).c_str());
        return false;
      }
      stream_up = std::make_unique<llvm::raw_fd_ostream>(
          (*file)->GetDescriptor(), /*shouldClose=*/true);
    } else {
      stream_up = std::make_unique<llvm::raw_fd_ostream>(
          GetDebugger().GetOutputFile().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_stream.str();
    }

    return result.Succeeded();
  }

  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>") {
    CommandArgumentEntry arg;
    CommandArgumentData depth_arg;

    // Define the first (and only) variant of this arg.
    depth_arg.arg_type = eArgTypeCount;
    depth_arg.arg_repetition = eArgRepeatOptional;

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

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

  ~CommandObjectLogTimerEnable() override = default;

protected:
  bool 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());
    }
    return result.Succeeded();
  }
};

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:
  bool 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());
    }
    return result.Succeeded();
  }
};

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:
  bool 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());
    }
    return result.Succeeded();
  }
};

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:
  bool 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());
    }
    return result.Succeeded();
  }
};

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>") {
    CommandArgumentEntry arg;
    CommandArgumentData bool_arg;

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

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

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

  ~CommandObjectLogTimerIncrement() override = default;

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

protected:
  bool 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());
    }
    return result.Succeeded();
  }
};

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;
