// 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 <fuchsia/modular/cpp/fidl.h>
#include <fuchsia/ui/viewsv1/cpp/fidl.h>
#include <fuchsia/ui/viewsv1token/cpp/fidl.h>
#include <lib/app_driver/cpp/module_driver.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/fsl/vmo/strings.h>
#include <lib/fxl/functional/make_copyable.h>
#include <lib/fxl/time/time_delta.h>

#include "peridot/public/lib/integration_testing/cpp/reporting.h"
#include "peridot/public/lib/integration_testing/cpp/testing.h"
#include "peridot/tests/chain/defs.h"
#include "peridot/tests/common/defs.h"

using modular::testing::TestPoint;

namespace {

// Cf. README.md for what this test does and how.
class TestModule {
 public:
  TestPoint initialized_{"Parent module initialized"};

  TestModule(modular::ModuleHost* module_host,
             fidl::InterfaceRequest<
                 fuchsia::ui::app::ViewProvider> /*view_provider_request*/)
      : module_context_(module_host->module_context()) {
    module_context_->GetComponentContext(component_context_.NewRequest());
    modular::testing::Init(module_host->startup_context(), __FILE__);
    initialized_.Pass();

    // We'll use an fuchsia::modular::Entity stored on one of our Links, which
    // will be used in the resolution process to choose a compatible Module.
    // TODO(thatguy): We should be specifying type constraints when we create
    // the fuchsia::modular::Link.
    auto entity_data =
        fidl::VectorPtr<fuchsia::modular::TypeToDataEntry>::New(1);
    entity_data->at(0) = fuchsia::modular::TypeToDataEntry();
    entity_data->at(0).type = "myType";
    entity_data->at(0).data = "1337";

    component_context_->CreateEntityWithData(
        std::move(entity_data), [this](fidl::StringPtr reference) {
          entity_one_reference_ = reference;
          EmbedModule();
        });
  }

  TestModule(modular::ModuleHost* const module_host,
             fidl::InterfaceRequest<
                 fuchsia::ui::viewsv1::ViewProvider> /*view_provider_request*/)
      : TestModule(
            module_host,
            fidl::InterfaceRequest<fuchsia::ui::app::ViewProvider>(nullptr)) {}

  // Called from ModuleDriver.
  TestPoint stopped_{"Parent module stopped"};
  void Terminate(const std::function<void()>& done) {
    stopped_.Pass();
    modular::testing::Done(done);
  }

 private:
  TestPoint start_intent_{"Started child Intent"};

  fuchsia::mem::Buffer VmoFromJson(const std::string& json) {
    fsl::SizedVmo vmo;
    FXL_CHECK(fsl::VmoFromString(json, &vmo));
    return std::move(vmo).ToTransport();
  }

  void EmbedModule() {
    intent_.handler = kChildModuleUrl;
    intent_.action = "action";
    intent_.parameters.resize(4);

    // We'll put three parameters "one", "two" and "three" on the
    // fuchsia::modular::Intent.
    //
    // The first is used to match the Module, because we know that it expects
    // a parameter named "one". The other two are extra and are going to be
    // passed on to the Module regardless.
    //
    // The second parameter is set to a Link that we own with regular JSON
    // content.
    //
    // The third parameter we expect to reference a Link created on our behalf
    // by the Framework. We don't get access to that Link.
    fuchsia::modular::IntentParameterData parameter_data;

    intent_.parameters->at(0) = fuchsia::modular::IntentParameter();
    intent_.parameters->at(0).name = "one";
    intent_.parameters->at(0).data.set_entity_reference(entity_one_reference_);

    module_context_->GetLink("bar", link_two_.NewRequest());
    fsl::SizedVmo vmo;
    FXL_CHECK(fsl::VmoFromString("\"12345\"", &vmo));
    link_two_->Set(nullptr, std::move(vmo).ToTransport());
    parameter_data = fuchsia::modular::IntentParameterData();
    parameter_data.set_link_name("bar");
    intent_.parameters->at(1) = fuchsia::modular::IntentParameter();
    intent_.parameters->at(1).name = "two";
    intent_.parameters->at(1).data = std::move(parameter_data);

    parameter_data = fuchsia::modular::IntentParameterData();
    parameter_data.set_json(VmoFromJson("\"67890\""));
    intent_.parameters->at(2) = fuchsia::modular::IntentParameter();
    intent_.parameters->at(2).name = "three";
    intent_.parameters->at(2).data = std::move(parameter_data);

    parameter_data = fuchsia::modular::IntentParameterData();
    parameter_data.set_json(VmoFromJson("\"1337\""));
    intent_.parameters->at(3) = fuchsia::modular::IntentParameter();
    intent_.parameters->at(3).name = "four";
    intent_.parameters->at(3).data = std::move(parameter_data);

    // Sync to avoid race conditions between writing
    link_two_->Sync([this] {
      module_context_->EmbedModule(
          "my child", std::move(intent_), child_module_.NewRequest(),
          child_view_.NewRequest(),
          [this](fuchsia::modular::StartModuleStatus status) {
            FXL_CHECK(status == fuchsia::modular::StartModuleStatus::SUCCESS);
            start_intent_.Pass();
          });
    });
  }

  fuchsia::modular::ComponentContextPtr component_context_;
  fuchsia::modular::ModuleContext* module_context_;
  fuchsia::modular::ModuleControllerPtr child_module_;
  fuchsia::ui::viewsv1token::ViewOwnerPtr child_view_;

  fidl::StringPtr entity_one_reference_;
  fuchsia::modular::Intent intent_;

  fuchsia::modular::LinkPtr link_two_;

  FXL_DISALLOW_COPY_AND_ASSIGN(TestModule);
};

}  // namespace

int main(int /*argc*/, const char** /*argv*/) {
  async::Loop loop(&kAsyncLoopConfigAttachToThread);
  auto context = component::StartupContext::CreateFromStartupInfo();
  modular::ModuleDriver<TestModule> driver(context.get(),
                                           [&loop] { loop.Quit(); });
  loop.Run();
  return 0;
}
