// Copyright 2019 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 <memory>
#include <utility>

#include <fuchsia/modular/cpp/fidl.h>
#include <fuchsia/sys/cpp/fidl.h>
#include <lib/fidl/cpp/binding.h>
#include <lib/fsl/vmo/strings.h>
#include <lib/modular_test_harness/cpp/fake_component.h>
#include <lib/modular_test_harness/cpp/fake_module.h>
#include <lib/modular_test_harness/cpp/test_harness_fixture.h>
#include <src/lib/fxl/logging.h>
#include <src/lib/fxl/macros.h>
#include <src/lib/fxl/strings/string_number_conversions.h>
#include <trace/event.h>

#include "peridot/lib/testing/session_shell_impl.h"
#include "src/modular/benchmarks/tracing_waiter.h"

namespace {

// Number of stories to create in the Loop test.
const int kStoryCount = 5;

// Number of times each module sets its link value.
const int kLinkSetCount = 100;

class TestStoryWatcher : fuchsia::modular::StoryWatcher {
 public:
  TestStoryWatcher() : binding_(this) {}
  ~TestStoryWatcher() override = default;

  // Registers itself as a watcher on the given story. Only one story at a time
  // can be watched.
  void Watch(fuchsia::modular::StoryController* const story_controller) {
    story_controller->Watch(binding_.NewBinding());
  }

  // Deregisters itself from the watched story.
  void Reset() { binding_.Unbind(); }

  // Sets a callback that will be called once the story is running.
  void OnStoryRunning(fit::function<void()> on_running) { on_running_ = std::move(on_running); }

 private:
  // |fuchsia::modular::StoryWatcher|
  void OnStateChange(fuchsia::modular::StoryState state) override {
    FXL_LOG(INFO) << "TestStoryWatcher.OnStateChange(): " << fidl::ToUnderlying(state);
    if (state != fuchsia::modular::StoryState::RUNNING) {
      return;
    }

    on_running_();
  }

  // |fuchsia::modular::StoryWatcher|
  void OnModuleAdded(fuchsia::modular::ModuleData /*module_data*/) override {}

  // |fuchsia::modular::StoryWatcher|
  void OnModuleFocused(std::vector<std::string> /*module_path*/) override {}

  fit::function<void()> on_running_;
  fidl::Binding<fuchsia::modular::StoryWatcher> binding_;
};

// A simple link watcher implementation that invokes a callback when
// it sees the watched link change.
class TestLinkWatcher : fuchsia::modular::LinkWatcher {
 public:
  TestLinkWatcher() : binding_(this) {}
  ~TestLinkWatcher() override = default;

  // Registers itself as a watcher on the given link. Only one story at a time
  // can be watched.
  void Watch(fuchsia::modular::Link* const link) { link->WatchAll(binding_.NewBinding()); }

  // Deregisters itself from the watched story.
  void Reset() { binding_.Unbind(); }

  // Sets the function that is called when the link changes.
  void OnNotify(fit::function<void(fidl::StringPtr)> callback) { on_notify_ = std::move(callback); }

 private:
  // |fuchsia::modular::LinkWatcher|
  void Notify(fuchsia::mem::Buffer value) override {
    std::string json;
    FXL_CHECK(fsl::StringFromVmo(value, &json));
    on_notify_(std::move(json));
  }

  fidl::Binding<fuchsia::modular::LinkWatcher> binding_;

  fit::function<void(fidl::StringPtr)> on_notify_{[](fidl::StringPtr) {}};

  FXL_DISALLOW_COPY_AND_ASSIGN(TestLinkWatcher);
};

// A basic fake session shell component: gives access to services
// available to session shells in their environment, as well as an
// implementation of fuchsia::modular::SessionShell built for tests.
class TestSessionShell : public modular::testing::FakeComponent {
 public:
  fuchsia::modular::StoryProvider* story_provider() { return story_provider_.get(); }

  fuchsia::modular::SessionShellContext* session_shell_context() {
    return session_shell_context_.get();
  }

 private:
  // |modular::testing::FakeComponent|
  void OnCreate(fuchsia::sys::StartupInfo startup_info) override {
    component_context()->svc()->Connect(session_shell_context_.NewRequest());
    session_shell_context_->GetStoryProvider(story_provider_.NewRequest());

    component_context()->outgoing()->AddPublicService(session_shell_impl_.GetHandler());
  }

  modular::testing::SessionShellImpl session_shell_impl_;
  fuchsia::modular::SessionShellContextPtr session_shell_context_;
  fuchsia::modular::StoryProviderPtr story_provider_;
};

// This module repeatedly updates its root link a number of times and then
// just sits there until it's terminated.
class TestModule : public modular::testing::FakeModule, fuchsia::modular::LinkWatcher {
 public:
  TestModule() : link_watcher_binding_(this) {}

