// Copyright 2016 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/fsl/vmo/strings.h>
#include <lib/modular_test_harness/cpp/fake_session_shell.h>
#include <lib/modular_test_harness/cpp/test_harness_fixture.h>
#include <peridot/lib/modular_config/modular_config_constants.h>

#include "gmock/gmock.h"

// TODO(MF-435): Use modular::testing::AddModToStory() throughout the test.
using fuchsia::modular::AddMod;
using fuchsia::modular::StoryCommand;
using fuchsia::modular::StoryInfo;
using fuchsia::modular::StoryInfo2;
using fuchsia::modular::StoryState;
using fuchsia::modular::StoryVisibilityState;
using fuchsia::modular::ViewIdentifier;
using testing::IsNull;
using testing::Not;

constexpr char kFakeModuleUrl[] = "fuchsia-pkg://example.com/FAKE_MODULE_PKG/fake_module.cmx";

namespace {

class SessionShellTest : public modular::testing::TestHarnessFixture {
 protected:
  // Shared boilerplate for configuring the test harness to intercept the
  // session shell, setting up the session shell mock object, running the test
  // harness, and waiting for the session shell to be successfully intercepted.
  // Note that this method blocks the thread until the session shell has started
  // up.
  //
  // Not done in SetUp() or the constructor to let the test reader know that
  // this is happening. Also, certain tests may want to change this flow.
  void RunHarnessAndInterceptSessionShell() {
    modular_testing::TestHarnessBuilder builder;
    builder.InterceptSessionShell(fake_session_shell_.GetOnCreateHandler(),
                                  {.sandbox_services = {"fuchsia.modular.SessionShellContext",
                                                        "fuchsia.modular.PuppetMaster"}});
    builder.BuildAndRun(test_harness());

    // Wait for our session shell to start.
    RunLoopUntil([&] { return fake_session_shell_.is_running(); });
  }

