// Copyright 2023 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/runner.h"

#include <zircon/processargs.h>

#include "src/devices/lib/log/log.h"

namespace {

namespace fdi = fuchsia_driver_index;
namespace fio = fuchsia_io;
namespace fprocess = fuchsia_process;
namespace frunner = fuchsia_component_runner;
namespace fcomponent = fuchsia_component;
namespace fdecl = fuchsia_component_decl;

constexpr uint32_t kTokenId = PA_HND(PA_USER0, 0);

zx::result<zx_koid_t> GetKoid(zx_handle_t handle) {
  zx_info_handle_basic_t info{};
  if (zx_status_t status =
          zx_object_get_info(handle, ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr);
      status != ZX_OK) {
    return zx::error(status);
  }
  return zx::ok(info.koid);
}

const char* GetErrorString(fcomponent::Error error) {
  switch (error) {
    case fcomponent::Error::kInternal:
      return "INTERNAL";
    case fcomponent::Error::kInvalidArguments:
      return "INVALID_ARGUMENTS";
    case fcomponent::Error::kUnsupported:
      return "UNSUPPORTED";
    case fcomponent::Error::kAccessDenied:
      return "ACCESS_DENIED";
    case fcomponent::Error::kInstanceNotFound:
      return "INSTANCE_NOT_FOUND";
    case fcomponent::Error::kInstanceAlreadyExists:
      return "INSTANCE_ALREADY_EXISTS";
    case fcomponent::Error::kInstanceCannotStart:
      return "INSTANCE_CANNOT_START";
    case fcomponent::Error::kInstanceCannotResolve:
      return "INSTANCE_CANNOT_RESOLVE";
    case fcomponent::Error::kCollectionNotFound:
      return "COLLECTION_NOT_FOUND";
    case fcomponent::Error::kResourceUnavailable:
      return "RESOURCE_UNAVAILABLE";
    case fcomponent::Error::kInstanceDied:
      return "INSTANCE_DIED";
    case fcomponent::Error::kResourceNotFound:
      return "RESOURCE_NOT_FOUND";
    case fcomponent::Error::kInstanceCannotUnresolve:
      return "INSTANCE_CANNOT_UNRESOLVE";
    case fcomponent::Error::kInstanceAlreadyStarted:
      return "INSTANCE_ALREADY_STARTED";
    default:
      return "UNKNOWN";
  }
}

}  // namespace

namespace driver_manager {

zx::result<> Runner::Publish(component::OutgoingDirectory& outgoing) {
  return outgoing.AddUnmanagedProtocol<frunner::ComponentRunner>(
      bindings_.CreateHandler(this, dispatcher_, fidl::kIgnoreBindingClosure));
}

void Runner::StartDriverComponent(std::string_view moniker, std::string_view url,
                                  std::string_view collection_name,
                                  fidl::VectorView<fuchsia_component_decl::wire::Offer> offers,
                                  StartCallback callback) {
  zx::event token;
  zx_status_t status = zx::event::create(0, &token);
  if (status != ZX_OK) {
    return callback(zx::error(status));
  }

  zx::result koid = GetKoid(token.get());
  if (koid.is_error()) {
    return callback(koid.take_error());
  }
  start_requests_.emplace(koid.value(), std::move(callback));

  fidl::Arena arena;
  auto child_decl = fdecl::wire::Child::Builder(arena)
                        .name(fidl::StringView::FromExternal(moniker))
                        .url(fidl::StringView::FromExternal(url))
                        .startup(fdecl::wire::StartupMode::kLazy)
                        .Build();

  fprocess::wire::HandleInfo handle_info = {
      .handle = std::move(token),
      .id = kTokenId,
  };

  auto child_args_builder = fcomponent::wire::CreateChildArgs::Builder(arena).numbered_handles(
      fidl::VectorView<fprocess::wire::HandleInfo>::FromExternal(&handle_info, 1));
  if (!offers.empty()) {
    child_args_builder.dynamic_offers(offers);
  }
  auto create_callback =
      [this, child_moniker = std::string(moniker.data()), koid = koid.value()](
          fidl::WireUnownedResult<fcomponent::Realm::CreateChild>& result) mutable {
        bool is_error = false;
        if (!result.ok()) {
          LOGF(ERROR, "Failed to create child '%s': %s", child_moniker.c_str(),
               result.FormatDescription().c_str());
          is_error = true;
        }
        if (result.value().is_error()) {
          LOGF(ERROR, "Failed to create child '%s': %s", child_moniker.c_str(),
               GetErrorString(result.value().error_value()));
          is_error = true;
        }
        if (is_error) {
          zx::result result = CallCallback(koid, zx::error(ZX_ERR_INTERNAL));
          if (result.is_error()) {
            LOGF(ERROR, "Failed to find driver request for '%s': %s", child_moniker.c_str(),
                 result.status_string());
          }
        }
      };
  realm_
      ->CreateChild(
          fdecl::wire::CollectionRef{
              .name = fidl::StringView::FromExternal(collection_name),
          },
          child_decl, child_args_builder.Build())
      .Then(std::move(create_callback));
}

void Runner::Start(StartRequestView request, StartCompleter::Sync& completer) {
  std::string url = std::string(request->start_info.resolved_url().get());

  // When we start a driver, we associate an unforgeable token (the KOID of a
  // zx::event) with the start request, through the use of the numbered_handles
  // field. We do this so:
  //  1. We can securely validate the origin of the request
  //  2. We avoid collisions that can occur when relying on the package URL
  //  3. We avoid relying on the resolved URL matching the package URL
  if (!request->start_info.has_numbered_handles()) {
    LOGF(ERROR, "Failed to start driver '%s', invalid request for driver", url.c_str());
    completer.Close(ZX_ERR_INVALID_ARGS);
    return;
  }
  auto& handles = request->start_info.numbered_handles();
  if (handles.count() != 1 || !handles[0].handle || handles[0].id != kTokenId) {
    LOGF(ERROR, "Failed to start driver '%s', invalid request for driver", url.c_str());
    completer.Close(ZX_ERR_INVALID_ARGS);
    return;
  }

  zx::result koid = GetKoid(handles[0].handle.get());
  if (koid.is_error()) {
    completer.Close(ZX_ERR_INVALID_ARGS);
    return;
  }

  zx::result result = CallCallback(koid.value(), zx::ok(StartedComponent{
                                                     .info = fidl::ToNatural(request->start_info),
                                                     .controller = std::move(request->controller),
                                                 }));
  if (result.is_error()) {
    LOGF(ERROR, "Failed to start driver '%s', unknown request for driver", url.c_str());
    completer.Close(ZX_ERR_UNAVAILABLE);
  }
}

zx::result<> Runner::CallCallback(zx_koid_t koid, zx::result<StartedComponent> component) {
  auto it = start_requests_.find(koid);
  if (it == start_requests_.end()) {
    return zx::error(ZX_ERR_NOT_FOUND);
  }
  auto callback = std::move(it->second);
  start_requests_.erase(koid);

  callback(std::move(component));
  return zx::ok();
}

}  // namespace driver_manager
