// 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/actions.h"

#include "src/developer/debug/shared/message_loop.h"
#include "src/lib/files/file.h"
#include "src/lib/files/path.h"
#include "src/lib/fxl/strings/split_string.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace zxdb {

namespace {

using Option = fxl::CommandLine::Option;

}  // namespace

// Action ----------------------------------------------------------------------

Action::Action() = default;
Action::Action(std::string name, Action::ActionFunction action)
    : name_(name), action_(std::move(action)) {}

Action::Action(Action&&) = default;
Action& Action::operator=(Action&& other) {
  this->name_ = std::move(other.name_);
  this->action_ = std::move(other.action_);
  return *this;
}

void Action::operator()(const Session& session, Console* console) const {
  // The next_action_ chaining will take care of calling the following command
  // when the time is due.
  action_(*this, session, console);
}

// ActionFlow ------------------------------------------------------------------

void ActionFlow::ScheduleActions(std::vector<Action>&& actions, const Session* session,
                                 Console* console, Callback callback) {
  // If there are no actions, we schedule the callback.
  if (actions.empty()) {
    callback_(Err());
    return;
  }

  // We store the parameters as they will be used in the future.
  flow_ = std::move(actions);
  session_ = session;
  console_ = console;
  callback_ = std::move(callback);

  // We schedule the first action to run
  debug_ipc::MessageLoop::Current()->PostTask(FROM_HERE, [&]() {
    const auto& action = flow_.front();
    action(*session_, console_);
  });
}

ActionFlow& ActionFlow::Singleton() {
  // We use the global callback function so that the user doesn't have to
  // worry about tracking an instance.
  static ActionFlow flow;
  return flow;
}

ActionFlow::ActionFlow() = default;

void ActionFlow::PostActionCallback(Err err) {
  ActionFlow& flow = ActionFlow::Singleton();
  // We log the callback
  flow.callbacks_.push_back(err);

  // If the command wants us to stop processing, we call the complete callback.
  if ((err.type() == ErrType::kCanceled) || err.has_error()) {
    flow.callback_(err);
    return;
  }

  flow.current_action_index_++;
  // In no more actions available, communicate to caller.
  if (flow.current_action_index_ >= flow.flow_.size()) {
    flow.callback_(Err());
    return;
  }

  // Schedule the next action.
  const auto& next_action = flow.current_action();
  debug_ipc::MessageLoop::Current()->PostTask(
      FROM_HERE, [&]() { next_action(*flow.session_, flow.console_); });
}

void ActionFlow::Clear() {
  flow_.clear();
  current_action_index_ = 0;
  session_ = nullptr;
  console_ = nullptr;
  callback_ = nullptr;
  callbacks_.clear();
}

std::vector<Action> CommandsToActions(const std::string& input) {
  auto commands = fxl::SplitStringCopy(input, "\n", fxl::kTrimWhitespace, fxl::kSplitWantNonEmpty);
  std::vector<Action> result;
  for (size_t i = 0; i < commands.size(); i++) {
    result.push_back(Action(
        commands[i],
        [&, cmd = commands[i]](const Action& action, const Session& session, Console* console) {
          console->ProcessInputLine(cmd.c_str(), ActionFlow::PostActionCallback);
        }));
  }
  return result;
}

Err ScriptFileToActions(const std::string& path, std::vector<Action>* actions) {
  std::string contents;
  if (!files::ReadFileToString(files::AbsolutePath(path), &contents))
    return Err(fxl::StringPrintf("Could not read file \"%s\"", path.c_str()));

  *actions = CommandsToActions(contents);
  return Err();
}

}  // namespace zxdb