  modular::testing::FakeSessionShell fake_session_shell_;
};

TEST_F(SessionShellTest, GetPackageName) {
  fuchsia::modular::testing::TestHarnessSpec spec;
  test_harness()->Run(std::move(spec));

  fuchsia::modular::ComponentContextPtr component_context;
  fuchsia::modular::testing::ModularService svc;
  svc.set_component_context(component_context.NewRequest());
  test_harness()->ConnectToModularService(std::move(svc));

  bool got_name = false;
  component_context->GetPackageName([&got_name](fidl::StringPtr name) {
    EXPECT_THAT(name, Not(IsNull()));
    got_name = true;
  });

  RunLoopUntil([&] { return got_name; });
}

TEST_F(SessionShellTest, GetStoryInfoNonexistentStory) {
  RunHarnessAndInterceptSessionShell();

  fuchsia::modular::StoryProvider* story_provider = fake_session_shell_.story_provider();
  ASSERT_TRUE(story_provider != nullptr);

  bool tried_get_story_info = false;
  story_provider->GetStoryInfo2("X",
                                [&tried_get_story_info](fuchsia::modular::StoryInfo2 story_info) {
                                  EXPECT_TRUE(story_info.IsEmpty());
                                  tried_get_story_info = true;
                                });

  RunLoopUntil([&] { return tried_get_story_info; });
}

TEST_F(SessionShellTest, GetLink) {
  RunHarnessAndInterceptSessionShell();

  fuchsia::modular::SessionShellContext* session_shell_context;
  session_shell_context = fake_session_shell_.session_shell_context();
  ASSERT_TRUE(session_shell_context != nullptr);

  fuchsia::modular::LinkPtr session_shell_link;
  session_shell_context->GetLink(session_shell_link.NewRequest());
  bool called_get_link = false;
  session_shell_link->Get(nullptr, [&called_get_link](std::unique_ptr<fuchsia::mem::Buffer> value) {
    called_get_link = true;
  });

  RunLoopUntil([&] { return called_get_link; });
}

TEST_F(SessionShellTest, GetStoriesEmpty) {
  RunHarnessAndInterceptSessionShell();

  fuchsia::modular::StoryProvider* story_provider = fake_session_shell_.story_provider();
  ASSERT_TRUE(story_provider != nullptr);

  bool called_get_stories = false;
  story_provider->GetStories2(
      nullptr, [&called_get_stories](const std::vector<fuchsia::modular::StoryInfo2>& stories) {
        EXPECT_THAT(stories, testing::IsEmpty());
        called_get_stories = true;
      });

  RunLoopUntil([&] { return called_get_stories; });
}

TEST_F(SessionShellTest, StartAndStopStoryWithExtraInfoMod) {
  RunHarnessAndInterceptSessionShell();

  // Create a new story using PuppetMaster and launch a new story shell,
  // including a mod with extra info.
  fuchsia::modular::PuppetMasterPtr puppet_master;
  fuchsia::modular::StoryPuppetMasterPtr story_master;

  fuchsia::modular::testing::ModularService svc;
  svc.set_puppet_master(puppet_master.NewRequest());
  test_harness()->ConnectToModularService(std::move(svc));

  fuchsia::modular::StoryProvider* story_provider = fake_session_shell_.story_provider();
  ASSERT_TRUE(story_provider != nullptr);
  const char kStoryId[] = "my_story";

  // Have the mock session_shell record the sequence of story states it sees,
  // and confirm that it only sees the correct story id.
  std::vector<StoryState> sequence_of_story_states;
  modular::testing::SimpleStoryProviderWatcher watcher;
  watcher.set_on_change_2([&sequence_of_story_states, kStoryId](StoryInfo2 story_info,
                                                                StoryState story_state,
                                                                StoryVisibilityState _) {
    ASSERT_TRUE(story_info.has_id());
    EXPECT_EQ(story_info.id(), kStoryId);
    sequence_of_story_states.push_back(story_state);
  });
  watcher.Watch(story_provider, /*on_get_stories=*/nullptr);
  puppet_master->ControlStory(kStoryId, story_master.NewRequest());

  AddMod add_mod;
  add_mod.mod_name_transitional = "mod1";
  add_mod.intent.handler = kFakeModuleUrl;
  fuchsia::modular::IntentParameter param;
  param.name = "root";
  fsl::SizedVmo vmo;
  const std::string initial_json = R"({"created-with-info": true})";
  ASSERT_TRUE(fsl::VmoFromString(initial_json, &vmo));
  param.data.set_json(std::move(vmo).ToTransport());
  add_mod.intent.parameters.emplace();
  add_mod.intent.parameters->push_back(std::move(param));

  StoryCommand command;
  command.set_add_mod(std::move(add_mod));

  std::vector<StoryCommand> commands;
  commands.push_back(std::move(command));

  story_master->Enqueue(std::move(commands));
  bool execute_called = false;
  story_master->Execute(
      [&execute_called](fuchsia::modular::ExecuteResult result) { execute_called = true; });
  RunLoopUntil([&] { return execute_called; });

  // Stop the story. Check that the story went through the correct sequence
  // of states (see StoryState FIDL file for valid state transitions). Since we
  // started it, ran it, and stopped it, the sequence is STOPPED -> RUNNING ->
  // STOPPING -> STOPPED.
  fuchsia::modular::StoryControllerPtr story_controller;
  story_provider->GetController(kStoryId, story_controller.NewRequest());
  bool stop_called = false;
  story_controller->Stop([&stop_called] { stop_called = true; });
  RunLoopUntil([&] { return stop_called; });
  // Run the loop until there are the expected number of state changes;
  // having called Stop() is not enough to guarantee seeing all updates.
  RunLoopUntil([&] { return sequence_of_story_states.size() == 4; });
  EXPECT_THAT(sequence_of_story_states,
              testing::ElementsAre(StoryState::STOPPED, StoryState::RUNNING, StoryState::STOPPING,
                                   StoryState::STOPPED));
}

TEST_F(SessionShellTest, StoryInfoBeforeAndAfterDelete) {
  RunHarnessAndInterceptSessionShell();

  // Create a new story using PuppetMaster and launch a new story shell.
  fuchsia::modular::PuppetMasterPtr puppet_master;
  fuchsia::modular::StoryPuppetMasterPtr story_master;

  fuchsia::modular::testing::ModularService svc;
  svc.set_puppet_master(puppet_master.NewRequest());
  test_harness()->ConnectToModularService(std::move(svc));

  fuchsia::modular::StoryProvider* story_provider = fake_session_shell_.story_provider();
  ASSERT_TRUE(story_provider != nullptr);
  const char kStoryId[] = "my_story";
  puppet_master->ControlStory(kStoryId, story_master.NewRequest());

  AddMod add_mod;
  add_mod.mod_name_transitional = "mod1";
  add_mod.intent.handler = kFakeModuleUrl;

  StoryCommand command;
  command.set_add_mod(std::move(add_mod));

  std::vector<StoryCommand> commands;
  commands.push_back(std::move(command));

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

  bool execute_and_get_story_info_called = false;
  story_master->Execute([&execute_and_get_story_info_called, kStoryId,
                         story_provider](fuchsia::modular::ExecuteResult result) {
    // Verify that the newly created story returns something for
    // GetStoryInfo().
    story_provider->GetStoryInfo2(kStoryId, [&execute_and_get_story_info_called,
                                             kStoryId](fuchsia::modular::StoryInfo2 story_info) {
      ASSERT_TRUE(story_info.has_id());
      EXPECT_EQ(story_info.id(), kStoryId);
      execute_and_get_story_info_called = true;
    });
  });
  RunLoopUntil([&] { return execute_and_get_story_info_called; });

  // Delete the story and confirm that the story info is null now.
  bool delete_called = false;
  puppet_master->DeleteStory(kStoryId, [&delete_called, kStoryId, story_provider] {
    story_provider->GetStoryInfo2(kStoryId, [](fuchsia::modular::StoryInfo2 story_info) {
      EXPECT_TRUE(story_info.IsEmpty());
    });
    delete_called = true;
  });
  RunLoopUntil([&] { return delete_called; });
}

TEST_F(SessionShellTest, KindOfProtoStoryNotInStoryList) {
  RunHarnessAndInterceptSessionShell();

  // Create a new story using PuppetMaster and launch a new story shell,
  // adding the kind of proto option.
  fuchsia::modular::PuppetMasterPtr puppet_master;
  fuchsia::modular::StoryPuppetMasterPtr story_master;

  fuchsia::modular::testing::ModularService svc;
  svc.set_puppet_master(puppet_master.NewRequest());
  test_harness()->ConnectToModularService(std::move(svc));

  fuchsia::modular::StoryProvider* story_provider = fake_session_shell_.story_provider();
  ASSERT_TRUE(story_provider != nullptr);

  const char kStoryId[] = "my_story";
  puppet_master->ControlStory(kStoryId, story_master.NewRequest());

  fuchsia::modular::StoryOptions story_options;
  story_options.kind_of_proto_story = true;
  story_master->SetCreateOptions(std::move(story_options));

  bool called_get_stories = false;
  story_master->Execute([&called_get_stories,
                         story_provider](fuchsia::modular::ExecuteResult result) {
    // Confirm that even after the story is created, GetStories() returns
    // empty.
    story_provider->GetStories2(
        nullptr, [&called_get_stories](const std::vector<fuchsia::modular::StoryInfo2>& stories) {
          EXPECT_THAT(stories, testing::IsEmpty());
          called_get_stories = true;
        });
  });

  RunLoopUntil([&] { return called_get_stories; });
}

TEST_F(SessionShellTest, AttachesAndDetachesView) {
  RunHarnessAndInterceptSessionShell();

  // Create a new story using PuppetMaster and start a new story shell.
  // Confirm that AttachView() is called.
  fuchsia::modular::PuppetMasterPtr puppet_master;
  fuchsia::modular::StoryPuppetMasterPtr story_master;

  fuchsia::modular::testing::ModularService svc;
  svc.set_puppet_master(puppet_master.NewRequest());
  test_harness()->ConnectToModularService(std::move(svc));

  fuchsia::modular::StoryProvider* story_provider = fake_session_shell_.story_provider();
  ASSERT_TRUE(story_provider != nullptr);

  const char kStoryId[] = "my_story";
  // Have the mock session_shell record the sequence of story states it sees,
  // and confirm that it only sees the correct story id.
  std::vector<StoryState> sequence_of_story_states;
  modular::testing::SimpleStoryProviderWatcher watcher;
  watcher.set_on_change_2([&sequence_of_story_states, kStoryId](StoryInfo2 story_info,
                                                                StoryState story_state,
                                                                StoryVisibilityState _) {
    EXPECT_TRUE(story_info.has_id());
    EXPECT_EQ(story_info.id(), kStoryId);
    sequence_of_story_states.push_back(story_state);
  });
  watcher.Watch(story_provider, /*on_get_stories=*/nullptr);
  puppet_master->ControlStory(kStoryId, story_master.NewRequest());

  AddMod add_mod;
  add_mod.mod_name_transitional = "mod1";
  add_mod.intent.handler = kFakeModuleUrl;

  StoryCommand command;
  command.set_add_mod(std::move(add_mod));

  std::vector<StoryCommand> commands;
  commands.push_back(std::move(command));

  story_master->Enqueue(std::move(commands));
  story_master->Execute([](fuchsia::modular::ExecuteResult result) {});

  bool called_attach_view = false;
  fake_session_shell_.set_on_attach_view(
      [&called_attach_view](ViewIdentifier) { called_attach_view = true; });

  RunLoopUntil([&] { return called_attach_view; });

  // Stop the story. Confirm that:
  //  a. DetachView() was called.
  //  b. The story went through the correct sequence
  // of states (see StoryState FIDL file for valid state transitions). Since we
  // started it, ran it, and stopped it, the sequence is STOPPED -> RUNNING ->
  // STOPPING -> STOPPED.
  bool called_detach_view = false;
  fake_session_shell_.set_on_detach_view(
      [&called_detach_view](ViewIdentifier) { called_detach_view = true; });
  fuchsia::modular::StoryControllerPtr story_controller;
  story_provider->GetController(kStoryId, story_controller.NewRequest());
  bool stop_called = false;
  story_controller->Stop([&stop_called] { stop_called = true; });
  RunLoopUntil([&] { return stop_called; });
  // Run the loop until there are the expected number of state changes;
  // having called Stop() is not enough to guarantee seeing all updates.
  RunLoopUntil([&] { return sequence_of_story_states.size() == 4; });
  EXPECT_TRUE(called_detach_view);
  EXPECT_THAT(sequence_of_story_states,
              testing::ElementsAre(StoryState::STOPPED, StoryState::RUNNING, StoryState::STOPPING,
                                   StoryState::STOPPED));
}

TEST_F(SessionShellTest, StoryStopDoesntWaitOnDetachView) {
  RunHarnessAndInterceptSessionShell();

  // Create a new story using PuppetMaster and start a new story shell.
  // Confirm that AttachView() is called.
  fuchsia::modular::PuppetMasterPtr puppet_master;
  fuchsia::modular::StoryPuppetMasterPtr story_master;

  fuchsia::modular::testing::ModularService svc;
  svc.set_puppet_master(puppet_master.NewRequest());
  test_harness()->ConnectToModularService(std::move(svc));

  fuchsia::modular::StoryProvider* story_provider = fake_session_shell_.story_provider();
  ASSERT_TRUE(story_provider != nullptr);
  const char kStoryId[] = "my_story";

  // Have the mock session_shell record the sequence of story states it sees,
  // and confirm that it only sees the correct story id.
  std::vector<StoryState> sequence_of_story_states;
  modular::testing::SimpleStoryProviderWatcher watcher;
  watcher.set_on_change_2([&sequence_of_story_states, kStoryId](StoryInfo2 story_info,
                                                                StoryState story_state,
                                                                StoryVisibilityState _) {
    EXPECT_TRUE(story_info.has_id());
    EXPECT_EQ(story_info.id(), kStoryId);
    sequence_of_story_states.push_back(story_state);
  });
  watcher.Watch(story_provider, /*on_get_stories=*/nullptr);

  puppet_master->ControlStory(kStoryId, story_master.NewRequest());

  AddMod add_mod;
  add_mod.mod_name_transitional = "mod1";
  add_mod.intent.handler = kFakeModuleUrl;

  StoryCommand command;
  command.set_add_mod(std::move(add_mod));

  std::vector<StoryCommand> commands;
  commands.push_back(std::move(command));

  story_master->Enqueue(std::move(commands));
  story_master->Execute([](fuchsia::modular::ExecuteResult result) {});

  bool called_attach_view = false;
  fake_session_shell_.set_on_attach_view(
      [&called_attach_view](ViewIdentifier) { called_attach_view = true; });

  RunLoopUntil([&] { return called_attach_view; });

  // Stop the story. Confirm that:
  //  a. The story stopped, even though it didn't see the DetachView() response
  //   (it was artificially delayed for 1hr).
  //  b. The story went through the correct sequence of states (see StoryState
  //   FIDL file for valid state transitions). Since we started it, ran it, and
  //   stopped it, the sequence is STOPPED -> RUNNING -> STOPPING -> STOPPED.
  fake_session_shell_.set_detach_delay(zx::sec(60 * 60));
  fuchsia::modular::StoryControllerPtr story_controller;
  story_provider->GetController(kStoryId, story_controller.NewRequest());
  bool stop_called = false;
  story_controller->Stop([&stop_called] { stop_called = true; });

  RunLoopUntil([&] { return stop_called; });
  // Run the loop until there are the expected number of state changes;
  // having called Stop() is not enough to guarantee seeing all updates.
  RunLoopUntil([&] { return sequence_of_story_states.size() == 4; });
  EXPECT_THAT(sequence_of_story_states,
              testing::ElementsAre(StoryState::STOPPED, StoryState::RUNNING, StoryState::STOPPING,
                                   StoryState::STOPPED));
}

TEST_F(SessionShellTest, GetStoryInfo2HasId) {
  RunHarnessAndInterceptSessionShell();

  // Create a new story using PuppetMaster and launch a new story shell.
  fuchsia::modular::PuppetMasterPtr puppet_master;
  fuchsia::modular::StoryPuppetMasterPtr story_master;

  fuchsia::modular::testing::ModularService svc;
  svc.set_puppet_master(puppet_master.NewRequest());
  test_harness()->ConnectToModularService(std::move(svc));

  fuchsia::modular::StoryProvider* story_provider = fake_session_shell_.story_provider();
  ASSERT_TRUE(story_provider != nullptr);
  const char kStoryId[] = "my_story";
  puppet_master->ControlStory(kStoryId, story_master.NewRequest());

  AddMod add_mod;
  add_mod.mod_name_transitional = "mod1";
  add_mod.intent.handler = kFakeModuleUrl;

  StoryCommand command;
  command.set_add_mod(std::move(add_mod));

  std::vector<StoryCommand> commands;
  commands.push_back(std::move(command));

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

  bool execute_and_get_story_info_called = false;
  story_master->Execute([&execute_and_get_story_info_called, kStoryId,
                         story_provider](fuchsia::modular::ExecuteResult result) {
    // Verify that the newly created story returns something for
    // GetStoryInfo2().
    story_provider->GetStoryInfo2(kStoryId, [&execute_and_get_story_info_called,
                                             kStoryId](fuchsia::modular::StoryInfo2 story_info) {
      EXPECT_FALSE(story_info.IsEmpty());
      EXPECT_TRUE(story_info.has_id());
      EXPECT_EQ(story_info.id(), kStoryId);
      execute_and_get_story_info_called = true;
    });
  });
  RunLoopUntil([&] { return execute_and_get_story_info_called; });
}

TEST_F(SessionShellTest, GetStories2ReturnsStoryInfo) {
  RunHarnessAndInterceptSessionShell();

  // Create a new story using PuppetMaster and launch a new story shell.
  fuchsia::modular::PuppetMasterPtr puppet_master;
  fuchsia::modular::StoryPuppetMasterPtr story_master;

  fuchsia::modular::testing::ModularService svc;
  svc.set_puppet_master(puppet_master.NewRequest());
  test_harness()->ConnectToModularService(std::move(svc));

  fuchsia::modular::StoryProvider* story_provider = fake_session_shell_.story_provider();
  ASSERT_TRUE(story_provider != nullptr);
  const char kStoryId[] = "my_story";
  puppet_master->ControlStory(kStoryId, story_master.NewRequest());

  AddMod add_mod;
  add_mod.mod_name_transitional = "mod1";
  add_mod.intent.handler = kFakeModuleUrl;

  StoryCommand command;
  command.set_add_mod(std::move(add_mod));

  std::vector<StoryCommand> commands;
  commands.push_back(std::move(command));

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

  bool execute_and_get_stories_called = false;
  story_master->Execute([&execute_and_get_stories_called, kStoryId,
                         story_provider](fuchsia::modular::ExecuteResult result) {
    // Verify that GetStories2 returns the StoryInfo2 for the newly created story
    story_provider->GetStories2(/*watcher=*/nullptr,
                                [&execute_and_get_stories_called,
                                 kStoryId](std::vector<fuchsia::modular::StoryInfo2> story_infos) {
                                  EXPECT_FALSE(story_infos.empty());
                                  const auto& story_info = story_infos.at(0);
                                  EXPECT_FALSE(story_info.IsEmpty());
                                  EXPECT_TRUE(story_info.has_id());
                                  EXPECT_EQ(story_info.id(), kStoryId);
                                  execute_and_get_stories_called = true;
                                });
  });
  RunLoopUntil([&] { return execute_and_get_stories_called; });
}

TEST_F(SessionShellTest, OnChange2ReturnsStoryInfo2) {
  RunHarnessAndInterceptSessionShell();

  // Create a new story using PuppetMaster and start a new story shell.
  fuchsia::modular::PuppetMasterPtr puppet_master;
  fuchsia::modular::StoryPuppetMasterPtr story_master;

  fuchsia::modular::testing::ModularService svc;
  svc.set_puppet_master(puppet_master.NewRequest());
  test_harness()->ConnectToModularService(std::move(svc));

  fuchsia::modular::StoryProvider* story_provider = fake_session_shell_.story_provider();
  ASSERT_TRUE(story_provider != nullptr);

  const char kStoryId[] = "my_story";

  // Once the story is created, OnChange2 should be called with a StoryInfo2 that has the story ID.
  bool called_on_change_2 = false;
  modular::testing::SimpleStoryProviderWatcher watcher;
  watcher.set_on_change_2([&called_on_change_2, kStoryId](StoryInfo2 story_info, StoryState _,
                                                          StoryVisibilityState __) {
    EXPECT_TRUE(story_info.has_id());
    EXPECT_EQ(story_info.id(), kStoryId);
    called_on_change_2 = true;
  });
  watcher.Watch(story_provider, /*on_get_stories=*/nullptr);

  puppet_master->ControlStory(kStoryId, story_master.NewRequest());

  AddMod add_mod;
  add_mod.mod_name_transitional = "mod1";
  add_mod.intent.handler = kFakeModuleUrl;

  StoryCommand command;
  command.set_add_mod(std::move(add_mod));

  std::vector<StoryCommand> commands;
  commands.push_back(std::move(command));

  story_master->Enqueue(std::move(commands));
  story_master->Execute([](fuchsia::modular::ExecuteResult result) {});

  RunLoopUntil([&] { return called_on_change_2; });
}

}  // namespace
