// 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 "src/modular/lib/fidl/app_client.h"

#include <fuchsia/sys/cpp/fidl.h>
#include <lib/gtest/test_loop_fixture.h>
#include <lib/sys/cpp/testing/fake_launcher.h>

#include <test/peridot/lib/fidl/appclient/cpp/fidl.h>

#include "gtest/gtest.h"

namespace modular_testing {
namespace {

using ::sys::testing::FakeLauncher;
using ::test::peridot::lib::fidl::appclient::TerminateService;

constexpr char kServiceName[] = "service1";
constexpr char kTestUrl[] = "some/test/url";

fuchsia::modular::AppConfig GetTestAppConfig() {
  fuchsia::modular::AppConfig app_config;
  app_config.url = kTestUrl;
  return app_config;
}

class TestComponentController : fuchsia::sys::ComponentController {
 public:
  TestComponentController() : binding_(this) {}

  void Connect(fidl::InterfaceRequest<fuchsia::sys::ComponentController> request) {
    binding_.Bind(std::move(request));
    binding_.set_error_handler([this](zx_status_t status) { Kill(); });
  }

  bool killed() { return killed_; }

 private:
  void Kill() override { killed_ = true; }

  void Detach() override {}

  fidl::Binding<fuchsia::sys::ComponentController> binding_;

  bool killed_{};

  FXL_DISALLOW_COPY_AND_ASSIGN(TestComponentController);
};

class AppClientTest : public gtest::TestLoopFixture {};

TEST_F(AppClientTest, BaseRun_Success) {
  bool callback_called = false;
  FakeLauncher launcher;
  launcher.RegisterComponent(
      kTestUrl, [&callback_called](fuchsia::sys::LaunchInfo launch_info,
                                   fidl::InterfaceRequest<fuchsia::sys::ComponentController> ctrl) {
        EXPECT_EQ(kTestUrl, launch_info.url);
        callback_called = true;
      });
  modular::AppClientBase app_client_base(&launcher, GetTestAppConfig());

  EXPECT_TRUE(callback_called);
}

TEST_F(AppClientTest, BaseTerminate_Success) {
  FakeLauncher launcher;
  TestComponentController controller;
  bool callback_called = false;
  launcher.RegisterComponent(kTestUrl,
                             [&callback_called, &controller](
                                 fuchsia::sys::LaunchInfo launch_info,
                                 fidl::InterfaceRequest<fuchsia::sys::ComponentController> ctrl) {
                               EXPECT_EQ(kTestUrl, launch_info.url);
                               callback_called = true;
                               controller.Connect(std::move(ctrl));
                             });

  modular::AppClientBase app_client_base(&launcher, GetTestAppConfig());

  bool app_terminated_callback_called = false;
  app_client_base.Teardown(
      zx::duration(), [&app_terminated_callback_called] { app_terminated_callback_called = true; });

  EXPECT_TRUE(callback_called);
  RunLoopUntilIdle();
  EXPECT_TRUE(app_terminated_callback_called);
  EXPECT_TRUE(controller.killed());
}

TEST_F(AppClientTest, Run_Success) {
  bool callback_called = false;
  FakeLauncher launcher;
  launcher.RegisterComponent(
      kTestUrl, [&callback_called](fuchsia::sys::LaunchInfo launch_info,
                                   fidl::InterfaceRequest<fuchsia::sys::ComponentController> ctrl) {
        EXPECT_EQ(kTestUrl, launch_info.url);
        callback_called = true;
      });

  modular::AppClient<TerminateService> app_client(&launcher, GetTestAppConfig());

  EXPECT_TRUE(callback_called);
}

TEST_F(AppClientTest, RunWithParams_Success) {
  fuchsia::sys::ServiceListPtr additional_services = fuchsia::sys::ServiceList::New();
  additional_services->names.push_back(kServiceName);
  // We just need |provider_request| to stay around till the end of this test.
  auto provider_request = additional_services->provider.NewRequest();

  bool callback_called = false;
  FakeLauncher launcher;
  launcher.RegisterComponent(
      kTestUrl, [&callback_called](fuchsia::sys::LaunchInfo launch_info,
                                   fidl::InterfaceRequest<fuchsia::sys::ComponentController> ctrl) {
        EXPECT_EQ(kTestUrl, launch_info.url);
        auto additional_services = std::move(launch_info.additional_services);
        EXPECT_EQ(kServiceName, additional_services->names.at(0));
        callback_called = true;
      });

  modular::AppClient<TerminateService> app_client(&launcher, GetTestAppConfig(), "",
                                                  std::move(additional_services));

  EXPECT_TRUE(callback_called);
}

}  // namespace
}  // namespace modular_testing
