// 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 "peridot/bin/sessionmgr/puppet_master/dispatch_story_command_executor.h"

#include <map>

#include <lib/async/cpp/future.h>
#include <lib/async/cpp/operation.h>

namespace modular {

namespace {

class RunStoryCommandCall : public Operation<fuchsia::modular::ExecuteResult> {
 public:
  RunStoryCommandCall(const char* const command_name,
                      CommandRunner* const runner,
                      StoryStorage* const story_storage,
                      fidl::StringPtr story_id,
                      fuchsia::modular::StoryCommand command, ResultCall done)
      : Operation(command_name, std::move(done), ""),
        command_(std::move(command)),
        story_storage_(story_storage),
        story_id_(std::move(story_id)),
        runner_(runner) {}

 private:
  // |OperationBase|
  void Run() override {
    auto done = [this](fuchsia::modular::ExecuteResult result) {
      Done(std::move(result));
    };
    runner_->Execute(story_id_, story_storage_, std::move(command_),
                     std::move(done));
  }

  fuchsia::modular::StoryCommand command_;
  StoryStorage* const story_storage_;
  const fidl::StringPtr story_id_;
  CommandRunner* runner_;
};

}  // namespace

class DispatchStoryCommandExecutor::ExecuteStoryCommandsCall
    : public Operation<fuchsia::modular::ExecuteResult> {
 public:
  ExecuteStoryCommandsCall(DispatchStoryCommandExecutor* const executor,
                           fidl::StringPtr story_id,
                           std::vector<fuchsia::modular::StoryCommand> commands,
                           ResultCall done)
      : Operation("ExecuteStoryCommandsCall", std::move(done)),
        executor_(executor),
        story_id_(std::move(story_id)),
        commands_(std::move(commands)) {}

  ~ExecuteStoryCommandsCall() override = default;

 private:
  void Run() override {
    executor_->session_storage_->GetStoryStorage(story_id_)->WeakThen(
        GetWeakPtr(), [this](std::unique_ptr<StoryStorage> story_storage) {
          if (!story_storage) {
            fuchsia::modular::ExecuteResult result;
            result.status = fuchsia::modular::ExecuteStatus::INVALID_STORY_ID;
            Done(result);
            return;
          }

          story_storage_ = std::move(story_storage);
          Cont();
        });
  }

  void Cont() {
    // TODO(thatguy): Add a WeakPtr check on |executor_|.

    // Keep track of the number of commands we need to run. When they are all
    // done, we complete this operation.
    std::vector<FuturePtr<>> did_execute_commands;
    did_execute_commands.reserve(commands_.size());

    for (auto& command : commands_) {
      auto tag_string_it =
          executor_->story_command_tag_strings_.find(command.Which());
      FXL_CHECK(tag_string_it != executor_->story_command_tag_strings_.end())
          << "No fuchsia::modular::StoryCommand::Tag string for tag "
          << static_cast<int>(command.Which());
      const auto& tag_string = tag_string_it->second;

      auto it = executor_->command_runners_.find(command.Which());
      FXL_DCHECK(it != executor_->command_runners_.end())
          << "Could not find a fuchsia::modular::StoryCommand runner for tag "
          << static_cast<int>(command.Which()) << ": " << tag_string;

      auto* const command_runner = it->second.get();
      // NOTE: it is safe to capture |this| on the lambdas below because if
      // |this| goes out of scope, |queue_| will be deleted, and the callbacks
      // on |queue_| will not run.

      auto did_execute_command =
          Future<fuchsia::modular::ExecuteResult>::Create(
              "DispatchStoryCommandExecutor.ExecuteStoryCommandsCall.Run.did_"
              "execute_command");
      queue_.Add(std::make_unique<RunStoryCommandCall>(
          tag_string, command_runner, story_storage_.get(), story_id_,
          std::move(command), did_execute_command->Completer()));
      auto did_execute_command_callback = did_execute_command->Then(
          [this](fuchsia::modular::ExecuteResult result) {
            // Check for error for this command. If there was an error, abort
            // early. All of the remaining operations (if any) in queue_ will
            // not be run.
            if (result.status != fuchsia::modular::ExecuteStatus::OK) {
              Done(std::move(result));
            }
          });
      did_execute_commands.emplace_back(did_execute_command_callback);
    }

    Wait("DispatchStoryCommandExecutor.ExecuteStoryCommandsCall.Run.Wait",
         did_execute_commands)
        ->Then([this] {
          fuchsia::modular::ExecuteResult result;
          result.status = fuchsia::modular::ExecuteStatus::OK;
          result.story_id = story_id_;
          Done(std::move(result));
        });
  }

  DispatchStoryCommandExecutor* const executor_;
  const fidl::StringPtr story_id_;
  std::vector<fuchsia::modular::StoryCommand> commands_;

  std::unique_ptr<StoryStorage> story_storage_;

  // All commands must be run in order so we use a queue.
  OperationQueue queue_;
};

DispatchStoryCommandExecutor::DispatchStoryCommandExecutor(
    SessionStorage* const session_storage,
    std::map<fuchsia::modular::StoryCommand::Tag,
             std::unique_ptr<CommandRunner>>
        command_runners)
    : session_storage_(session_storage),
      command_runners_(std::move(command_runners)),
      story_command_tag_strings_{
          {fuchsia::modular::StoryCommand::Tag::kAddMod,
           "StoryCommand::AddMod"},
          {fuchsia::modular::StoryCommand::Tag::kFocusMod,
           "StoryCommand::FocusMod"},
          {fuchsia::modular::StoryCommand::Tag::kRemoveMod,
           "StoryCommand::RemoveMod"},
          {fuchsia::modular::StoryCommand::Tag::kSetLinkValue,
           "StoryCommand::SetLinkValue"},
          {fuchsia::modular::StoryCommand::Tag::kSetFocusState,
           "StoryCommand::SetFocusState"},
          {fuchsia::modular::StoryCommand::Tag::kSetKindOfProtoStoryOption,
           "StoryCommand::SetKindOfProtoStoryOption"}} {
  FXL_DCHECK(session_storage_ != nullptr);
}

DispatchStoryCommandExecutor::~DispatchStoryCommandExecutor() {}

void DispatchStoryCommandExecutor::ExecuteCommandsInternal(
    fidl::StringPtr story_id,
    std::vector<fuchsia::modular::StoryCommand> commands,
    fit::function<void(fuchsia::modular::ExecuteResult)> done) {
  operation_queues_[story_id].Add(std::make_unique<ExecuteStoryCommandsCall>(
      this, std::move(story_id), std::move(commands), std::move(done)));
}

}  // namespace modular
