// 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_writer_impl.h"

#include <memory>

#include <fuchsia/modular/cpp/fidl.h>
#include <lib/entity/cpp/json.h>
#include <lib/fidl/cpp/clone.h>
#include <lib/fit/defer.h>
#include <lib/fxl/functional/make_copyable.h>

#include "peridot/bin/context_engine/debug.h"
#include "rapidjson/document.h"

namespace modular {

ContextWriterImpl::ContextWriterImpl(
    const fuchsia::modular::ComponentScope& client_info,
    ContextRepository* const repository,
    fuchsia::modular::EntityResolver* const entity_resolver,
    fidl::InterfaceRequest<fuchsia::modular::ContextWriter> request)
    : binding_(this, std::move(request)),
      repository_(repository),
      entity_resolver_(entity_resolver),
      weak_factory_(this) {
  FXL_DCHECK(repository != nullptr);

  // Set up a query to the repository to get our parent id.
  if (client_info.is_module_scope()) {
    parent_value_selector_.type = fuchsia::modular::ContextValueType::MODULE;
    parent_value_selector_.meta = fuchsia::modular::ContextMetadata::New();
    parent_value_selector_.meta->story = fuchsia::modular::StoryMetadata::New();
    parent_value_selector_.meta->story->id =
        client_info.module_scope().story_id;
    parent_value_selector_.meta->mod = fuchsia::modular::ModuleMetadata::New();
    std::vector<std::string> module_path;
    fidl::Clone(client_info.module_scope().module_path, &module_path);
    parent_value_selector_.meta->mod->path = fidl::VectorPtr(std::move(module_path));
  }
}

ContextWriterImpl::~ContextWriterImpl() {}

namespace {

fidl::VectorPtr<std::string> Deprecated_GetTypesFromJsonEntity(
    const fidl::StringPtr& content) {
  // If the content has the @type attribute, take its contents and populate the
  // fuchsia::modular::EntityMetadata appropriately, overriding whatever is
  // there.
  std::vector<std::string> types;
  if (!ExtractEntityTypesFromJson(content, &types)) {
    FXL_LOG(WARNING) << "Invalid entity metadata in JSON value: " << content;
    return {};
  }

  return fidl::VectorPtr(types);
}

void MaybeFillEntityTypeMetadata(const std::vector<std::string>& types,
                                 fuchsia::modular::ContextValue& value) {
  if (value.type != fuchsia::modular::ContextValueType::ENTITY)
    return;

  if (!value.meta.entity) {
    value.meta.entity = fuchsia::modular::EntityMetadata::New();
  }
  value.meta.entity->type = fidl::VectorPtr(types);
}

bool MaybeFindParentValueId(ContextRepository* repository,
                            const fuchsia::modular::ContextSelector& selector,
                            ContextRepository::Id* out) {
  // There is technically a race condition here, since on construction, we
  // are given a fuchsia::modular::ComponentScope, which contains some metadata
  // to find a value in the context engine. It is the responsibility of the
  // story_info acquierer to actually create that value, so we query at
  // CreateValue()-time because it makes it less likely to hit the race
  // condition.
  //
  // This is only exercised when a Module publishes context explicitly,
  // something that we plan to disallow once Links speak in Entities, as then
  // Modules that wish to store context can simply write Entities into a new
  // link.
  auto ids = repository->Select(selector);
  if (ids.size() == 1) {
    *out = *ids.begin();
    return true;
  }
  return false;
}

}  // namespace

void ContextWriterImpl::CreateValue(
    fidl::InterfaceRequest<fuchsia::modular::ContextValueWriter> request,
    fuchsia::modular::ContextValueType type) {
  ContextRepository::Id parent_id;
  // We ignore the return value - if it returns false |parent_id| will stay
  // default-initialized.
  MaybeFindParentValueId(repository_, parent_value_selector_, &parent_id);
  auto ptr =
      new ContextValueWriterImpl(this, parent_id, type, std::move(request));
  AddContextValueWriter(ptr);
}

void ContextWriterImpl::AddContextValueWriter(ContextValueWriterImpl* ptr) {
  value_writer_storage_.emplace_back(ptr);
}

void ContextWriterImpl::DestroyContextValueWriter(ContextValueWriterImpl* ptr) {
  auto it = std::remove_if(
      value_writer_storage_.begin(), value_writer_storage_.end(),
      [ptr](const std::unique_ptr<ContextValueWriterImpl>& u_ptr) {
        return u_ptr.get() == ptr;
      });
  value_writer_storage_.erase(it, value_writer_storage_.end());
}

void ContextWriterImpl::WriteEntityTopic(std::string topic,
                                         fidl::StringPtr value) {
  auto activity =
      repository_->debug()->GetIdleWaiter()->RegisterOngoingActivity();

  if (!value) {
    // Remove this value.
    auto it = topic_value_ids_.find(topic);
    if (it != topic_value_ids_.end()) {
      repository_->Remove(it->second);
    }
    return;
  }

  GetEntityTypesFromEntityReference(
      value, [this, activity, topic,
              value](const std::vector<std::string>& types) {
        fuchsia::modular::ContextValue context_value;
        context_value.type = fuchsia::modular::ContextValueType::ENTITY;
        context_value.content = value;
        context_value.meta.entity = fuchsia::modular::EntityMetadata::New();
        context_value.meta.entity->topic = topic;
        context_value.meta.entity->type = fidl::VectorPtr(types);

        auto it = topic_value_ids_.find(topic);
        if (it == topic_value_ids_.end()) {
          ContextRepository::Id parent_id;
          ContextRepository::Id id;
          if (MaybeFindParentValueId(repository_, parent_value_selector_,
                                     &parent_id)) {
            id = repository_->Add(parent_id, std::move(context_value));
          } else {
            id = repository_->Add(std::move(context_value));
          }
          topic_value_ids_[topic] = id;
        } else {
          repository_->Update(it->second, std::move(context_value));
        }
      });
}

void ContextWriterImpl::GetEntityTypesFromEntityReference(
    const fidl::StringPtr& reference,
    std::function<void(const std::vector<std::string>&)> done) {
  auto activity =
      repository_->debug()->GetIdleWaiter()->RegisterOngoingActivity();

  // TODO(thatguy): This function could be re-used in multiple places. Move it
  // somewhere other places can reach it.
  std::unique_ptr<fuchsia::modular::EntityPtr> entity =
      std::make_unique<fuchsia::modular::EntityPtr>();
  entity_resolver_->ResolveEntity(reference, entity->NewRequest());

  auto fallback = fit::defer([done, reference] {
    // The contents of the fuchsia::modular::Entity value could be a deprecated
    // JSON fuchsia::modular::Entity, not an fuchsia::modular::Entity reference.
    done(Deprecated_GetTypesFromJsonEntity(reference));
  });

  (*entity)->GetTypes(fxl::MakeCopyable(
      [this, activity, id = entities_.GetId(&entity), done = std::move(done),
       fallback = std::move(fallback)](
          const std::vector<std::string>& types) mutable {
        done(types);
        fallback.cancel();
        entities_.erase(id);
      }));

  entities_.emplace(std::move(entity));
}

ContextValueWriterImpl::ContextValueWriterImpl(
    ContextWriterImpl* writer, const ContextRepository::Id& parent_id,
    fuchsia::modular::ContextValueType type,
    fidl::InterfaceRequest<fuchsia::modular::ContextValueWriter> request)
    : binding_(this, std::move(request)),
      writer_(writer),
      parent_id_(parent_id),
      type_(type),
      value_id_(Future<ContextRepository::Id>::Create(
          "ContextValueWriterImpl.value_id_")),
      weak_factory_(this) {
  binding_.set_error_handler(
      [this](zx_status_t status) { writer_->DestroyContextValueWriter(this); });

  // When |value_id_| completes, we want to remember it so that we know what
  // branch to execute in Set().
  value_id_->WeakConstThen(
      weak_factory_.GetWeakPtr(),
      [this](const ContextRepository::Id& id) { have_value_id_ = true; });
}

ContextValueWriterImpl::~ContextValueWriterImpl() {
  // It's possible we haven't actually created a value in |repository_| yet.
  // Either we have, and |value_id_| is complete and this callback will be
  // called synchronously, or we haven't and |value_id_| will go out of scope
  // with *this goes out of scope.
  value_id_->WeakConstThen(weak_factory_.GetWeakPtr(),
                           [this](const ContextRepository::Id& id) {
                             // Remove the value.
                             writer_->repository()->Remove(id);
                           });
}

void ContextValueWriterImpl::CreateChildValue(
    fidl::InterfaceRequest<fuchsia::modular::ContextValueWriter> request,
    fuchsia::modular::ContextValueType type) {
  // We can't create a child value until this value has an ID.
  value_id_->WeakConstThen(
      weak_factory_.GetWeakPtr(),
      fxl::MakeCopyable([this, request = std::move(request),
                         type](const ContextRepository::Id& value_id) mutable {
        auto ptr = new ContextValueWriterImpl(writer_, value_id, type,
                                              std::move(request));
        writer_->AddContextValueWriter(ptr);
      }));
}

void ContextValueWriterImpl::Set(
    fidl::StringPtr content, fuchsia::modular::ContextMetadataPtr metadata) {
  auto activity = writer_->repository()
                      ->debug()
                      ->GetIdleWaiter()
                      ->RegisterOngoingActivity();

  auto done_getting_types =
      [weak_this = weak_factory_.GetWeakPtr(), activity, content,
       metadata = std::move(metadata)](
          const std::vector<std::string>& entity_types) mutable {
        if (!weak_this)
          return;

        if (!weak_this->have_value_id_) {
          // We're creating this value for the first time.
          fuchsia::modular::ContextValue value;
          value.type = weak_this->type_;
          value.content = content;
          if (metadata) {
            fidl::Clone(*metadata, &value.meta);
          }
          MaybeFillEntityTypeMetadata(entity_types, value);

          if (weak_this->parent_id_.empty()) {
            weak_this->value_id_->Complete(
                weak_this->writer_->repository()->Add(std::move(value)));
          } else {
            weak_this->value_id_->Complete(
                weak_this->writer_->repository()->Add(weak_this->parent_id_,
                                                      std::move(value)));
          }
        } else {
          // We can safely capture everything by reference because we know
          // |weak_this->value_id_| has been completed, which means this
          // callback will be executed immediately.
          weak_this->value_id_->ConstThen(
              [weak_this, &content, &metadata,
               &entity_types](const ContextRepository::Id& value_id) {
                if (!weak_this->writer_->repository()->Contains(value_id)) {
                  FXL_LOG(FATAL)
                      << "Trying to update non-existent context value ("
                      << value_id << "). New content: " << content
                      << ", new metadata: " << metadata;
                }

                auto value = weak_this->writer_->repository()->Get(value_id);
                if (content) {
                  value->content = content;
                }
                if (metadata) {
                  fidl::Clone(*metadata, &value->meta);
                }
                MaybeFillEntityTypeMetadata(entity_types, *value);
                weak_this->writer_->repository()->Update(value_id,
                                                         std::move(*value));
              });
        }
      };

  if (type_ != fuchsia::modular::ContextValueType::ENTITY || !content) {
    // Avoid an extra round-trip to fuchsia::modular::EntityResolver that won't
    // get us anything.
    done_getting_types({});
  } else {
    writer_->GetEntityTypesFromEntityReference(
        content, fxl::MakeCopyable(std::move(done_getting_types)));
  }
}

}  // namespace modular
