// Copyright 2017 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 "peridot/bin/context_engine/context_repository.h"

#include <fuchsia/modular/cpp/fidl.h>
#include <lib/context/cpp/context_helper.h>
#include <lib/context/cpp/context_metadata_builder.h>
#include <lib/context/cpp/formatting.h>
#include <lib/fidl/cpp/clone.h>
#include <lib/fidl/cpp/optional.h>

#include "gtest/gtest.h"

using maxwell::ContextMetadataBuilder;

namespace modular {
namespace {

TEST(ContextGraph, GetChildrenRecursive_GetAncestors) {
  ContextGraph graph;

  graph.AddEdge("a", "b");
  graph.AddEdge("b", "c");
  graph.AddEdge("b", "d");

  auto children = graph.GetChildrenRecursive("b");
  EXPECT_EQ(2lu, children.size());
  EXPECT_TRUE(children.find("c") != children.end());
  EXPECT_TRUE(children.find("d") != children.end());

  children = graph.GetChildrenRecursive("a");
  EXPECT_EQ(3lu, children.size());
  EXPECT_TRUE(children.find("b") != children.end());
  EXPECT_TRUE(children.find("c") != children.end());
  EXPECT_TRUE(children.find("d") != children.end());

  auto ancestors = graph.GetAncestors("c");
  EXPECT_EQ(2lu, ancestors.size());
  EXPECT_EQ("a", ancestors[0]);
  EXPECT_EQ("b", ancestors[1]);
}

class ContextRepositoryTest : public ::testing::Test {
 public:
  ContextRepositoryTest() {}

 protected:
  ContextRepository repository_;
};

class TestListener : public fuchsia::modular::ContextListener {
 public:
  fuchsia::modular::ContextUpdatePtr last_update;

  void OnContextUpdate(fuchsia::modular::ContextUpdate update) override {
    last_update = fidl::MakeOptional(std::move(update));
  }

