// 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 <fuchsia/modular/testing/cpp/fidl.h>
#include <lib/async/cpp/task.h>
#include <lib/modular/testing/cpp/fake_component.h>
#include <lib/syslog/cpp/macros.h>

#include "src/lib/fsl/vmo/strings.h"
#include "src/modular/lib/modular_test_harness/cpp/fake_story_shell.h"
#include "src/modular/lib/modular_test_harness/cpp/test_harness_fixture.h"
#include "src/modular/lib/testing/session_shell_impl.h"

namespace {

// An implementation of the fuchsia.modular.StoryShellFactory FIDL service, to
// be used in session shell components in integration tests.
class TestStoryShellFactory : fuchsia::modular::StoryShellFactory {
 public:
  using StoryShellRequest = fidl::InterfaceRequest<fuchsia::modular::StoryShell>;

  TestStoryShellFactory(sys::ComponentContext* const component_context) {
    component_context->outgoing()->AddPublicService(GetHandler());
  }

  virtual ~TestStoryShellFactory() override = default;

  // Produces a handler function that can be used in the outgoing service
  // provider.
  fidl::InterfaceRequestHandler<fuchsia::modular::StoryShellFactory> GetHandler() {
    return bindings_.GetHandler(this);
  }

  // Whenever StoryShellFactory.AttachStory() is called, the supplied callback
  // is invoked with the story ID and StoryShell request.
  void set_on_attach_story(
      fit::function<void(std::string story_id, StoryShellRequest request)> callback) {
    on_attach_story_ = std::move(callback);
  }

  // Whenever StoryShellFactory.DetachStory() is called, the supplied callback
  // is invoked. The return callback of DetachStory() is invoked asynchronously
  // after a delay that can be configured by the client with set_detach_delay().
  void set_on_detach_story(fit::function<void()> callback) {
    on_detach_story_ = std::move(callback);
  }

  // Configures the delay after which the return callback of DetachStory() is
  // invoked. Used to test the timeout behavior of sessionmgr.
  void set_detach_delay(zx::duration detach_delay) { detach_delay_ = detach_delay; }

 private:
  // |StoryShellFactory|
  void AttachStory(std::string story_id, StoryShellRequest request) override {
    on_attach_story_(std::move(story_id), std::move(request));
  }

  // |StoryShellFactory|
  void DetachStory(std::string story_id, fit::function<void()> done) override {
    on_detach_story_();

    // Used to simulate a sluggish shell that hits the timeout.
    async::PostDelayedTask(async_get_default_dispatcher(), std::move(done), detach_delay_);
  }

  fidl::BindingSet<fuchsia::modular::StoryShellFactory> bindings_;
  fit::function<void(std::string story_id, StoryShellRequest request)> on_attach_story_{
      [](std::string, StoryShellRequest) {}};
  fit::function<void()> on_detach_story_{[]() {}};
  zx::duration detach_delay_{};
};

// 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:
  TestSessionShell(modular_testing::FakeComponent::Args args)
      : modular_testing::FakeComponent(std::move(args)) {}
  fuchsia::modular::StoryProvider* story_provider() { return story_provider_.get(); }

  TestStoryShellFactory* story_shell_factory() { return story_shell_factory_.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());

    story_shell_factory_ = std::make_unique<TestStoryShellFactory>(component_context());
  }

  modular_testing::SessionShellImpl session_shell_impl_;
  fuchsia::modular::SessionShellContextPtr session_shell_context_;
  fuchsia::modular::StoryProviderPtr story_provider_;
  std::unique_ptr<TestStoryShellFactory> story_shell_factory_;
};

class StoryShellFactoryTest : public modular_testing::TestHarnessFixture {
 public:
  static constexpr auto kStoryName = "story1";
  static constexpr auto kModName = "mod1";

  TestSessionShell* test_session_shell() { return test_session_shell_.get(); }

