// 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 "src/modular/bin/module_resolver/type_inference.h"

#include <string>
#include <vector>

#include "src/lib/fsl/types/type_converters.h"
#include "src/lib/fxl/macros.h"
#include "src/modular/lib/async/cpp/operation.h"
#include "src/modular/lib/entity/cpp/json.h"

namespace modular {

ParameterTypeInferenceHelper::ParameterTypeInferenceHelper(
    fuchsia::modular::EntityResolverPtr entity_resolver)
    : entity_resolver_(std::move(entity_resolver)) {}

ParameterTypeInferenceHelper::~ParameterTypeInferenceHelper() = default;

class ParameterTypeInferenceHelper::GetParameterTypesCall
    : public Operation<std::vector<std::string>> {
 public:
  GetParameterTypesCall(fuchsia::modular::EntityResolver* entity_resolver,
                        const fidl::StringPtr& entity_reference, ResultCall result)
      : Operation("ParameterTypeInferenceHelper::GetParameterTypesCall", std::move(result)),
        entity_resolver_(entity_resolver),
        entity_reference_(entity_reference) {}

  void Run() {
    entity_resolver_->ResolveEntity(entity_reference_, entity_.NewRequest());
    entity_->GetTypes([this](const fidl::VectorPtr<fidl::StringPtr>& types) {
      Done(fidl::To<std::vector<std::string>>(types));
    });
  }

 private:
  fuchsia::modular::EntityResolver* const entity_resolver_;
  fidl::StringPtr const entity_reference_;
  fuchsia::modular::EntityPtr entity_;
};

void ParameterTypeInferenceHelper::GetParameterTypes(
    const fuchsia::modular::ResolverParameterConstraint& parameter_constraint,
    fit::function<void(std::vector<std::string>)> result_callback) {
  if (parameter_constraint.is_entity_type()) {
    result_callback(std::vector<std::string>(parameter_constraint.entity_type()->begin(),
                                             parameter_constraint.entity_type()->end()));
  } else if (parameter_constraint.is_json()) {
    std::vector<std::string> types;
    if (!ExtractEntityTypesFromJson(parameter_constraint.json(), &types)) {
      FXL_LOG(WARNING) << "Mal-formed JSON in parameter: " << parameter_constraint.json();
      result_callback({});
    } else {
      result_callback(types);
    }
  } else if (parameter_constraint.is_entity_reference()) {
    operation_collection_.Add(std::make_unique<GetParameterTypesCall>(
        entity_resolver_.get(), parameter_constraint.entity_reference(), result_callback));
  } else if (parameter_constraint.is_link_info()) {
    if (parameter_constraint.link_info().allowed_types) {
      std::vector<std::string> types(
          parameter_constraint.link_info().allowed_types->allowed_entity_types->begin(),
          parameter_constraint.link_info().allowed_types->allowed_entity_types->end());
      result_callback(std::move(types));
    } else if (parameter_constraint.link_info().content_snapshot) {
      // TODO(thatguy): See if there's an fuchsia::modular::Entity reference on
      // the fuchsia::modular::Link. If so, get the types from that.  If
      // resolution results in a Module being started, this
      // fuchsia::modular::Link should have its allowed types constrained, since
      // *another* Module is now relying on a small set of types being set.
      // Consider doing this when we move type extraction to the Framework and
      // simplify the Resolver.
      std::string entity_reference;
      if (EntityReferenceFromJson(parameter_constraint.link_info().content_snapshot,
                                  &entity_reference)) {
        operation_collection_.Add(std::make_unique<GetParameterTypesCall>(
            entity_resolver_.get(), entity_reference, result_callback));
      }
    }
  } else {
    FXL_NOTREACHED();
  }
}

}  // namespace modular