  void reset() { last_update.reset(); }
};

fuchsia::modular::ContextValue CreateValue(
    fuchsia::modular::ContextValueType type, const std::string& content) {
  fuchsia::modular::ContextValue value;
  value.type = type;
  value.content = content;
  return value;
}

fuchsia::modular::ContextValue CreateValue(
    fuchsia::modular::ContextValueType type, const std::string& content,
    fuchsia::modular::ContextMetadata meta) {
  fuchsia::modular::ContextValue value;
  value.type = type;
  value.content = content;
  value.meta = std::move(meta);
  return value;
}

}  // namespace

TEST_F(ContextRepositoryTest, GetAddUpdateRemove) {
  // This test ensures that we can do basic, synchronous add/update/remove/get
  // operations.

  // Show that when we set values, we can get them back.
  auto id1 = repository_.Add(
      CreateValue(fuchsia::modular::ContextValueType::ENTITY, "content"));
  auto value1 = repository_.Get(id1);
  ASSERT_TRUE(value1);
  EXPECT_EQ(fuchsia::modular::ContextValueType::ENTITY, value1->type);
  EXPECT_EQ("content", value1->content);

  // Setting another value doesn't affect the original value.
  auto id2 = repository_.Add(
      CreateValue(fuchsia::modular::ContextValueType::ENTITY, "content2"));
  auto value2 = repository_.Get(id2);
  ASSERT_TRUE(value2);
  EXPECT_EQ("content2", value2->content);
  value1 = repository_.Get(id1);
  ASSERT_TRUE(value1);
  EXPECT_EQ(fuchsia::modular::ContextValueType::ENTITY, value1->type);
  EXPECT_EQ("content", value1->content);

  // Let's create metadata.
  auto id3 = repository_.Add(
      CreateValue(fuchsia::modular::ContextValueType::ENTITY, "content3",
                  ContextMetadataBuilder().SetStoryId("id3story").Build()));
  auto value3 = repository_.Get(id3);
  ASSERT_TRUE(value3);
  EXPECT_EQ("content3", value3->content);
  ASSERT_TRUE(value3->meta.story);
  EXPECT_EQ("id3story", value3->meta.story->id);

  // Update one of the previous values.
  repository_.Update(
      id2,
      CreateValue(fuchsia::modular::ContextValueType::ENTITY, "new content2",
                  ContextMetadataBuilder().SetStoryId("id2story").Build()));
  value2 = repository_.Get(id2);
  ASSERT_TRUE(value2);
  ASSERT_TRUE(value2->meta.story);
  EXPECT_EQ("id2story", value2->meta.story->id);
  EXPECT_EQ("new content2", value2->content);

  // Now remove id3.
  repository_.Remove(id3);
  EXPECT_FALSE(repository_.Get(id3));
  EXPECT_TRUE(repository_.Get(id1));
  EXPECT_TRUE(repository_.Get(id2));

  // And the others.
  repository_.Remove(id1);
  repository_.Remove(id2);
  EXPECT_FALSE(repository_.Get(id1));
  EXPECT_FALSE(repository_.Get(id2));
}

TEST_F(ContextRepositoryTest, ValuesInheritMetadata) {
  // When a value is added as a child of another value, the child inherits the
  // metadata of its parent.
  auto meta1 = ContextMetadataBuilder().SetStoryId("id").Build();
  auto id1 = repository_.Add(CreateValue(
      fuchsia::modular::ContextValueType::STORY, "s", std::move(meta1)));

  auto meta2 = ContextMetadataBuilder().SetModuleUrl("url").Build();
  auto id2 = repository_.Add(
      id1, CreateValue(fuchsia::modular::ContextValueType::MODULE, "m",
                       std::move(meta2)));

  auto value1 = repository_.GetMerged(id1);
  ASSERT_TRUE(value1);
  // value1's metadata shouldn't have changed.
  ASSERT_TRUE(value1->meta.story);
  EXPECT_EQ("id", value1->meta.story->id);
  ASSERT_FALSE(value1->meta.mod);

  auto value2 = repository_.GetMerged(id2);
  ASSERT_TRUE(value2);
  // value2's metadata should combine both value1's and value2's.
  ASSERT_TRUE(value2->meta.story);
  EXPECT_EQ("id", value2->meta.story->id);
  ASSERT_TRUE(value2->meta.mod);
  ASSERT_TRUE(value2->meta.mod->url);
  EXPECT_EQ("url", value2->meta.mod->url);

  // Changing the parent's metadata value should update the child's also.
  meta1 = fuchsia::modular::ContextMetadata();
  meta1.story = fuchsia::modular::StoryMetadata::New();
  meta1.story->id = "newid";
  repository_.Update(id1, CreateValue(fuchsia::modular::ContextValueType::STORY,
                                      "s", std::move(meta1)));
  value2 = repository_.GetMerged(id2);
  ASSERT_TRUE(value2);
  ASSERT_TRUE(value2->meta.story);
  EXPECT_EQ("newid", value2->meta.story->id);
  ASSERT_TRUE(value2->meta.mod);
  ASSERT_TRUE(value2->meta.mod->url);
  EXPECT_EQ("url", value2->meta.mod->url);

  // If a parent contains metadata that the child also contains (they both have
  // 'mod' metadata), the parent's takes precendence.
  meta1 =
      ContextMetadataBuilder(std::move(meta1)).SetModuleUrl("override").Build();
  repository_.Update(id1, CreateValue(fuchsia::modular::ContextValueType::STORY,
                                      "s", std::move(meta1)));
  value2 = repository_.GetMerged(id2);
  ASSERT_TRUE(value2);
  ASSERT_FALSE(value2->meta.story);
  ASSERT_TRUE(value2->meta.mod);
  ASSERT_EQ("override", value2->meta.mod->url);
}

TEST_F(ContextRepositoryTest, ListenersGetUpdates) {
  // We want to test these subscription behaviors.
  // 1) A value is added but doesn't match our subscription.
  //    a) It's the wrong type (ie, STORY vs ENTITY)
  //    b) Its metadata doesn't match.
  // 2) A value is added that matches our existing subscription.
  // 3) A value is updated that newly matches our subscription.
  // 4) When a value is removed, it is no longer returned.

  // (1)
  fuchsia::modular::ContextQuery query;
  fuchsia::modular::ContextSelector selector;
  selector.type = fuchsia::modular::ContextValueType::ENTITY;
  selector.meta = ContextMetadataBuilder().SetEntityTopic("topic").BuildPtr();
  AddToContextQuery(&query, "a", std::move(selector));

  TestListener listener;
  repository_.AddSubscription(std::move(query), &listener,
                              fuchsia::modular::SubscriptionDebugInfo());
  auto maybe_result = TakeContextValue(listener.last_update.get(), "a");
  ASSERT_TRUE(maybe_result.has_value());
  EXPECT_TRUE(maybe_result.value()->empty());
  listener.reset();

  // (a)
  fuchsia::modular::ContextValue value;
  value.type = fuchsia::modular::ContextValueType::STORY;
  value.content = "no match";
  value.meta = ContextMetadataBuilder().SetEntityTopic("topic").Build();
  repository_.Add(std::move(value));
  // No new update because nothing changed for our subscription.
  EXPECT_FALSE(listener.last_update);
  listener.reset();

  // (b)
  value = fuchsia::modular::ContextValue();
  value.type = fuchsia::modular::ContextValueType::ENTITY;
  value.content = "no match yet";
  value.meta = ContextMetadataBuilder().SetEntityTopic("not the topic").Build();
  auto id = repository_.Add(std::move(value));  // Save id for later.
  // No new update because nothing changed for our subscription.
  EXPECT_FALSE(listener.last_update);
  listener.reset();

  // (2)
  value = fuchsia::modular::ContextValue();
  value.type = fuchsia::modular::ContextValueType::ENTITY;
  value.content = "match";
  value.meta = ContextMetadataBuilder().SetEntityTopic("topic").Build();
  repository_.Add(std::move(value));
  maybe_result = TakeContextValue(listener.last_update.get(), "a");
  ASSERT_TRUE(maybe_result.has_value());
  {
    auto& result = maybe_result.value();
    EXPECT_EQ(1lu, result->size());
    EXPECT_EQ("match", result->at(0).content);
  }
  listener.reset();

  // (3)
  value = fuchsia::modular::ContextValue();
  value.type = fuchsia::modular::ContextValueType::ENTITY;
  value.content = "now it matches";
  // Add more metadata than the query is looking for. It shouldn't affect
  // the query, because it doesn't express any constraint on 'type'.
  value.meta = ContextMetadataBuilder()
                   .SetEntityTopic("topic")
                   .AddEntityType("type1")
                   .AddEntityType("type2")
                   .Build();
  repository_.Update(id, std::move(value));
  ASSERT_TRUE(listener.last_update);
  maybe_result = TakeContextValue(listener.last_update.get(), "a");
  ASSERT_TRUE(maybe_result.has_value());
  {
    auto& result = maybe_result.value();
    EXPECT_EQ(2lu, result->size());
    EXPECT_EQ("now it matches", result->at(0).content);
    EXPECT_EQ("match", result->at(1).content);
  }
  listener.reset();

  // (4)
  repository_.Remove(id);
  ASSERT_TRUE(listener.last_update);
  maybe_result = TakeContextValue(listener.last_update.get(), "a");
  ASSERT_TRUE(maybe_result.has_value());
  {
    auto& result = maybe_result.value();
    EXPECT_EQ(1lu, result->size());
    EXPECT_EQ("match", result->at(0).content);
  }
  listener.reset();
}

TEST_F(ContextRepositoryTest, ListenersGetUpdates_WhenParentsUpdated) {
  // We should see updates to listeners when an update to a node's
  // parent causes that node to be matched by a query.
  fuchsia::modular::ContextQuery query;
  fuchsia::modular::ContextSelector selector;
  selector.type = fuchsia::modular::ContextValueType::ENTITY;
  selector.meta = ContextMetadataBuilder().SetStoryId("match").BuildPtr();
  AddToContextQuery(&query, "a", std::move(selector));

  TestListener listener;
  repository_.AddSubscription(std::move(query), &listener,
                              fuchsia::modular::SubscriptionDebugInfo());
  ASSERT_TRUE(listener.last_update);
  auto maybe_result = TakeContextValue(listener.last_update.get(), "a");
  ASSERT_TRUE(maybe_result.has_value());
  {
    auto& result = maybe_result.value();
    EXPECT_EQ(0lu, result->size());
    listener.reset();
  }

  // Add a Story value.
  fuchsia::modular::ContextValue story_value;
  story_value.type = fuchsia::modular::ContextValueType::STORY;
  story_value.meta = ContextMetadataBuilder().SetStoryId("no match").Build();
  fuchsia::modular::ContextValue first_story_value;
  fidl::Clone(story_value, &first_story_value);  // Save for later.
  auto story_value_id = repository_.Add(std::move(story_value));

  // Expect no update.
  EXPECT_FALSE(listener.last_update);

  // Add an fuchsia::modular::Entity node, but it still shouldn't match.
  fuchsia::modular::ContextValue entity_value;
  entity_value.type = fuchsia::modular::ContextValueType::ENTITY;
  entity_value.content = "content";
  repository_.Add(story_value_id, std::move(entity_value));

  // Still expect no update.
  EXPECT_FALSE(listener.last_update);

  // Update the story value so its metadata matches the query, and we should
  // see the entity value returned in our update.
  story_value = fuchsia::modular::ContextValue();
  story_value.type = fuchsia::modular::ContextValueType::STORY;
  story_value.meta = ContextMetadataBuilder().SetStoryId("match").Build();
  fuchsia::modular::ContextValue matching_story_value;
  fidl::Clone(story_value, &matching_story_value);  // Save for later.
  repository_.Update(story_value_id, std::move(story_value));

  ASSERT_TRUE(listener.last_update);
  maybe_result = TakeContextValue(listener.last_update.get(), "a");
  ASSERT_TRUE(maybe_result.has_value());
  {
    auto& result = maybe_result.value();
    EXPECT_EQ(1lu, result->size());
    EXPECT_EQ("content", result->at(0).content);
    // Make sure we adopted the parent metadata from the story node.
    ASSERT_TRUE(result->at(0).meta.story);
    EXPECT_EQ("match", result->at(0).meta.story->id);
  }
  listener.reset();

  // Set the value back to something that doesn't match, and we should get an
  // empty update.
  repository_.Update(story_value_id, std::move(first_story_value));
  ASSERT_TRUE(listener.last_update);
  maybe_result = TakeContextValue(listener.last_update.get(), "a");
  ASSERT_TRUE(maybe_result.has_value());
  EXPECT_EQ(0lu, maybe_result.value()->size());
  listener.reset();

  // Set it back to something that matched, and this time remove the value
  // entirely. We should observe it go away.
  repository_.Update(story_value_id, std::move(matching_story_value));
  ASSERT_TRUE(listener.last_update);
  maybe_result = TakeContextValue(listener.last_update.get(), "a");
  ASSERT_TRUE(maybe_result.has_value());
  EXPECT_EQ(1lu, maybe_result.value()->size());
  listener.reset();

  repository_.Remove(story_value_id);
  ASSERT_TRUE(listener.last_update);
  maybe_result = TakeContextValue(listener.last_update.get(), "a");
  ASSERT_TRUE(maybe_result.has_value());
  EXPECT_TRUE(maybe_result.value()->empty());
  listener.reset();
}

}  // namespace modular
