// 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.

#include "src/developer/debug/zxdb/console/command.h"

#include <lib/syslog/cpp/macros.h>

#include <algorithm>

#include "src/developer/debug/zxdb/common/err.h"
#include "src/developer/debug/zxdb/console/nouns.h"
#include "src/developer/debug/zxdb/console/verbs.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace zxdb {

const int Command::kNoIndex;

Command::Command() = default;
Command::~Command() = default;

bool Command::HasNoun(Noun noun) const { return nouns_.find(noun) != nouns_.end(); }

int Command::GetNounIndex(Noun noun) const {
  auto found = nouns_.find(noun);
  if (found == nouns_.end())
    return kNoIndex;
  return found->second;
}

void Command::SetNoun(Noun noun, int index) {
  FX_DCHECK(nouns_.find(noun) == nouns_.end());
  nouns_[noun] = index;
}

Err Command::ValidateNouns(std::initializer_list<Noun> allowed_nouns) const {
  for (const auto& pair : nouns_) {
    if (std::find(allowed_nouns.begin(), allowed_nouns.end(), pair.first) == allowed_nouns.end()) {
      return Err(ErrType::kInput, fxl::StringPrintf("\"%s\" may not be specified for this command.",
                                                    NounToString(pair.first).c_str()));
    }
  }
  return Err();
}

bool Command::HasSwitch(int id) const { return switches_.find(id) != switches_.end(); }

std::string Command::GetSwitchValue(int id) const {
  auto found = switches_.find(id);
  if (found == switches_.end())
    return std::string();
  return found->second;
}

void Command::SetSwitch(int id, std::string str) { switches_[id] = std::move(str); }

Err DispatchCommand(ConsoleContext* context, const Command& cmd, CommandCallback callback) {
  if (cmd.verb() == Verb::kNone)
    return ExecuteNoun(context, cmd);

  const auto& verbs = GetVerbs();
  const auto& found = verbs.find(cmd.verb());
  if (found == verbs.end()) {
    return Err(ErrType::kInput, "Invalid verb \"" + VerbToString(cmd.verb()) + "\".");
  }

  auto& verb_record = found->second;
  if (verb_record.exec_cb) {
    return verb_record.exec_cb(context, cmd, std::move(callback));
  } else {
    Err original_err = verb_record.exec(context, cmd);
    if (callback) {
      // We need to call the callback to let the caller know they ran a command
      // that doesn't receive callbacks.
      Err callback_err = original_err.has_error()
                             ? original_err
                             : Err("Command was processed but it doesn't receive "
                                   "callbacks. Going to interactive mode.");
      // Commands without callbacks never quit by callback.
      callback(callback_err);
    }
    return original_err;
  }
}

}  // namespace zxdb
