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

#include <lib/entity/cpp/json.h>
#include <lib/fidl/cpp/clone.h>
#include <lib/fsl/vmo/strings.h>
#include <lib/fxl/logging.h>
#include <lib/fxl/strings/string_printf.h>

#include "peridot/bin/sessionmgr/puppet_master/command_runners/operation_calls/find_modules_call.h"
#include "peridot/bin/sessionmgr/puppet_master/command_runners/operation_calls/get_link_path_for_parameter_name_call.h"
#include "peridot/bin/sessionmgr/puppet_master/command_runners/operation_calls/get_types_from_entity_call.h"
#include "peridot/bin/sessionmgr/puppet_master/command_runners/operation_calls/initialize_chain_call.h"
#include "peridot/lib/fidl/clone.h"
#include "peridot/lib/module_manifest/module_facet_reader.h"

namespace modular {

namespace {

class AddModCall : public Operation<fuchsia::modular::ExecuteResult,
                                    fuchsia::modular::ModuleData> {
 public:
  AddModCall(StoryStorage* const story_storage,
             fuchsia::modular::ModuleResolver* const module_resolver,
             fuchsia::modular::EntityResolver* const entity_resolver,
             modular::ModuleFacetReader* const module_facet_reader,
             fidl::VectorPtr<fidl::StringPtr> mod_name,
             fuchsia::modular::Intent intent,
             fuchsia::modular::SurfaceRelationPtr surface_relation,
             fidl::VectorPtr<fidl::StringPtr> surface_parent_mod_name,
             fuchsia::modular::ModuleSource module_source, ResultCall done)
      : Operation("AddModCommandRunner::AddModCall", std::move(done)),
        story_storage_(story_storage),
        module_resolver_(module_resolver),
        entity_resolver_(entity_resolver),
        module_facet_reader_(module_facet_reader),
        mod_name_(std::move(mod_name)),
        intent_(std::move(intent)),
        surface_relation_(std::move(surface_relation)),
        surface_parent_mod_name_(std::move(surface_parent_mod_name)),
        module_source_(module_source) {}

 private:
  void Run() override {
    FlowToken flow{this, &out_result_, &out_module_data_};

    if (!surface_parent_mod_name_) {
      surface_parent_mod_name_.resize(0);
    }

    // Success status by default, it will be update it if an error state is
    // found.
    out_result_.status = fuchsia::modular::ExecuteStatus::OK;

    // If we have an action, we use the module resolver to type-check and
    // resolve the (action, parameter) and the supplied optional handler to a
    // module. If the module resolver doesn't recognize a supplied handler, we
    // forgivingly execute the handler anyway.
    if (!intent_.action.is_null()) {
      AddFindModulesOperation(
          &operation_queue_, story_storage_, module_resolver_, entity_resolver_,
          CloneOptional(intent_), surface_parent_mod_name_.Clone(),
          [this, flow](fuchsia::modular::ExecuteResult result,
                       fuchsia::modular::FindModulesResponse response) {
            if (result.status != fuchsia::modular::ExecuteStatus::OK) {
              out_result_ = std::move(result);
              return;
              // Operation finishes since |flow| goes out of scope.
            }

            // NOTE: leave this as a switch case and omit the default case; the
            // compiler will make sure we're handling all error cases.
            switch (response.status) {
              case fuchsia::modular::FindModulesStatus::SUCCESS: {
                if (response.results->empty()) {
                  out_result_.status =
                      fuchsia::modular::ExecuteStatus::NO_MODULES_FOUND;
                  out_result_.error_message =
                      "Resolution of intent gave zero results.";
                  return;
                  // Operation finishes since |flow| goes out of scope.
                }

                candidate_module_ = std::move(response.results->at(0));
              } break;

              case fuchsia::modular::FindModulesStatus::UNKNOWN_HANDLER: {
                FXL_LOG(INFO)
                    << "Module Resolver does not know about module '"
                    << intent_.handler << "' with action = '" << intent_.action
                    << "'. Going to try using it anyway..";
                candidate_module_.module_id = intent_.handler;
              } break;
            }

            CreateLinks(flow);
          });
    } else {
      // We arrive here if the Intent has a handler, but no action.
      FXL_DCHECK(!intent_.handler.is_null())
          << "Cannot start a module without an action or a handler";
      candidate_module_.module_id = intent_.handler;

      CreateLinks(flow);
    }
  }

  // Create module parameters info and create links.
  void CreateLinks(FlowToken flow) {
    CreateModuleParameterMapInfo(flow, [this, flow] {
      if (out_result_.status != fuchsia::modular::ExecuteStatus::OK) {
        return;
        // Operation finishes since |flow| goes out of scope.
      }
      auto full_module_path = surface_parent_mod_name_.Clone();
      full_module_path->insert(full_module_path->end(), mod_name_->begin(),
                               mod_name_->end());
      AddInitializeChainOperation(
          &operation_queue_, story_storage_, std::move(full_module_path),
          std::move(parameter_info_),
          [this, flow](fuchsia::modular::ExecuteResult result,
                       fuchsia::modular::ModuleParameterMapPtr map) {
            if (result.status != fuchsia::modular::ExecuteStatus::OK) {
              out_result_ = std::move(result);
              return;
              // Operation finishes since |flow| goes out of scope.
            }
            WriteModuleData(flow, std::move(map));
          });
    });
  }

  // On success, populates |parameter_info_|. On failure, |out_result_| contains
  // error reason. Calls |done()| on completion in either case.
  void CreateModuleParameterMapInfo(FlowToken flow,
                                    std::function<void()> done) {
    parameter_info_ = fuchsia::modular::CreateModuleParameterMapInfo::New();

    std::vector<FuturePtr<fuchsia::modular::CreateModuleParameterMapEntry>>
        did_get_entries;
    did_get_entries.reserve(intent_.parameters->size());

    for (auto& param : *intent_.parameters) {
      fuchsia::modular::CreateModuleParameterMapEntry entry;
      entry.key = param.name;

      switch (param.data.Which()) {
        case fuchsia::modular::IntentParameterData::Tag::kEntityReference: {
          fuchsia::modular::CreateLinkInfo create_link;
          fsl::SizedVmo vmo;
          FXL_CHECK(fsl::VmoFromString(
              EntityReferenceToJson(param.data.entity_reference()), &vmo));
          create_link.initial_data = std::move(vmo).ToTransport();
          entry.value.set_create_link(std::move(create_link));
          break;
        }
        case fuchsia::modular::IntentParameterData::Tag::kEntityType: {
          // Create a link, but don't populate it. This is useful in the event
          // that the link is used as an 'output' link. Setting a valid JSON
          // value for null in the vmo.
          fsl::SizedVmo vmo;
          FXL_CHECK(fsl::VmoFromString("null", &vmo));
          fuchsia::modular::CreateLinkInfo create_link;
          create_link.initial_data = std::move(vmo).ToTransport();
          entry.value.set_create_link(std::move(create_link));
          break;
        }
        case fuchsia::modular::IntentParameterData::Tag::kJson: {
          fuchsia::modular::CreateLinkInfo create_link;
          param.data.json().Clone(&create_link.initial_data);
          entry.value.set_create_link(std::move(create_link));
          break;
        }
        case fuchsia::modular::IntentParameterData::Tag::kLinkName: {
          auto did_get_lp = Future<fuchsia::modular::LinkPathPtr>::Create(
              "AddModCommandRunner::AddModCall::did_get_link");
          // TODO(miguelfrde): get rid of using surface_parent_mod_name this
          // way. Maybe INVALID status should be returned here since using
          // this parameter in a StoryCommand doesn't make much sense.
          AddGetLinkPathForParameterNameOperation(
              &operations_, story_storage_, surface_parent_mod_name_.Clone(),
              param.data.link_name(), did_get_lp->Completer());

          did_get_entries.emplace_back(
              did_get_lp->Map([this, param_name = param.name,
                               done](fuchsia::modular::LinkPathPtr link_path) {
                if (!GetWeakPtr()) {
                  return fuchsia::modular::CreateModuleParameterMapEntry{};
                }
                if (!link_path) {
                  // OH NO! bail on this entire function's flow.
                  out_result_.status =
                      fuchsia::modular::ExecuteStatus::INTERNAL_ERROR;
                  out_result_.error_message = fxl::StringPrintf(
                      "Link path does not exist for parameter name = %s",
                      param_name.get().c_str());
                  done();
                  return fuchsia::modular::CreateModuleParameterMapEntry{};
                }
                fuchsia::modular::CreateModuleParameterMapEntry entry;
                entry.key = param_name;
                entry.value.set_link_path(std::move(*link_path));
                return entry;
              }));
          continue;
        }
        case fuchsia::modular::IntentParameterData::Tag::kLinkPath: {
          fuchsia::modular::LinkPath lp;
          param.data.link_path().Clone(&lp);
          entry.value.set_link_path(std::move(lp));
          break;
        }
        case fuchsia::modular::IntentParameterData::Tag::Invalid: {
          out_result_.status = fuchsia::modular::ExecuteStatus::INVALID_COMMAND;
          out_result_.error_message =
              fxl::StringPrintf("Invalid data for parameter with name: %s",
                                param.name.get().c_str());
          done();
          return;
        }
      }

      auto did_create_entry =
          Future<fuchsia::modular::CreateModuleParameterMapEntry>::
              CreateCompleted(
                  "AddModCommandRunner::FindModulesCall.did_create_entry",
                  std::move(entry));
      did_get_entries.emplace_back(std::move(did_create_entry));
    }

    Wait("AddModCommandRunner::AddModCall::Wait", did_get_entries)
        ->Then([this, done, flow](
                   std::vector<fuchsia::modular::CreateModuleParameterMapEntry>
                       entries) {
          parameter_info_->property_info.reset(std::move(entries));
          done();
        });
  }

  // Write module data
  void WriteModuleData(FlowToken flow,
                       fuchsia::modular::ModuleParameterMapPtr map) {
    fidl::Clone(*map, &out_module_data_.parameter_map);
    out_module_data_.module_url = candidate_module_.module_id;
    out_module_data_.module_path = surface_parent_mod_name_.Clone();
    out_module_data_.module_path->insert(out_module_data_.module_path->end(),
                                         mod_name_->begin(), mod_name_->end());
    out_module_data_.module_source = module_source_;
    out_module_data_.module_deleted = false;
    fidl::Clone(surface_relation_, &out_module_data_.surface_relation);
    out_module_data_.intent =
        std::make_unique<fuchsia::modular::Intent>(std::move(intent_));

    auto write_to_storage_cont = [this, flow]() {
      // Operation stays alive until flow goes out of scope.
      fuchsia::modular::ModuleData module_data;
      out_module_data_.Clone(&module_data);
      story_storage_->WriteModuleData(std::move(module_data))
          ->Then([this, flow] {});
    };

    // If the resolver gave us a module manifest (which is described in the
    // module facet), we don't need to try and read it.
    if (candidate_module_.manifest) {
      fidl::Clone(candidate_module_.manifest,
                  &out_module_data_.module_manifest);
      write_to_storage_cont();
      return;
    }

    module_facet_reader_->GetModuleManifest(
        out_module_data_.module_url,
        [this, flow,
         write_to_storage_cont](fuchsia::modular::ModuleManifestPtr manifest) {
          out_module_data_.module_manifest = std::move(manifest);
          write_to_storage_cont();
        });
  }

  StoryStorage* const story_storage_;                        // Not owned.
  fuchsia::modular::ModuleResolver* const module_resolver_;  // Not owned.
  fuchsia::modular::EntityResolver* const entity_resolver_;  // Not owned.
  modular::ModuleFacetReader* const module_facet_reader_;    // Not owned.
  fidl::VectorPtr<fidl::StringPtr> mod_name_;
  fuchsia::modular::Intent intent_;
  fuchsia::modular::SurfaceRelationPtr surface_relation_;
  fidl::VectorPtr<fidl::StringPtr> surface_parent_mod_name_;
  fuchsia::modular::ModuleSource module_source_;
  fuchsia::modular::FindModulesResult candidate_module_;
  fuchsia::modular::CreateModuleParameterMapInfoPtr parameter_info_;
  fuchsia::modular::ModuleData out_module_data_;
  fuchsia::modular::ExecuteResult out_result_;
  // Used when creating the map info to execute an operation as soon as it
  // arrives.
  OperationCollection operations_;
  // Used to enqueue sub-operations that should be executed sequentially.
  OperationQueue operation_queue_;

  FXL_DISALLOW_COPY_AND_ASSIGN(AddModCall);
};  // namespace

}  // namespace

void AddAddModOperation(
    OperationContainer* const container, StoryStorage* const story_storage,
    fuchsia::modular::ModuleResolver* const module_resolver,
    fuchsia::modular::EntityResolver* const entity_resolver,
    modular::ModuleFacetReader* const module_facet_reader,
    fidl::VectorPtr<fidl::StringPtr> mod_name, fuchsia::modular::Intent intent,
    fuchsia::modular::SurfaceRelationPtr surface_relation,
    fidl::VectorPtr<fidl::StringPtr> surface_parent_mod_name,
    fuchsia::modular::ModuleSource module_source,
    std::function<void(fuchsia::modular::ExecuteResult,
                       fuchsia::modular::ModuleData)>
        done) {
  container->Add(new AddModCall(
      story_storage, module_resolver, entity_resolver, module_facet_reader,
      std::move(mod_name), std::move(intent), std::move(surface_relation),
      std::move(surface_parent_mod_name), module_source, std::move(done)));
}

}  // namespace modular
