// Copyright 2018 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/sessionmgr/puppet_master/command_runners/operation_calls/find_modules_call.h"

#include <lib/entity/cpp/json.h>
#include <lib/fostr/fidl/fuchsia/modular/formatting.h>
#include <lib/fsl/types/type_converters.h>
#include <lib/fsl/vmo/strings.h>
#include <src/lib/fxl/logging.h>

#include "peridot/bin/sessionmgr/puppet_master/command_runners/operation_calls/get_types_from_entity_call.h"
#include "peridot/lib/fidl/clone.h"

namespace modular {

namespace {

class FindModulesCall
    : public Operation<fuchsia::modular::ExecuteResult,
                       fuchsia::modular::FindModulesResponse> {
 public:
  FindModulesCall(fuchsia::modular::ModuleResolver* const module_resolver,
                  fuchsia::modular::EntityResolver* const entity_resolver,
                  fuchsia::modular::IntentPtr intent,
                  std::vector<std::string> requesting_module_path,
                  ResultCall result_call)
      : Operation("FindModulesCall", std::move(result_call)),
        module_resolver_(module_resolver),
        entity_resolver_(entity_resolver),
        intent_(std::move(intent)),
        requesting_module_path_(std::move(requesting_module_path)) {}

 private:
  void Run() override {
    FlowToken flow{this, &result_, &response_};
    // Default status. We'll update it and return if an error occurs.
    result_.status = fuchsia::modular::ExecuteStatus::OK;

    FXL_DCHECK(intent_->action) << intent_;

    constraint_futs_.reserve(intent_->parameters->size());

    resolver_query_.action = intent_->action;
    resolver_query_.handler = intent_->handler;
    resolver_query_.parameter_constraints.resize(0);

    for (auto& param : *intent_->parameters) {
      // TODO(MF-23): Deprecate parameter name nullability altogether.
      if (param.name.is_null() && intent_->handler.is_null()) {
        result_.error_message =
            "A null-named module parameter is not allowed "
            "when using fuchsia::modular::Intent.";
        result_.status = fuchsia::modular::ExecuteStatus::INVALID_COMMAND;
        return;
        // Operation finishes since |flow| goes out of scope.
      }

      // Skip processing null intent parameter names (these are generally
      // root/null link names).
      if (param.name.is_null()) {
        param.name = "";
      }

      constraint_futs_.push_back(
          GetTypesFromIntentParameter(std::move(param.data), param.name)
              ->Map([name = param.name](std::vector<std::string> types) {
                fuchsia::modular::FindModulesParameterConstraint constraint;
                constraint.param_name = name;
                constraint.param_types = std::move(types);
                return constraint;
              }));
    }

    Wait("FindModulesCall.Run.Wait", constraint_futs_)
        ->Then([this, flow](
                   std::vector<fuchsia::modular::FindModulesParameterConstraint>
                       constraint_params) {
          if (result_.status != fuchsia::modular::ExecuteStatus::OK) {
            // Operation finishes since |flow| goes out of scope.
            return;
          }
          resolver_query_.parameter_constraints = std::move(constraint_params);
          module_resolver_->FindModules(
              std::move(resolver_query_),
              [this, flow](fuchsia::modular::FindModulesResponse response) {
                response_ = std::move(response);
                // At this point, the only remaining |flow| is the one captured
                // in this lambda. This operation should end once |flow| goes
                // out of scope here.
              });
        });
  }

  // To avoid deadlocks, this function must not depend on anything that executes
  // on the story controller's operation queue.
  FuturePtr<std::vector<std::string>> GetTypesFromIntentParameter(
      fuchsia::modular::IntentParameterData input,
      const fidl::StringPtr& param_name) {
    auto fut = Future<std::vector<std::string>>::Create(
        "AddModCommandRunner::GetTypesFromIntentParameter");
    switch (input.Which()) {
      case fuchsia::modular::IntentParameterData::Tag::kEntityReference: {
        AddGetTypesFromEntityOperation(&operations_, entity_resolver_,
                                       input.entity_reference(),
                                       fut->Completer());
        break;
      }
      case fuchsia::modular::IntentParameterData::Tag::kEntityType: {
        fut->Complete(fidl::To<std::vector<std::string>>(input.entity_type()));
        break;
      }
      case fuchsia::modular::IntentParameterData::Tag::kJson: {
        std::string json_string;
        FXL_CHECK(fsl::StringFromVmo(input.json(), &json_string));
        if (auto result = GetTypesFromJson(json_string)) {
          fut->Complete(std::move(*result));
        } else {
          std::ostringstream stream;
          stream << "Mal-formed JSON in parameter: " << param_name;
          result_.error_message = stream.str();
          result_.status = fuchsia::modular::ExecuteStatus::INVALID_COMMAND;
          fut->Complete({});
        }
        break;
      }
      case fuchsia::modular::IntentParameterData::Tag::Invalid: {
        std::ostringstream stream;
        stream << "Invalid data for parameter with name: " << param_name;
        result_.error_message = stream.str();
        result_.status = fuchsia::modular::ExecuteStatus::INVALID_COMMAND;
        fut->Complete({});
        break;
      }
    }
    return fut;
  }

  std::optional<std::vector<std::string>> GetTypesFromJson(
      const fidl::StringPtr& input) {
    std::vector<std::string> types;
    if (ExtractEntityTypesFromJson(input, &types)) {
      return types;
    }
    return std::nullopt;
  }

  fuchsia::modular::ModuleResolver* const module_resolver_;  // Not Owned
  fuchsia::modular::EntityResolver* const entity_resolver_;  // Not owned.
  const fuchsia::modular::IntentPtr intent_;
  const std::vector<std::string> requesting_module_path_;

  fuchsia::modular::FindModulesQuery resolver_query_;
  std::vector<FuturePtr<fuchsia::modular::FindModulesParameterConstraint>>
      constraint_futs_;
  fuchsia::modular::ExecuteResult result_;
  fuchsia::modular::FindModulesResponse response_;
  OperationCollection operations_;
};

}  // namespace

void AddFindModulesOperation(
    OperationContainer* operation_container,
    fuchsia::modular::ModuleResolver* const module_resolver,
    fuchsia::modular::EntityResolver* const entity_resolver,
    fuchsia::modular::IntentPtr intent,
    std::vector<std::string> requesting_module_path,
    fit::function<void(fuchsia::modular::ExecuteResult,
                       fuchsia::modular::FindModulesResponse)>
        result_call) {
  operation_container->Add(std::make_unique<FindModulesCall>(
      module_resolver, entity_resolver, std::move(intent),
      std::move(requesting_module_path), std::move(result_call)));
}

}  // namespace modular
