// 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/cpp/fidl.h>
#include <fuchsia/modular/testing/cpp/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fidl/cpp/optional.h>
#include <lib/inspect/testing/cpp/inspect.h>
#include <zircon/device/vfs.h>

#include <sdk/lib/inspect/testing/cpp/inspect.h>

#include "gmock/gmock.h"
#include "src/lib/files/glob.h"
#include "src/lib/fsl/vmo/strings.h"
#include "src/lib/fxl/strings/substitute.h"
#include "src/modular/lib/modular_config/modular_config_constants.h"
#include "src/modular/lib/modular_test_harness/cpp/fake_session_shell.h"
#include "src/modular/lib/modular_test_harness/cpp/test_harness_fixture.h"
#include "src/modular/lib/modular_test_harness/cpp/test_harness_impl.h"

namespace {

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 ::fxl::Substitute;
using inspect::testing::DoubleIs;
using inspect::testing::IntIs;
using inspect::testing::NameMatches;
using inspect::testing::NodeMatches;
using inspect::testing::PropertyList;
using inspect::testing::StringIs;
using testing::IsNull;
using testing::Not;

constexpr char kFakeModuleUrl[] = "fuchsia-pkg://example.com/FAKE_MODULE_PKG/fake_module.cmx";
constexpr char kSessionmgrInspectRootGlobPath[] =
    "/hub/r/mth_*_inspect/*/c/sessionmgr.cmx/*/out/diagnostics/root.inspect";
// The initial module's intent parameter data. This needs to be JSON formatted.
constexpr char kInitialIntentParameterData[] = "\"initial\"";
constexpr char kIntentAction[] = "action";
constexpr char kIntentParameterName[] = "intent_parameter";

class InspectSessionTest : public modular_testing::TestHarnessFixture {
 protected:
  InspectSessionTest()
      : fake_session_shell_(modular_testing::FakeSessionShell::CreateWithDefaultOptions()) {}

  void RunHarnessAndInterceptSessionShell() {
    fuchsia::modular::testing::TestHarnessSpec spec;
    spec.set_environment_suffix("inspect");
    modular_testing::TestHarnessBuilder builder(std::move(spec));
    builder.InterceptSessionShell(fake_session_shell_->BuildInterceptOptions());
    builder.BuildAndRun(test_harness());

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

  zx_status_t GetInspectVmo(zx::vmo* out_vmo) {
    files::Glob glob(kSessionmgrInspectRootGlobPath);
    if (glob.size() == 0) {
      return ZX_ERR_NOT_FOUND;
    }

    fuchsia::io::FileSyncPtr file;
    zx_status_t status;
    status = fdio_open(std::string(*glob.begin()).c_str(), ZX_FS_RIGHT_READABLE,
                       file.NewRequest().TakeChannel().release());
    if (status != ZX_OK) {
      return status;
    }

    EXPECT_TRUE(file.is_bound());

    fuchsia::io::NodeInfo info;
    auto get_status = file->Describe(&info);
    if (get_status != ZX_OK) {
      printf("get failed\n");
      return get_status;
    }

    if (!info.is_vmofile()) {
      printf("not a vmofile");
      return ZX_ERR_NOT_FOUND;
    }

    *out_vmo = std::move(info.vmofile().vmo);
    return ZX_OK;
  }
  fuchsia::modular::Intent CreateIntent(std::string handler, std::string parameter_name,
                                        std::string parameter_data) {
    fuchsia::modular::Intent intent;
    intent.handler = handler;
    intent.action = kIntentAction;

    fuchsia::modular::IntentParameter intent_parameter;
    intent_parameter.name = parameter_name;
    intent_parameter.data = fuchsia::modular::IntentParameterData();
    fsl::SizedVmo vmo;
    ZX_ASSERT(fsl::VmoFromString(parameter_data, &vmo));
    intent_parameter.data.set_json(std::move(vmo).ToTransport());
    intent.parameters.emplace();
    intent.parameters->push_back(std::move(intent_parameter));

    return intent;
  }

  std::unique_ptr<modular_testing::FakeSessionShell> fake_session_shell_;
};  // namespace

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