 private:
  // |modular::testing::FakeComponent|
  void OnCreate(fuchsia::sys::StartupInfo startup_info) override {
    modular::testing::FakeModule::OnCreate(std::move(startup_info));

    FXL_LOG(INFO) << "TestModule.OnCreate()";

    module_context()->GetLink(nullptr, link_.NewRequest());

    // Will call Notify() with current value.
    link_->WatchAll(link_watcher_binding_.NewBinding());
  }

  // |fuchsia::modular::LinkWatcher|
  void Notify(fuchsia::mem::Buffer content) override {
    std::string json;
    FXL_CHECK(fsl::StringFromVmo(content, &json));
    FXL_LOG(INFO) << "TestModule.Notify(): " << json;

    // First invocation is from WatchAll(); next from Set().
    if (count_ == -1) {
      count_ = 0;
      Set();
      return;
    }

    // Corresponding TRACE_ASYNC_BEGIN() is in Set().
    TRACE_ASYNC_END("benchmark", "link/set", count_);

    ++count_;
    if (count_ <= kLinkSetCount) {
      Set();
    }
  }

  void Set() {
    FXL_LOG(INFO) << "TestModule.Set(): " << count_;

    // Corresponding TRACE_ASYNC_END() is in Notify().
    TRACE_ASYNC_BEGIN("benchmark", "link/set", count_);

    // Corresponding TRACE_FLOW_END() is in the session shell.
    TRACE_FLOW_BEGIN("benchmark", "link/trans", count_);

    fsl::SizedVmo vmo;
    FXL_CHECK(fsl::VmoFromString(std::to_string(count_), &vmo));
    link_->Set(nullptr, std::move(vmo).ToTransport());
  }

  // The number of times the root link has been set.
  int count_{-1};

  fuchsia::modular::LinkPtr link_;
  fidl::Binding<fuchsia::modular::LinkWatcher> link_watcher_binding_;
};

// Measures timing the machinery available to a session shell implementation.
class StoryBenchmarkTest : public modular::testing::TestHarnessFixture {
 public:
  // Name of the module created in CreateStory().
  const std::string kModName = "mod";

  // Prefix of the name of each story created.
  const std::string kStoryNamePrefix = "story-";

  // Initializes and starts the modular test harness.
  void InitSession() {
    modular_testing::TestHarnessBuilder builder;

    link_watcher_ = std::make_unique<TestLinkWatcher>();
    story_watcher_ = std::make_unique<TestStoryWatcher>();

    session_shell_ = std::make_unique<TestSessionShell>();
    builder.InterceptSessionShell(session_shell_->GetOnCreateHandler(),
                                  {.sandbox_services = {"fuchsia.modular.SessionShellContext",
                                                        "fuchsia.modular.PuppetMaster"}});

    // Listen for the module that is created in CreateStory().
    module_ = std::make_unique<TestModule>();
    module_url_ = modular_testing::TestHarnessBuilder::GenerateFakeUrl();
    builder.InterceptComponent(
        module_->GetOnCreateHandler(),
        {.url = module_url_, .sandbox_services = module_->GetSandboxServices()});

    TRACE_ASYNC_BEGIN("benchmark", "session/start", 0);
    builder.BuildAndRun(test_harness());

    // Wait for our session shell to start.
    RunLoopUntil([&] {
      bool is_running = session_shell_->is_running();
      if (is_running) {
        TRACE_ASYNC_END("benchmark", "session/start", 0);
      }
      return is_running;
    });

    // Connect to the PuppetMaster service also provided to the session shell.
    fuchsia::modular::testing::ModularService modular_service;
    modular_service.set_puppet_master(puppet_master_.NewRequest());
    test_harness()->ConnectToModularService(std::move(modular_service));
  }

  void CreateStory(std::string story_name) {
    FXL_LOG(INFO) << "CreateStory()";
    TRACE_ASYNC_BEGIN("benchmark", "story/create", 0);

    story_name_ = story_name;

    puppet_master_->ControlStory(story_name_, story_puppet_master_.NewRequest());

    fuchsia::modular::AddMod add_mod;
    add_mod.mod_name_transitional = kModName;
    add_mod.intent.handler = module_url_;
    add_mod.intent.action = "action";

    std::vector<fuchsia::modular::StoryCommand> commands(1);
    commands.at(0).set_add_mod(std::move(add_mod));

    story_puppet_master_->Enqueue(std::move(commands));

    bool is_created{false};
    story_puppet_master_->Execute([&](fuchsia::modular::ExecuteResult result) {
      TRACE_ASYNC_END("benchmark", "story/create", 0);
      is_created = true;
    });

    // Wait for the story to be created.
    RunLoopUntil([&] { return is_created; });

    session_shell_->story_provider()->GetController(story_name_, story_controller_.NewRequest());
  }

