// 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 <utility>

#include <fuchsia/modular/cpp/fidl.h>
#include <lib/app_driver/cpp/module_driver.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async/cpp/task.h>
#include <lib/async/default.h>
#include <lib/callback/scoped_callback.h>
#include <lib/component/cpp/connect.h>
#include <lib/fxl/memory/weak_ptr.h>
#include <lib/message_queue/cpp/message_queue_client.h>
#include <test/peridot/tests/componentcontext/cpp/fidl.h>

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

using ::modular::testing::Await;
using ::modular::testing::Signal;
using ::modular::testing::TestPoint;
using ::test::peridot::tests::componentcontext::ComponentContextTestServicePtr;

namespace {

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

  TestModule(modular::ModuleHost* module_host,
             fidl::InterfaceRequest<
                 fuchsia::ui::app::ViewProvider> /*view_provider_request*/)
      : weak_ptr_factory_(this) {
    modular::testing::Init(module_host->startup_context(), __FILE__);

    initialized_.Pass();

    // Exercise fuchsia::modular::ComponentContext.ConnectToAgent()
    module_host->module_context()->GetComponentContext(
        component_context_.NewRequest());

    fuchsia::sys::ServiceProviderPtr one_agent_services;
    component_context_->ConnectToAgent(kOneAgentUrl,
                                       one_agent_services.NewRequest(),
                                       one_agent_controller.NewRequest());
    component::ConnectToService(one_agent_services.get(),
                                one_agent_interface_.NewRequest());

    TestAgentConnected();
  }

  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 by ModuleDriver.
  TestPoint stopped_{"Root module stopped"};
  void Terminate(const std::function<void()>& done) {
    stopped_.Pass();
    modular::testing::Done(done);
  }

 private:
  TestPoint one_agent_connected_{"One agent accepted connection"};

  void TestAgentConnected() {
    Await("one_agent_connected", [this] {
                                   FXL_LOG(INFO) << "TestModule One Agent Connected";
                                   one_agent_connected_.Pass();
                                   TestMessageQueue();
                               });
  }

  TestPoint msg_queue_communicated_{
      "Communicated message between Agent one using a MessageQueue"};

  // Tests message queues.
  void TestMessageQueue() {
    constexpr char kTestMessage[] = "test message!";

    component_context_->ObtainMessageQueue("root_msg_queue",
                                           msg_queue_.NewRequest());

    // MessageQueueManager shouldn't send us anything just yet.
    msg_queue_.RegisterReceiver(
        [this, kTestMessage](const std::string& msg,
                             fit::function<void()> ack) {
          ack();
          // We only want one message.
          msg_queue_.RegisterReceiver(nullptr);

          if (msg == kTestMessage) {
            msg_queue_communicated_.Pass();
          }
          TestAgentController();
        });

    msg_queue_.GetToken([this, kTestMessage](const fidl::StringPtr& token) {
      one_agent_interface_->SendToMessageQueue(token, kTestMessage);
    });
  }

  TestPoint one_agent_stopped_{"One agent stopped"};

  // Tests fuchsia::modular::AgentController. Calls |done_cb| when completed
  // successfully.
  void TestAgentController() {
    // Closing the agent controller should trigger the agent to stop.
    one_agent_controller.Unbind();

    Await("one_agent_stopped", [this] {
      one_agent_stopped_.Pass();
      TestUnstoppableAgent();
    });
  }

  // Start an agent that will not stop of its own accord.
  void TestUnstoppableAgent() {
    fuchsia::sys::ServiceProviderPtr unstoppable_agent_services;
    component_context_->ConnectToAgent(
        kUnstoppableAgent, unstoppable_agent_services.NewRequest(),
        unstoppable_agent_controller_.NewRequest());

    // After 500ms close the fuchsia::modular::AgentController for the
    // unstoppable agent.
    // TODO(jimbe) We don't check if the agent started running in the allotted
    // time, so this test isn't reliable. We need to make a call to the agent
    // and wait for a response.
    async::PostDelayedTask(
        async_get_default_dispatcher(),
        callback::MakeScoped(weak_ptr_factory_.GetWeakPtr(),
                             [this] {
                               unstoppable_agent_controller_.Unbind();
                               Signal(modular::testing::kTestShutdown);
                             }),
        zx::msec(500));
  }

  fuchsia::modular::AgentControllerPtr one_agent_controller;
  ComponentContextTestServicePtr one_agent_interface_;
  fuchsia::modular::ComponentContextPtr component_context_;
  modular::MessageQueueClient msg_queue_;

  fuchsia::modular::AgentControllerPtr unstoppable_agent_controller_;

  fxl::WeakPtrFactory<TestModule> weak_ptr_factory_;

  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;
}
