// 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 "src/graphics/bin/opencl_loader/loader.h"

fidl::ProtocolHandler<fuchsia_opencl_loader::Loader> LoaderImpl::GetHandler(
    LoaderApp* app, async_dispatcher_t* dispatcher) {
  return [=](fidl::ServerEnd<fuchsia_opencl_loader::Loader> server_end) {
    std::unique_ptr<LoaderImpl> impl(new LoaderImpl(app));
    auto binding = fidl::BindServer(dispatcher, std::move(server_end), std::move(impl));
  };
}

LoaderImpl::~LoaderImpl() { app_->RemoveObserver(this); }

zx::result<> LoaderImpl::Add(component::OutgoingDirectory& outgoing_dir, LoaderApp* app,
                             async_dispatcher_t* dispatcher) {
  return outgoing_dir.AddUnmanagedProtocol<fuchsia_opencl_loader::Loader>(
      GetHandler(app, dispatcher));
}

// LoaderApp::Observer implementation.
void LoaderImpl::OnIcdListChanged(LoaderApp* app) {
  auto it = callbacks_.begin();
  while (it != callbacks_.end()) {
    std::optional<zx::vmo> vmo = app->GetMatchingIcd(it->first);
    if (!vmo) {
      ++it;
    } else {
      it->second.Reply(*std::move(vmo));
      it = callbacks_.erase(it);
    }
  }
  if (!waiting_for_callbacks()) {
    app_->RemoveObserver(this);
  }
}

// fuchsia::opencl::loader::Loader impl
void LoaderImpl::Get(GetRequest& request, GetCompleter::Sync& completer) {
  AddCallback(std::move(request.name()), completer.ToAsync());
}

void LoaderImpl::ConnectToDeviceFs(ConnectToDeviceFsRequest& request,
                                   ConnectToDeviceFsCompleter::Sync& completer) {
  app_->ServeDeviceFs(fidl::ServerEnd<fuchsia_io::Directory>{std::move(request.channel())});
}

void LoaderImpl::ConnectToManifestFs(ConnectToManifestFsRequest& request,
                                     ConnectToManifestFsCompleter::Sync& completer) {
  auto server_end = fidl::ServerEnd<fuchsia_io::Directory>{std::move(request.channel())};
  if (!(request.options() & fuchsia_opencl_loader::ConnectToManifestOptions::kWaitForIdle) ||
      !app_->HavePendingActions()) {
    app_->ServeManifestFs(std::move(server_end));
    return;
  }

  bool was_waiting_for_callbacks = waiting_for_callbacks();
  connect_manifest_handles_.push_back(std::move(server_end));
  if (waiting_for_callbacks() && !was_waiting_for_callbacks) {
    app_->AddObserver(this);
  }
}

void LoaderImpl::GetSupportedFeatures(GetSupportedFeaturesCompleter::Sync& completer) {
  constexpr fuchsia_opencl_loader::Features kFeatures =
      fuchsia_opencl_loader::Features::kConnectToDeviceFs | fuchsia_opencl_loader::Features::kGet;
  completer.Reply(kFeatures);
}

void LoaderImpl::AddCallback(std::string name, GetCompleter::Async completer) {
  bool was_waiting_for_callbacks = waiting_for_callbacks();
  std::optional<zx::vmo> vmo = app_->GetMatchingIcd(name);
  if (vmo) {
    completer.Reply(*std::move(vmo));
    return;
  }
  callbacks_.emplace_back(std::move(name), std::move(completer));
  if (waiting_for_callbacks() && !was_waiting_for_callbacks) {
    app_->AddObserver(this);
  }
}
