// 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 "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,
    fit::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 = done.share(), 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([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(),
                           [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,
                                               std::move(done_getting_types));
  }
}

}  // namespace modular
