// Copyright 2021 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/component/cpp/fidl.h>
#include <fuchsia/component/decl/cpp/fidl.h>
#include <fuchsia/io/cpp/fidl.h>
#include <lib/async/default.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/io.h>
#include <lib/fit/defer.h>
#include <lib/sys/component/cpp/testing/internal/errors.h>
#include <lib/sys/component/cpp/testing/internal/realm.h>
#include <lib/sys/component/cpp/testing/scoped_child.h>
#include <lib/sys/cpp/component_context.h>
#include <lib/sys/cpp/service_directory.h>
#include <zircon/assert.h>
#include <zircon/status.h>
#include <zircon/types.h>

#include <memory>
#include <optional>
#include <random>

namespace component_testing {

namespace {

std::size_t random_unsigned() {
  std::random_device random_device;
  std::mt19937 generator(random_device());
  std::uniform_int_distribution<std::size_t> distribution;
  return distribution(generator);
}
}  // namespace

ScopedChild ScopedChild::New(fuchsia::component::RealmSyncPtr realm_proxy, std::string collection,
                             std::string url) {
  std::string name = "auto-" + std::to_string(random_unsigned());
  return New(std::move(realm_proxy), std::move(collection), std::move(name), std::move(url));
}

ScopedChild ScopedChild::New(fuchsia::component::RealmSyncPtr realm_proxy, std::string collection,
                             std::string name, std::string url) {
#if __Fuchsia_API_level__ >= 14
  fuchsia::component::ControllerSyncPtr controller_proxy;
  internal::CreateChild(realm_proxy.get(), controller_proxy.NewRequest(), collection, name,
                        std::move(url));
#else
  internal::CreateChild(realm_proxy.get(), collection, name, std::move(url));
#endif
  fuchsia::component::decl::ChildRef child_ref{.name = std::move(name),
                                               .collection = std::move(collection)};
  fuchsia::io::DirectorySyncPtr exposed_dir;
  exposed_dir.Bind(internal::OpenExposedDir(realm_proxy.get(), child_ref));
  return ScopedChild(sys::ServiceDirectory::CreateFromNamespace(), std::move(child_ref),
                     std::move(exposed_dir)
#if __Fuchsia_API_level__ >= 14
                         ,
                     std::move(controller_proxy)
#endif
  );
}

ScopedChild ScopedChild::New(std::string collection, std::string name, std::string url,
                             std::shared_ptr<sys::ServiceDirectory> svc) {
  fuchsia::component::RealmSyncPtr realm_proxy;
  svc->Connect(realm_proxy.NewRequest());
#if __Fuchsia_API_level__ >= 14
  fuchsia::component::ControllerSyncPtr controller_proxy;
  internal::CreateChild(realm_proxy.get(), controller_proxy.NewRequest(), collection, name,
                        std::move(url));
#else
  internal::CreateChild(realm_proxy.get(), collection, name, std::move(url));
#endif
  fuchsia::component::decl::ChildRef child_ref{.name = std::move(name),
                                               .collection = std::move(collection)};
  fuchsia::io::DirectorySyncPtr exposed_dir;
  exposed_dir.Bind(internal::OpenExposedDir(realm_proxy.get(), child_ref));
  return ScopedChild(std::move(svc), std::move(child_ref), std::move(exposed_dir)
#if __Fuchsia_API_level__ >= 14
                                                               ,
                     std::move(controller_proxy)
#endif
  );
}

ScopedChild ScopedChild::New(std::string collection, std::string url,
                             std::shared_ptr<sys::ServiceDirectory> svc) {
  std::string name = "auto-" + std::to_string(random_unsigned());
  return New(std::move(collection), std::move(name), std::move(url), std::move(svc));
}

ScopedChild::ScopedChild(std::shared_ptr<sys::ServiceDirectory> svc,
                         fuchsia::component::decl::ChildRef child_ref,
                         fuchsia::io::DirectorySyncPtr exposed_dir
#if __Fuchsia_API_level__ >= 14
                         ,
                         fuchsia::component::ControllerSyncPtr controller_proxy
#endif
                         )
    : svc_(std::move(svc)),
      child_ref_(std::move(child_ref)),
      exposed_dir_(std::move(exposed_dir))
#if __Fuchsia_API_level__ >= 14
      ,
      controller_proxy_(std::move(controller_proxy))
#endif
{
}

ScopedChild::~ScopedChild() {
  if (svc_ == nullptr) {
    return;
  }

  fuchsia::component::RealmSyncPtr sync_realm_proxy;
  ZX_COMPONENT_ASSERT_STATUS_OK("sys::ServiceDirectory/Connect",
                                svc_->Connect(sync_realm_proxy.NewRequest()));
  internal::DestroyChild(sync_realm_proxy.get(), child_ref_);
}

void ScopedChild::Teardown(async_dispatcher_t* dispatcher, TeardownCallback callback) {
  ZX_ASSERT(callback != nullptr);

  if (svc_ == nullptr) {
    callback(fit::ok());
    return;
  }

  fuchsia::component::RealmPtr async_realm_proxy;
  async_realm_proxy.set_error_handler(
      [](zx_status_t status) { ZX_PANIC("%s", zx_status_get_string(status)); });
  ZX_COMPONENT_ASSERT_STATUS_OK("sys::ServiceDirectory/Connect",
                                svc_->Connect(async_realm_proxy.NewRequest(dispatcher)));

  internal::DestroyChild(
      async_realm_proxy.get(), child_ref_,
      [callback = std::move(callback),
       // Stash a panic-on-drop callback into the closure; this asserts that callers do not shut
       // down the dispatcher before the async call completes.
       forbid_drop = fit::deferred_callback(
           []() { ZX_PANIC("async callback dropped without being called"); }),
       // We have to move the proxy into the callback so that the channel
       // connection doesn't prematurely close.
       _proxy = std::move(async_realm_proxy)](
          fuchsia::component::Realm_DestroyChild_Result result) mutable {
        forbid_drop.cancel();
        switch (result.Which()) {
          case fuchsia::component::Realm_DestroyChild_Result::kResponse:
            callback(fit::ok());
            break;
          case fuchsia::component::Realm_DestroyChild_Result::kErr:
            callback(fit::error(result.err()));
            break;
          case fuchsia::component::Realm_DestroyChild_Result::Invalid:
            ZX_PANIC("Realm/DestroyChild returned invalid response");
        }
      });

  // Prevent the destructor from calling DestroyChild again.
  svc_ = nullptr;
}

zx_status_t ScopedChild::Connect(const std::string& interface_name, zx::channel request) const {
  return fdio_service_connect_at(exposed_dir_.unowned_channel()->get(), interface_name.c_str(),
                                 request.release());
}

std::string ScopedChild::GetChildName() const { return child_ref_.name; }

const fuchsia::io::DirectorySyncPtr& ScopedChild::exposed() const { return exposed_dir_; }

#if __Fuchsia_API_level__ >= 14
ExecutionController ScopedChild::Start(fuchsia::component::StartChildArgs start_args) const {
  fuchsia::component::Controller_Start_Result result;
  fuchsia::component::ExecutionControllerPtr execution_controller_proxy;
  ZX_COMPONENT_ASSERT_STATUS_AND_RESULT_OK(
      "Controller/Start",
      controller_proxy_->Start(std::move(start_args), execution_controller_proxy.NewRequest(),
                               &result),
      result);
  return ExecutionController(std::move(execution_controller_proxy));
}
#endif

}  // namespace component_testing
