// Copyright 2020 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/devices/bin/driver_manager/package_resolver.h"

#include <fidl/fuchsia.io/cpp/wire.h>
#include <fidl/fuchsia.pkg/cpp/wire.h>
#include <lib/fdio/directory.h>
#include <lib/service/llcpp/service.h>

#include <fbl/string_printf.h>

#include "src/devices/lib/log/log.h"
#include "src/lib/storage/vfs/cpp/vfs.h"

namespace fio = fuchsia_io;

namespace internal {

zx::status<std::unique_ptr<Driver>> PackageResolver::FetchDriver(const std::string& package_url) {
  component::FuchsiaPkgUrl parsed_url;
  if (!parsed_url.Parse(std::string(package_url))) {
    LOGF(ERROR, "Failed to parse package url: %s", package_url.data());
    return zx::error(ZX_ERR_INTERNAL);
  }

  auto package_dir_result = Resolve(parsed_url);
  if (!package_dir_result.is_ok()) {
    LOGF(ERROR, "Failed to resolve package url %s, err %d", parsed_url.ToString().c_str(),
         package_dir_result.status_value());
    return package_dir_result.take_error();
  }

  auto driver_vmo_result = LoadDriver(package_dir_result.value(), parsed_url);
  if (driver_vmo_result.status_value()) {
    return driver_vmo_result.take_error();
  }

  Driver* driver = nullptr;
  DriverLoadCallback callback = [&driver](Driver* d, const char* version) mutable { driver = d; };

  zx_status_t status = load_driver_vmo(boot_args_, std::string_view(parsed_url.ToString()),
                                       std::move(driver_vmo_result.value()), std::move(callback));
  if (status != ZX_OK) {
    return zx::error(status);
  }

  fbl::unique_fd package_dir_fd;
  status = fdio_fd_create(package_dir_result.value().TakeClientEnd().TakeChannel().release(),
                          package_dir_fd.reset_and_get_address());
  if (status != ZX_OK) {
    LOGF(ERROR, "Failed to create package_dir_fd: %sd", zx_status_get_string(status));
    return zx::error(status);
  }
  driver->package_dir = std::move(package_dir_fd);
  return zx::ok(std::unique_ptr<Driver>(driver));
}

zx_status_t PackageResolver::ConnectToResolverService() {
  auto client_end = service::Connect<fuchsia_pkg::PackageResolver>();
  if (client_end.is_error()) {
    return client_end.error_value();
  }
  resolver_client_ = fidl::BindSyncClient(std::move(*client_end));
  return ZX_OK;
}

zx::status<fidl::WireSyncClient<fio::Directory>> PackageResolver::Resolve(
    const component::FuchsiaPkgUrl& package_url) {
  if (!resolver_client_.is_valid()) {
    zx_status_t status = ConnectToResolverService();
    if (status != ZX_OK) {
      LOGF(ERROR, "Failed to connect to package resolver service");
      return zx::error(status);
    }
  }
  auto endpoints = fidl::CreateEndpoints<fuchsia_io::Directory>();
  if (endpoints.is_error()) {
    return endpoints.take_error();
  }

  // This is synchronous for now so we can get the proof of concept working.
  // Eventually we will want to do this asynchronously.
  auto result = resolver_client_->Resolve(
      ::fidl::StringView(fidl::StringView::FromExternal(package_url.package_path())),
      std::move(endpoints->server));
  if (!result.ok() || result->is_error()) {
    LOGF(ERROR, "Failed to resolve package");
    if (!result.ok()) {
      return zx::error(ZX_ERR_INTERNAL);
    } else {
      switch (result->error_value()) {
        case fuchsia_pkg::wire::ResolveError::kIo:
          return zx::error(ZX_ERR_IO);
        case fuchsia_pkg::wire::ResolveError::kAccessDenied:
          return zx::error(ZX_ERR_ACCESS_DENIED);
        case fuchsia_pkg::wire::ResolveError::kRepoNotFound:
          return zx::error(ZX_ERR_NOT_FOUND);
        case fuchsia_pkg::wire::ResolveError::kPackageNotFound:
          return zx::error(ZX_ERR_NOT_FOUND);
        case fuchsia_pkg::wire::ResolveError::kUnavailableBlob:
          return zx::error(ZX_ERR_UNAVAILABLE);
        case fuchsia_pkg::wire::ResolveError::kInvalidUrl:
          return zx::error(ZX_ERR_INVALID_ARGS);
        case fuchsia_pkg::wire::ResolveError::kNoSpace:
          return zx::error(ZX_ERR_NO_SPACE);
        default:
          return zx::error(ZX_ERR_INTERNAL);
      }
    }
  }
  return zx::ok(fidl::BindSyncClient(std::move(endpoints->client)));
}

zx::status<zx::vmo> PackageResolver::LoadDriver(
    const fidl::WireSyncClient<fuchsia_io::Directory>& package_dir,
    const component::FuchsiaPkgUrl& package_url) {
  const fio::wire::OpenFlags kFileRights =
      fio::wire::OpenFlags::kRightReadable | fio::wire::OpenFlags::kRightExecutable;
  const fio::wire::VmoFlags kDriverVmoFlags =
      fio::wire::VmoFlags::kRead | fio::wire::VmoFlags::kExecute;

  // Open and duplicate the driver vmo.
  auto endpoints = fidl::CreateEndpoints<fuchsia_io::File>();
  if (endpoints.is_error()) {
    return endpoints.take_error();
  }
  auto file_open_result = package_dir->Open(
      kFileRights, 0u /* mode */,
      ::fidl::StringView(fidl::StringView::FromExternal(package_url.resource_path())),
      fidl::ServerEnd<fuchsia_io::Node>(endpoints->server.TakeChannel()));
  if (!file_open_result.ok()) {
    LOGF(ERROR, "Failed to open driver file: %s", package_url.resource_path().c_str());
    return zx::error(ZX_ERR_INTERNAL);
  }

  auto file_client = fidl::BindSyncClient(std::move(endpoints->client));
  fidl::WireResult file_res = file_client->GetBackingMemory(kDriverVmoFlags);
  if (!file_res.ok()) {
    LOGF(ERROR, "Failed to get driver vmo: %s", file_res.FormatDescription().c_str());
    return zx::error(ZX_ERR_INTERNAL);
  }
  const auto* res = file_res.Unwrap();
  if (res->is_error()) {
    LOGF(ERROR, "Failed to get driver vmo: %s", zx_status_get_string(res->error_value()));
    return zx::error(ZX_ERR_INTERNAL);
  }
  return zx::ok(std::move(res->value()->vmo));
}

}  // namespace internal
