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

#include <fuchsia/modular/cpp/fidl.h>
#include <fuchsia/ui/viewsv1/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/fsl/vmo/strings.h>
#include <lib/fxl/memory/weak_ptr.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/parent_child/defs.h"

using modular::testing::Await;
using modular::testing::Get;
using modular::testing::Put;
using modular::testing::Signal;
using modular::testing::TestPoint;

namespace {

void AddModuleToStoryWithHandler(
    fuchsia::modular::ModuleContext* const module_context,
    fidl::InterfaceRequest<fuchsia::modular::ModuleController> request,
    fidl::StringPtr handler) {
  fuchsia::modular::Intent intent;
  intent.handler = handler;
  intent.action = kChildModuleAction;
  module_context->AddModuleToStory(
      kChildModuleName, std::move(intent), std::move(request),
      nullptr /* surface_relation */,
      [](const fuchsia::modular::StartModuleStatus) {});
}

// 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_host_(module_host) {
    modular::testing::Init(module_host->startup_context(), __FILE__);
    initialized_.Pass();

    StartChildModuleTwice();
  }

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

 private:
  TestPoint second_child_module_controller_closed_{
      "Second child module controller closed"};

  void StartChildModuleTwice() {
    AddModuleToStoryWithHandler(module_host_->module_context(),
                                child_module_.NewRequest(), kChildModuleUrl1);
    child_module_.set_error_handler(
        [this](zx_status_t status) { OnFirstChildModuleStopped(); });

    // Once the module starts, start the same module again with the same
    // Intent, and then again but with a different Intent.handler. The second
    // call stops the previous module instance and starts a new one.
    Await("child_module_1_init", [this] {
      AddModuleToStoryWithHandler(module_host_->module_context(),
                                  child_module_again_.NewRequest(),
                                  kChildModuleUrl1);
      child_module_again_.set_error_handler([this](zx_status_t status) {
        second_child_module_controller_closed_.Pass();
      });
      AddModuleToStoryWithHandler(module_host_->module_context(),
                                  child_module2_.NewRequest(),
                                  kChildModuleUrl2);
    });
  }

  TestPoint child_module1_stopped_{"Child module killed for restart"};

  void OnFirstChildModuleStopped() {
    child_module1_stopped_.Pass();

    // Confirm that the first module instance stopped, and then stop the second
    // module instance.
    Await("child_module_1_stop", [this] {
      Await("child_module_2_init", [this] {
        child_module2_->Stop([this] { OnChildModule2Stopped(); });
      });
    });
  }

  TestPoint child_module2_stopped_{"Second child module stopped"};
  void OnChildModule2Stopped() {
    child_module2_stopped_.Pass();

    TestPipelinedAddAndStop();
  }

  TestPoint child_module_3_started_{"Third child module started"};
  TestPoint child_module_3_stopped_{"Third child module stopped"};
  void TestPipelinedAddAndStop() {
    // New test case: start a third child module, and immediately stop it.
    // We expect that the child module will go through its full lifecycle,
    // since we serialize these requests in sessionmgr.
    AddModuleToStoryWithHandler(module_host_->module_context(),
                                child_module3_.NewRequest(), kChildModuleUrl1);
    child_module3_->Stop([this] { /* do nothing */ });
    child_module3_.events().OnStateChange =
        [this](fuchsia::modular::ModuleState module_state) {
          if (module_state == fuchsia::modular::ModuleState::RUNNING) {
            child_module_3_started_.Pass();
          }
          if (module_state == fuchsia::modular::ModuleState::STOPPED) {
            child_module_3_stopped_.Pass();
            Signal(modular::testing::kTestShutdown);
          }
        };
  }

  modular::ModuleHost* module_host_;
  fuchsia::modular::ModuleControllerPtr child_module_;
  fuchsia::modular::ModuleControllerPtr child_module_again_;
  fuchsia::modular::ModuleControllerPtr child_module2_;
  fuchsia::modular::ModuleControllerPtr child_module3_;

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