#include "CommandObjectSession.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.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.",
                            "session save [file]") {
    CommandArgumentEntry arg1;
    arg1.emplace_back(eArgTypePath, eArgRepeatOptional);
    m_arguments.push_back(arg1);
  }

  ~CommandObjectSessionSave() override = default;

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    CommandCompletions::InvokeCommonCompletionCallbacks(
        GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
        request, nullptr);
  }

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

#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),
        m_options() {}

  ~CommandObjectSessionHistory() override = default;

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

protected:
  class CommandOptions : public Options {
  public:
    CommandOptions()
        : Options(), 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::makeArrayRef(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;
  };

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

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