  void OnChange2(fit::function<void(fuchsia::modular::StoryInfo2)> on_change) {
    on_change_2_ = std::move(on_change);
  }

  void Watch(fuchsia::modular::StoryProvider* const story_provider) {
    story_provider->Watch(binding_.NewBinding());
  }

 private:
  // |fuchsia::modular::StoryProviderWatcher|
  void OnDelete(::std::string story_id) override {}

  // |fuchsia::modular::StoryProviderWatcher|
  void OnChange2(fuchsia::modular::StoryInfo2 story_info, fuchsia::modular::StoryState story_state,
                 fuchsia::modular::StoryVisibilityState story_visibility_state) override {
    on_change_2_(std::move(story_info));
    return;
  }

  fit::function<void(fuchsia::modular::StoryInfo2)> on_change_2_;
  fidl::Binding<fuchsia::modular::StoryProviderWatcher> binding_;
};

TEST_F(InspectSessionTest, NodeHierarchyNoStories) {
  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; });

  // Check the iquery node hierarchy is properly set up with only a root.
  zx::vmo vmo;
  ASSERT_EQ(ZX_OK, GetInspectVmo(&vmo));
  auto hierarchy = inspect::ReadFromVmo(std::move(vmo)).take_value();

  EXPECT_THAT(hierarchy,
              AllOf(inspect::testing::NodeMatches(inspect::testing::NameMatches("root"))));
}

TEST_F(InspectSessionTest, DefaultAgentsHierarchy) {
  fuchsia::modular::testing::TestHarnessSpec spec;
  spec.set_environment_suffix("inspect");
  modular_testing::TestHarnessBuilder builder(std::move(spec));
  builder.InterceptSessionShell(fake_session_shell_->BuildInterceptOptions());
  builder.BuildAndRun(test_harness());

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

  zx::vmo vmo;
  ASSERT_EQ(ZX_OK, GetInspectVmo(&vmo));
  auto hierarchy = inspect::ReadFromVmo(std::move(vmo)).take_value();
  EXPECT_THAT(hierarchy, (NodeMatches(NameMatches("root"))));

  const auto& child = hierarchy.children();
  ASSERT_THAT(child.size(), 1);
  EXPECT_THAT(child.at(0),
              NodeMatches(NameMatches(modular_testing::kSessionAgentFakeInterceptionUrl)));
}

TEST_F(InspectSessionTest, CheckNodeHierarchyStartAndStopStory) {
  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());

  auto text_story_annotation_value = fuchsia::modular::AnnotationValue{};
  text_story_annotation_value.set_text("test_value");

  auto text_story_annotation = fuchsia::modular::Annotation{
      .key = "test_key", .value = fidl::MakeOptional(std::move(text_story_annotation_value))};

  std::vector<fuchsia::modular::Annotation> story_annotations;
  story_annotations.push_back(std::move(text_story_annotation));
  bool done{false};
  story_master->Annotate(std::move(story_annotations),
                         [&](fuchsia::modular::StoryPuppetMaster_Annotate_Result result) {
                           EXPECT_FALSE(result.is_err());
                           done = true;
                         });
  RunLoopUntil([&] { return done; });

  // Watch for changes to the session.
  TestStoryProviderWatcher story_provider_watcher;
  story_provider_watcher.Watch(fake_session_shell_->story_provider());

  // Keep track of the focus timestamp that we receive for the story.
  std::vector<int64_t> last_focus_timestamps;
  story_provider_watcher.OnChange2([&](fuchsia::modular::StoryInfo2 story_info) {
    ASSERT_TRUE(story_info.has_id());
    ASSERT_TRUE(story_info.has_last_focus_time());
    ASSERT_EQ(kStoryId, story_info.id());
    last_focus_timestamps.push_back(story_info.last_focus_time());
  });

  // Story doesn't start unless it has a mod, so add a mod.
  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_called = false;
  story_master->Execute(
      [&execute_called](fuchsia::modular::ExecuteResult result) { execute_called = true; });
  RunLoopUntil([&] { return execute_called; });

  zx::vmo vmo_inspect;
  ASSERT_EQ(ZX_OK, GetInspectVmo(&vmo_inspect));
  auto hierarchy = inspect::ReadFromVmo(std::move(vmo_inspect)).take_value();
  EXPECT_THAT(hierarchy, (NodeMatches(NameMatches("root"))));

  const auto& children = hierarchy.children();
  // Contains 1 agent and 1 story
  ASSERT_THAT(children.size(), 2);
  EXPECT_THAT(children, Contains(NodeMatches(NameMatches("my_story"))));
  EXPECT_THAT(children.at(0), NodeMatches(AllOf(PropertyList(UnorderedElementsAre(
                                  IntIs("last_focus_time", last_focus_timestamps.back()),
                                  StringIs("annotation: test_key", "test_value"))))));

  bool story_deleted = false;
  puppet_master->DeleteStory(kStoryId, [&] { story_deleted = true; });

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

  // Check that a node is removed from the hierarchy when a story is removed.
  ASSERT_EQ(ZX_OK, GetInspectVmo(&vmo_inspect));

  hierarchy = inspect::ReadFromVmo(std::move(vmo_inspect)).take_value();
  EXPECT_THAT(hierarchy, AllOf(NodeMatches(NameMatches("root"))));
}