  // Initializes the session shell, story shell factory, and story shell
  // implementations and starts the modular test harness.
  void InitSession() {
    // The session shell provides the StoryShellFactory protocol.
    fuchsia::modular::testing::TestHarnessSpec spec;
    spec.mutable_basemgr_config()->set_use_session_shell_for_story_shell_factory(true);

    modular_testing::TestHarnessBuilder builder(std::move(spec));
    test_session_shell_ = std::make_unique<TestSessionShell>(modular_testing::FakeComponent::Args{
        .url = modular_testing::TestHarnessBuilder::GenerateFakeUrl(),
        .sandbox_services = {"fuchsia.modular.SessionShellContext",
                             "fuchsia.modular.PuppetMaster"}});
    // Listen for the module that is created in CreateStory().
    test_module_ =
        std::make_unique<modular_testing::FakeComponent>(modular_testing::FakeComponent::Args{
            .url = modular_testing::TestHarnessBuilder::GenerateFakeUrl()});
    builder.InterceptSessionShell(test_session_shell_->BuildInterceptOptions());
    builder.InterceptComponent(test_module_->BuildInterceptOptions());
    builder.BuildAndRun(test_harness());

    // Wait for our session shell to start.
    RunLoopUntil([this] { return test_session_shell_->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() {
    // The session shell should be running and connected to PuppetMaster.
    FX_CHECK(test_session_shell_->is_running());
    // The story should not already be created.
    FX_CHECK(!test_module_->is_running());

    // Create a story
    fuchsia::modular::Intent intent;
    intent.handler = test_module_->url();
    intent.action = "action";
    modular_testing::AddModToStory(test_harness(), kStoryName, kModName, std::move(intent));

    // Wait for the story to be created.
    RunLoopUntil([this] { return test_module_->is_running(); });
  }

  void DeleteStory() {
    // The session shell should be running and connected to PuppetMaster.
    FX_CHECK(test_session_shell_->is_running());
    // The story should have been previously created through CreateStory.
    FX_CHECK(test_module_->is_running());

    puppet_master_->DeleteStory(kStoryName, [] {});

    // Wait for the story to be deleted.
    RunLoopUntil([this] { return !test_module_->is_running(); });
  }

  fuchsia::modular::StoryControllerPtr ControlStory() {
    // The story should have been previously created through CreateStory.
    FX_CHECK(test_module_->is_running());

    // Get a story controller.
    fuchsia::modular::StoryControllerPtr story_controller;
    test_session_shell_->story_provider()->GetController(kStoryName, story_controller.NewRequest());

    return story_controller;
  }

 private:
  // Component URL of the |test_module_| intercepted in InitSession().
  std::string test_module_url_;

  fuchsia::modular::PuppetMasterPtr puppet_master_;
  std::unique_ptr<TestSessionShell> test_session_shell_;
  std::unique_ptr<modular_testing::FakeComponent> test_module_;
};

TEST_F(StoryShellFactoryTest, AttachCalledOnStoryStart) {
  InitSession();

  modular_testing::FakeStoryShell fake_story_shell(modular_testing::FakeComponent::Args{
      .url = modular_testing::TestHarnessBuilder::GenerateFakeUrl()});

  // The StoryShellFactory will be asked to attach a StoryShell when the story
  // is started.
  bool is_attached{false};
  test_session_shell()->story_shell_factory()->set_on_attach_story(
      [&](std::string, fidl::InterfaceRequest<fuchsia::modular::StoryShell> request) {
        is_attached = true;
        fake_story_shell.GetHandler()(std::move(request));
      });

  CreateStory();

  // Start and show the story.
  auto story_controller = ControlStory();
  story_controller->RequestStart();

  // Wait for the StoryShellFactory to attach the StoryShell.
  RunLoopUntil([&] { return is_attached; });
};

TEST_F(StoryShellFactoryTest, DetachCalledOnStoryStop) {
  InitSession();

  // The StoryShellFactory will be asked to detach a StoryShell when the story
  // is stopped.
  bool is_detached{false};
  test_session_shell()->story_shell_factory()->set_on_detach_story([&]() { is_detached = true; });

  CreateStory();

  // Start and show the story.
  auto story_controller = ControlStory();
  story_controller->RequestStart();

  // Stop the story.
  story_controller->Stop([]() {});

  // Wait for the StoryShellFactory to detach the StoryShell.
  RunLoopUntil([&] { return is_detached; });
};

TEST_F(StoryShellFactoryTest, DetachCalledOnStoryDelete) {
  InitSession();

  // The StoryShellFactory will be asked to detach a StoryShell when the story
  // is deleted.
  bool is_detached{false};
  test_session_shell()->story_shell_factory()->set_on_detach_story([&]() { is_detached = true; });

  CreateStory();

  // Start and show the story.
  auto story_controller = ControlStory();
  story_controller->RequestStart();

  DeleteStory();

  // Wait for the StoryShellFactory to detach the StoryShell.
  RunLoopUntil([&] { return is_detached; });
};

}  // namespace
