//===-- 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"

#include "llvm/Support/FormatAdapters.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;
      case 'j':
        log_options |= LLDB_LOG_OPTION_JSON;
        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",
          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';

    llvm::Error error = GetDebugger().EnableLog(
        channel, args.GetArgumentArrayRef(), log_file, m_options.log_options,
        m_options.buffer_size.GetCurrentValue(), m_options.handler);

    if (error) {
      result.GetErrorStream()
          << llvm::formatv("{}", llvm::fmt_consume(std::move(error)));
      result.SetStatus(eReturnStatusFailed);
    } else
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
  }

  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",
          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 {
      if (llvm::Error err =
              Log::DisableLogChannel(channel, args.GetArgumentArrayRef()))
        result.AppendError(toString(std::move(err)));
      else
        result.SetStatus(eReturnStatusSuccessFinishNoResult);
    }
  }
};

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()) {
        auto err_or_list = Log::ListChannelCategories(entry.ref());
        if (!err_or_list) {
          success = false;
          output_stream << toString(err_or_list.takeError());
        } else
          output_stream << *err_or_list;
      }
      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",
          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", 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", 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", 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", 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", 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;