TEST_F(InspectSessionTest, CheckNodeHierarchyMods) {
  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";
  auto initial_module_intent =
      CreateIntent(kFakeModuleUrl, kIntentParameterName, kInitialIntentParameterData);
  add_mod.intent = std::move(initial_module_intent);

  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; });

  // Annotate the module.
  auto text_mod_annotation_value = fuchsia::modular::AnnotationValue{};
  text_mod_annotation_value.set_bytes({01});
  auto text_mod_annotation = fuchsia::modular::Annotation{
      .key = "text_key", .value = fidl::MakeOptional(fidl::Clone(text_mod_annotation_value))};
  std::vector<fuchsia::modular::Annotation> mod_annotations;
  mod_annotations.push_back(fidl::Clone(text_mod_annotation));

  bool annotate_done = false;
  story_master->AnnotateModule(
      "mod1", std::move(mod_annotations),
      [&](fuchsia::modular::StoryPuppetMaster_AnnotateModule_Result result) {
        EXPECT_FALSE(result.is_err());
        annotate_done = true;
      });
  RunLoopUntil([&] { return annotate_done && execute_called; });

  zx::vmo vmo_inspect;
  ASSERT_EQ(ZX_OK, GetInspectVmo(&vmo_inspect));
  auto hierarchy = inspect::ReadFromVmo(std::move(vmo_inspect)).take_value();
  EXPECT_THAT(hierarchy, (NodeMatches(NameMatches("root"))));

  const auto& child = hierarchy.children();
  ASSERT_THAT(child.size(), 2);

  EXPECT_THAT(child.at(0), NodeMatches(NameMatches("my_story")));

  const auto& grandchild = child.at(0).children();

  ASSERT_THAT(grandchild.size(), 1);
  EXPECT_THAT(grandchild.at(0), NodeMatches(NameMatches(kFakeModuleUrl)));
  EXPECT_THAT(grandchild.at(0),
              NodeMatches(AllOf(PropertyList(UnorderedElementsAre(
                  StringIs(modular_config::kInspectIsEmbedded, "False"),
                  StringIs(modular_config::kInspectModuleSource, "EXTERNAL"),
                  StringIs(modular_config::kInspectIntentHandler, kFakeModuleUrl),
                  StringIs(modular_config::kInspectIntentAction, "action"),
                  StringIs(modular_config::kInspectIsDeleted, "False"),
                  StringIs(modular_config::kInspectIntentParams, "name : intent_parameter "),
                  StringIs(modular_config::kInspectSurfaceRelationArrangement, "NONE"),
                  StringIs(modular_config::kInspectSurfaceRelationDependency, "NONE"),
                  DoubleIs(modular_config::kInspectSurfaceRelationEmphasis, 1.0),
                  StringIs(modular_config::kInspectModulePath, "mod1"),
                  StringIs("annotation: text_key", "bytes"))))));
}
}  // namespace
