// 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/fsl/vmo/strings.h>
#include <lib/modular_test_harness/cpp/fake_component.h>
#include <lib/modular_test_harness/cpp/fake_story_shell.h>
#include <lib/modular_test_harness/cpp/test_harness_fixture.h>
#include <src/lib/fxl/logging.h>

#include "peridot/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:
  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:
  const std::string story_name = "story1";
  const std::string mod_name = "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>();
    builder.InterceptSessionShell(test_session_shell_->GetOnCreateHandler(),
                                  {.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>();
    test_module_url_ = modular_testing::TestHarnessBuilder::GenerateFakeUrl();
    builder.InterceptComponent(test_module_->GetOnCreateHandler(), {.url = test_module_url_});
    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.
    FXL_CHECK(test_session_shell_->is_running());
    // The story should not already be created.
    FXL_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(), story_name, mod_name, 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.
    FXL_CHECK(test_session_shell_->is_running());
    // The story should have been previously created through CreateStory.
    FXL_CHECK(test_module_->is_running());

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

    // 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.
    FXL_CHECK(test_module_->is_running());

    // Get a story controller.
    fuchsia::modular::StoryControllerPtr story_controller;
    test_session_shell_->story_provider()->GetController(story_name, 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;

  // 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