  void StoryInfo() {
    FXL_LOG(INFO) << "StoryInfo()";
    TRACE_ASYNC_BEGIN("benchmark", "story/info", 0);

    bool got_story_info{false};
    story_controller_->GetInfo(
        [&](fuchsia::modular::StoryInfo story_info, fuchsia::modular::StoryState state) {
          TRACE_ASYNC_END("benchmark", "story/info", 0);
          got_story_info = true;
        });

    // Wait for the story info to be returned.
    RunLoopUntil([&] { return got_story_info; });
  }

  void StartStory() {
    FXL_LOG(INFO) << "StartStory()";
    TRACE_ASYNC_BEGIN("benchmark", "story/start", 0);

    bool is_started{false};
    story_watcher_->OnStoryRunning([&] {
      TRACE_ASYNC_END("benchmark", "story/start", 0);
      is_started = true;
    });

    story_watcher_->Watch(story_controller_.get());
    story_controller_->RequestStart();

    // Wait for the story to start.
    RunLoopUntil([&] { return is_started; });
  }

  void WatchLink() {
    FXL_LOG(INFO) << "WatchLink()";

    std::vector<std::string> module_path = {kModName};
    fuchsia::modular::LinkPath link_path{.module_path = std::move(module_path),
                                         .link_name = nullptr};
    story_controller_->GetLink(std::move(link_path), link_.NewRequest());

    link_watcher_->Watch(link_.get());

    link_watcher_->OnNotify([&](fidl::StringPtr json) {
      FXL_LOG(INFO) << "WatchLink(): " << json;
      // Ignore empty links which have the JSON string value "null".
      if (json == "null") {
        return;
      }

      link_value_ = fxl::StringToNumber<int>(json.value_or(""));

      // Corresponding TRACE_FLOW_BEGIN() is in the module.
      TRACE_FLOW_END("benchmark", "link/trans", link_value_);
    });
  }

  void StopStory() {
    FXL_LOG(INFO) << "StopStory()";
    TRACE_ASYNC_BEGIN("benchmark", "story/stop", 0);

    bool is_stopped{false};
    story_controller_->Stop([&] {
      TRACE_ASYNC_END("benchmark", "story/stop", 0);
      is_stopped = true;
    });

    // Wait for the story to stop.
    RunLoopUntil([&] { return is_stopped; });
  }

  void Reset() {
    FXL_LOG(INFO) << "Reset()";
    link_watcher_->Reset();
    story_watcher_->Reset();
    story_controller_.Unbind();
    story_puppet_master_.Unbind();
    story_name_.clear();
  }

  void Logout() {
    FXL_LOG(INFO) << "Logout()";
    TRACE_ASYNC_BEGIN("benchmark", "user/logout", 0);
    session_shell_->session_shell_context()->Logout();
    TRACE_ASYNC_END("benchmark", "user/logout", 0);
  }

  // The name of the story created by CreateStory().
  std::string story_name_;

  // Component URL of the |module_| intercepted in InitSession().
  std::string module_url_;

  // The last link value that |link_watcher_| has observed.
  int link_value_{0};

  std::unique_ptr<TestStoryWatcher> story_watcher_;
  std::unique_ptr<TestSessionShell> session_shell_;
  std::unique_ptr<TestModule> module_;
  std::unique_ptr<TestLinkWatcher> link_watcher_;

  fuchsia::modular::StoryControllerPtr story_controller_;
  fuchsia::modular::PuppetMasterPtr puppet_master_;
  fuchsia::modular::StoryPuppetMasterPtr story_puppet_master_;
  fuchsia::modular::LinkPtr link_;

  modular::TracingWaiter tracing_waiter_;
};

TEST_F(StoryBenchmarkTest, Loop) {
  // Wait for the tracing service to be ready to use.
  bool is_tracing_started{false};
  tracing_waiter_.WaitForTracing([&] { is_tracing_started = true; });
  RunLoopUntil([&] { return is_tracing_started; });

  InitSession();

  for (int i = 1; i <= kStoryCount; i++) {
    auto story_name = std::string(kStoryNamePrefix) + std::to_string(i);

    FXL_LOG(INFO) << "Creating story \"" << story_name << "\" (" << i << " of " << kStoryCount
                  << ")";

    CreateStory(story_name);
    StoryInfo();
    WatchLink();
    StartStory();

    // Wait for the module to set the link value |kLinkSetCount| times.
    RunLoopUntil([&] { return link_value_ == kLinkSetCount; });

    StopStory();

    Reset();
  }

  Logout();
}

}  // namespace
