// 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::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::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, false);
        }));
  }
  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()));

  for (auto& action : CommandsToActions(contents)) {
    actions->push_back(std::move(action));
  }
  return Err();
}

}  // namespace zxdb
