// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef GARNET_BIN_ZXDB_CONSOLE_COMMAND_H_
#define GARNET_BIN_ZXDB_CONSOLE_COMMAND_H_

#include <initializer_list>
#include <map>
#include <string>
#include <vector>

#include "garnet/bin/zxdb/common/err.h"
#include "garnet/bin/zxdb/console/nouns.h"
#include "garnet/bin/zxdb/console/verbs.h"

namespace zxdb {

class Breakpoint;
class ConsoleContext;
class Frame;
class Target;
class JobContext;
class Thread;

// Command ---------------------------------------------------------------------

class Command {
 public:
  // This valid indicates that there was a noun specified but no index.
  // For example the command "process step" specifies the process noun but
  // not an index.
  static constexpr int kNoIndex = -1;

  Command();
  ~Command();

  // Returns true if the noun was specified by the user.
  bool HasNoun(Noun noun) const;

  // Returns the index specified for the given noun. If the noun was not
  // specified or the index was not specified, returns kNoIndex (use HasNoun to
  // disambiguate).
  int GetNounIndex(Noun noun) const;

  // Sets that the given noun was present. index may be kNoIndex.
  void SetNoun(Noun noun, int index);

  const std::map<Noun, int>& nouns() const { return nouns_; }

  // Checks the specified nouns against the parameter listing the allowed ones.
  // If any nouns are specified that are not in the list, generates an error
  // and returns it. Otherwise it will return an empty error.
  Err ValidateNouns(std::initializer_list<Noun> allowed_nouns) const;

  Verb verb() const { return verb_; }
  void set_verb(Verb v) { verb_ = v; }

  // Returns whether a given switch was specified.
  bool HasSwitch(int id) const;

  // Returns the value corresponding to the given switch, or the empty string
  // if not specified.
  std::string GetSwitchValue(int id) const;

  void SetSwitch(int id, std::string str);

  const std::map<int, std::string>& switches() const { return switches_; }

  const std::vector<std::string>& args() const { return args_; }
  void set_args(std::vector<std::string> a) { args_ = std::move(a); }

  // The computed environment for the command. This is filled in with the
  // objects corresponding to the indices given on the command line, and
  // default to the current one for the current command line.
  //
  // If HasNoun() returns true, the corresponding getter here is guaranteed
  // non-null.
  Frame* frame() const { return frame_; }
  void set_frame(Frame* f) { frame_ = f; }
  Target* target() const { return target_; }
  void set_target(Target* t) { target_ = t; }
  JobContext* job_context() const { return job_context_; }
  void set_job_context(JobContext* t) { job_context_ = t; }
  Thread* thread() const { return thread_; }
  void set_thread(Thread* t) { thread_ = t; }
  Breakpoint* breakpoint() const { return breakpoint_; }
  void set_breakpoint(Breakpoint* b) { breakpoint_ = b; }

 private:
  // The nouns specified for this command. If not present here, the noun
  // was not written on the command line. If present but there was no index
  // given for it, the mapped value will be kNoIndex. Otherwise the mapped
  // value will be the index specified.
  std::map<Noun, int> nouns_;

  // The effective context for the command. The explicitly specified process/
  // thread/etc. will be reflected here, and anything that wasn't explicit
  // will inherit the default.
  Target* target_ = nullptr;  // Guaranteed non-null for valid commands.
  JobContext* job_context_ = nullptr;  // May be null.
  Thread* thread_ = nullptr;  // Will be null if not running.
  Frame* frame_ = nullptr;    // Will be null if no valid thread stopped.
  Breakpoint* breakpoint_ = nullptr;  // May be null.

  Verb verb_ = Verb::kNone;

  std::map<int, std::string> switches_;
  std::vector<std::string> args_;
};

// Command dispatch ------------------------------------------------------------

// Type for a callback that a CommandExecutor will receive
using CommandCallback = std::function<void(Err)>;

// Runs the given command.
Err DispatchCommand(ConsoleContext* context, const Command& cmd,
                    CommandCallback callback = nullptr);

}  // namespace zxdb

#endif  // GARNET_BIN_ZXDB_CONSOLE_COMMAND_H_
