// 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>
#include <lib/fxl/functional/make_copyable.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(new 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,
    std::function<void(fuchsia::modular::ExecuteResult)> done) {
  operation_queues_[story_id].Add(new ExecuteStoryCommandsCall(
      this, std::move(story_id), std::move(commands), std::move(done)));
}

}  // namespace modular
