#include "CommandObjectSession.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandOptionArgumentTable.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionValue.h"
#include "lldb/Interpreter/OptionValueBoolean.h"
#include "lldb/Interpreter/OptionValueString.h"
#include "lldb/Interpreter/OptionValueUInt64.h"
#include "lldb/Interpreter/Options.h"

using namespace lldb;
using namespace lldb_private;

class CommandObjectSessionSave : public CommandObjectParsed {
public:
  CommandObjectSessionSave(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "session save",
                            "Save the current session transcripts to a file.\n"
                            "If no file if specified, transcripts will be "
                            "saved to a temporary file.\n"
                            "Note: transcripts will only be saved if "
                            "interpreter.save-transcript is true.\n",
                            "session save [file]") {
    AddSimpleArgumentList(eArgTypePath, eArgRepeatOptional);
  }

  ~CommandObjectSessionSave() override = default;

protected:
  void DoExecute(Args &args, CommandReturnObject &result) override {
    llvm::StringRef file_path;

    if (!args.empty())
      file_path = args[0].ref();

    if (m_interpreter.SaveTranscript(result, file_path.str()))
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
    else
      result.SetStatus(eReturnStatusFailed);
  }
};

#define LLDB_OPTIONS_history
#include "CommandOptions.inc"

class CommandObjectSessionHistory : public CommandObjectParsed {
public:
  CommandObjectSessionHistory(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "session history",
                            "Dump the history of commands in this session.\n"
                            "Commands in the history list can be run again "
                            "using \"!<INDEX>\".   \"!-<OFFSET>\" will re-run "
                            "the command that is <OFFSET> commands from the end"
                            " of the list (counting the current command).",
                            nullptr) {}

  ~CommandObjectSessionHistory() override = default;

  Options *GetOptions() override { return &m_options; }

protected:
  class CommandOptions : public Options {
  public:
    CommandOptions()
        : m_start_idx(0), m_stop_idx(0), m_count(0), m_clear(false) {}

    ~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 'c':
        error = m_count.SetValueFromString(option_arg, eVarSetOperationAssign);
        break;
      case 's':
        if (option_arg == "end") {
          m_start_idx.SetCurrentValue(UINT64_MAX);
          m_start_idx.SetOptionWasSet();
        } else
          error = m_start_idx.SetValueFromString(option_arg,
                                                 eVarSetOperationAssign);
        break;
      case 'e':
        error =
            m_stop_idx.SetValueFromString(option_arg, eVarSetOperationAssign);
        break;
      case 'C':
        m_clear.SetCurrentValue(true);
        m_clear.SetOptionWasSet();
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_start_idx.Clear();
      m_stop_idx.Clear();
      m_count.Clear();
      m_clear.Clear();
    }

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

    // Instance variables to hold the values for command options.

    OptionValueUInt64 m_start_idx;
    OptionValueUInt64 m_stop_idx;
    OptionValueUInt64 m_count;
    OptionValueBoolean m_clear;
  };

  void DoExecute(Args &command, CommandReturnObject &result) override {
    if (m_options.m_clear.GetCurrentValue() &&
        m_options.m_clear.OptionWasSet()) {
      m_interpreter.GetCommandHistory().Clear();
      result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
    } else {
      if (m_options.m_start_idx.OptionWasSet() &&
          m_options.m_stop_idx.OptionWasSet() &&
          m_options.m_count.OptionWasSet()) {
        result.AppendError("--count, --start-index and --end-index cannot be "
                           "all specified in the same invocation");
        result.SetStatus(lldb::eReturnStatusFailed);
      } else {
        std::pair<bool, uint64_t> start_idx(
            m_options.m_start_idx.OptionWasSet(),
            m_options.m_start_idx.GetCurrentValue());
        std::pair<bool, uint64_t> stop_idx(
            m_options.m_stop_idx.OptionWasSet(),
            m_options.m_stop_idx.GetCurrentValue());
        std::pair<bool, uint64_t> count(m_options.m_count.OptionWasSet(),
                                        m_options.m_count.GetCurrentValue());

        const CommandHistory &history(m_interpreter.GetCommandHistory());

        if (start_idx.first && start_idx.second == UINT64_MAX) {
          if (count.first) {
            start_idx.second = history.GetSize() - count.second;
            stop_idx.second = history.GetSize() - 1;
          } else if (stop_idx.first) {
            start_idx.second = stop_idx.second;
            stop_idx.second = history.GetSize() - 1;
          } else {
            start_idx.second = 0;
            stop_idx.second = history.GetSize() - 1;
          }
        } else {
          if (!start_idx.first && !stop_idx.first && !count.first) {
            start_idx.second = 0;
            stop_idx.second = history.GetSize() - 1;
          } else if (start_idx.first) {
            if (count.first) {
              stop_idx.second = start_idx.second + count.second - 1;
            } else if (!stop_idx.first) {
              stop_idx.second = history.GetSize() - 1;
            }
          } else if (stop_idx.first) {
            if (count.first) {
              if (stop_idx.second >= count.second)
                start_idx.second = stop_idx.second - count.second + 1;
              else
                start_idx.second = 0;
            }
          } else /* if (count.first) */
          {
            start_idx.second = 0;
            stop_idx.second = count.second - 1;
          }
        }
        history.Dump(result.GetOutputStream(), start_idx.second,
                     stop_idx.second);
      }
    }
  }

  CommandOptions m_options;
};

CommandObjectSession::CommandObjectSession(CommandInterpreter &interpreter)
    : CommandObjectMultiword(interpreter, "session",
                             "Commands controlling LLDB session.",
                             "session <subcommand> [<command-options>]") {
  LoadSubCommand("save",
                 CommandObjectSP(new CommandObjectSessionSave(interpreter)));
  LoadSubCommand("history",
                 CommandObjectSP(new CommandObjectSessionHistory(interpreter)));
}
