// 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/debugdata/cpp/fidl.h>
#include <fuchsia/io/cpp/fidl.h>
#include <fuchsia/sys/cpp/fidl.h>
#include <lib/fidl/cpp/clone.h>
#include <lib/fidl/cpp/interface_handle.h>
#include <lib/fidl/cpp/interface_request.h>
#include <lib/fit/function.h>
#include <lib/sys/cpp/service_directory.h>
#include <lib/sys/cpp/testing/enclosing_environment.h>
#include <lib/vfs/cpp/pseudo_dir.h>
#include <zircon/assert.h>

#include <memory>

namespace sys::testing {

EnvironmentServices::ParentOverrides::ParentOverrides(ParentOverrides&&) noexcept = default;

EnvironmentServices::ParentOverrides::ParentOverrides() = default;

EnvironmentServices::EnvironmentServices(const fuchsia::sys::EnvironmentPtr& parent_env,
                                         ParentOverrides parent_overrides,
                                         async_dispatcher_t* dispatcher)
    : dispatcher_(dispatcher) {
  zx::channel request;
  parent_svc_ = sys::ServiceDirectory::CreateWithRequest(&request);
  parent_env->GetDirectory(std::move(request));
  if (parent_overrides.loader_service_) {
    AddSharedService(parent_overrides.loader_service_, fuchsia::sys::Loader::Name_);
  } else {
    AllowParentService(fuchsia::sys::Loader::Name_);
  }

  if (parent_overrides.debug_data_service_) {
    AddSharedService(parent_overrides.debug_data_service_, fuchsia::debugdata::DebugData::Name_);
  } else {
    AllowParentService(fuchsia::debugdata::DebugData::Name_);
  }
}

// static
std::unique_ptr<EnvironmentServices> EnvironmentServices::Create(
    const fuchsia::sys::EnvironmentPtr& parent_env, async_dispatcher_t* dispatcher) {
  return std::unique_ptr<EnvironmentServices>(
      new EnvironmentServices(parent_env, ParentOverrides{}, dispatcher));
}

// static
std::unique_ptr<EnvironmentServices> EnvironmentServices::CreateWithParentOverrides(
    const fuchsia::sys::EnvironmentPtr& parent_env, ParentOverrides parent_overrides,
    async_dispatcher_t* dispatcher) {
  return std::unique_ptr<EnvironmentServices>(
      new EnvironmentServices(parent_env, std::move(parent_overrides), dispatcher));
}

zx_status_t EnvironmentServices::AddSharedService(const std::shared_ptr<vfs::Service>& service,
                                                  const std::string& service_name) {
  svc_names_.push_back(service_name);
  return svc_.AddSharedEntry(service_name, service);
}

zx_status_t EnvironmentServices::AddService(std::unique_ptr<vfs::Service> service,
                                            const std::string& service_name) {
  svc_names_.push_back(service_name);
  return svc_.AddEntry(service_name, std::move(service));
}

zx_status_t EnvironmentServices::AddServiceWithLaunchInfo(fuchsia::sys::LaunchInfo launch_info,
                                                          const std::string& service_name) {
  return AddServiceWithLaunchInfo(
      launch_info.url,
      [launch_info = std::move(launch_info)]() {
        // clone only URL and Arguments
        fuchsia::sys::LaunchInfo dup_launch_info;
        fidl::Clone(launch_info.url, &dup_launch_info.url);
        fidl::Clone(launch_info.arguments, &dup_launch_info.arguments);
        return dup_launch_info;
      },
      service_name);
}

zx_status_t EnvironmentServices::AddServiceWithLaunchInfo(
    std::string singleton_id, fit::function<fuchsia::sys::LaunchInfo()> handler,
    const std::string& service_name) {
  auto child = std::make_unique<vfs::Service>(
      [this, service_name, handler = std::move(handler), singleton_id = std::move(singleton_id),
       controller = fuchsia::sys::ComponentControllerPtr()](
          zx::channel client_handle, async_dispatcher_t* /*unused*/) mutable {
        auto it = singleton_services_.find(singleton_id);
        if (it == singleton_services_.end()) {
          fuchsia::sys::LaunchInfo launch_info = handler();
          auto services = sys::ServiceDirectory::CreateWithRequest(&launch_info.directory_request);

          enclosing_env_->CreateComponent(std::move(launch_info), controller.NewRequest());
          controller.set_error_handler([this, singleton_id, &controller](zx_status_t /*unused*/) {
            // TODO(unknown): show error? where on stderr?
            controller.Unbind();  // kills the singleton application
            singleton_services_.erase(singleton_id);
          });

          controller.events().OnTerminated =
              [this, singleton_id](int64_t exit_code, fuchsia::sys::TerminationReason reason) {
                if (service_terminated_callback_) {
                  service_terminated_callback_(singleton_id, exit_code, reason);
                }
              };

          std::tie(it, std::ignore) =
              singleton_services_.emplace(singleton_id, std::move(services));
        }

        it->second->Connect(service_name, std::move(client_handle));
      });
  svc_names_.push_back(service_name);
  return svc_.AddEntry(service_name, std::move(child));
}

zx_status_t EnvironmentServices::AllowParentService(const std::string& service_name) {
  svc_names_.push_back(service_name);
  return svc_.AddEntry(
      service_name, std::make_unique<vfs::Service>(
                        [this, service_name](zx::channel channel, async_dispatcher_t* /*unused*/) {
                          parent_svc_->Connect(service_name, std::move(channel));
                        }));
}

fidl::InterfaceHandle<fuchsia::io::Directory> EnvironmentServices::ServeServiceDir(uint32_t flags) {
  fidl::InterfaceHandle<fuchsia::io::Directory> dir;
  ZX_ASSERT(ServeServiceDir(dir.NewRequest(), flags) == ZX_OK);
  return dir;
}

zx_status_t EnvironmentServices::ServeServiceDir(
    fidl::InterfaceRequest<fuchsia::io::Directory> request, uint32_t flags) {
  return ServeServiceDir(request.TakeChannel(), flags);
}

zx_status_t EnvironmentServices::ServeServiceDir(zx::channel request, uint32_t flags) {
  return svc_.Serve(flags, std::move(request), dispatcher_);
}

EnclosingEnvironment::EnclosingEnvironment(std::string label,
                                           const fuchsia::sys::EnvironmentPtr& parent_env,
                                           std::unique_ptr<EnvironmentServices> services,
                                           const fuchsia::sys::EnvironmentOptions& options)
    : label_(std::move(label)), services_(std::move(services)) {
  services_->set_enclosing_env(this);

  // Start environment with services.
  fuchsia::sys::ServiceListPtr service_list(new fuchsia::sys::ServiceList);
  service_list->names = std::move(services_->svc_names_);
  service_list->host_directory = services_->ServeServiceDir().TakeChannel();
  fuchsia::sys::EnvironmentPtr env;

  parent_env->CreateNestedEnvironment(env.NewRequest(), env_controller_.NewRequest(), label_,
                                      std::move(service_list), options);
  env_controller_.set_error_handler([this](zx_status_t /*unused*/) { SetRunning(false); });
  // Connect to launcher
  env->GetLauncher(launcher_.NewRequest());

  zx::channel request;
  service_provider_ = sys::ServiceDirectory::CreateWithRequest(&request);
  // Connect to service
  env->GetDirectory(std::move(request));

  env_controller_.events().OnCreated = [this]() { SetRunning(true); };
}

// static
std::unique_ptr<EnclosingEnvironment> EnclosingEnvironment::Create(
    const std::string& label, const fuchsia::sys::EnvironmentPtr& parent_env,
    std::unique_ptr<EnvironmentServices> services,
    const fuchsia::sys::EnvironmentOptions& options) {
  auto* env = new EnclosingEnvironment(label, parent_env, std::move(services), options);
  return std::unique_ptr<EnclosingEnvironment>(env);
}

EnclosingEnvironment::~EnclosingEnvironment() {
  auto channel = env_controller_.Unbind();
  if (channel) {
    fuchsia::sys::EnvironmentControllerSyncPtr controller;
    controller.Bind(std::move(channel));
    controller->Kill();
  }
}

void EnclosingEnvironment::Kill(fit::function<void()> callback) {
  env_controller_->Kill([callback = std::move(callback)]() {
    if (callback) {
      callback();
    }
  });
}

std::unique_ptr<EnclosingEnvironment> EnclosingEnvironment::CreateNestedEnclosingEnvironment(
    const std::string& label) {
  fuchsia::sys::EnvironmentPtr env;
  service_provider_->Connect(env.NewRequest());
  return Create(label, env, EnvironmentServices::Create(env));
}

void EnclosingEnvironment::CreateComponent(
    fuchsia::sys::LaunchInfo launch_info,
    fidl::InterfaceRequest<fuchsia::sys::ComponentController> request) {
  launcher_.CreateComponent(std::move(launch_info), std::move(request));
}

fuchsia::sys::ComponentControllerPtr EnclosingEnvironment::CreateComponent(
    fuchsia::sys::LaunchInfo launch_info) {
  fuchsia::sys::ComponentControllerPtr controller;
  CreateComponent(std::move(launch_info), controller.NewRequest());
  return controller;
}

fuchsia::sys::ComponentControllerPtr EnclosingEnvironment::CreateComponentFromUrl(
    std::string component_url) {
  fuchsia::sys::LaunchInfo launch_info;
  launch_info.url = component_url;

  return CreateComponent(std::move(launch_info));
}

void EnclosingEnvironment::SetRunning(bool running) {
  running_ = running;
  if (running_changed_callback_) {
    running_changed_callback_(running_);
  }
}

}  // namespace sys::testing
