// Copyright 2016 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 "zircon_platform_connection.h"

#include <optional>

#include "magma_common_defs.h"
#include "zircon_platform_status.h"

namespace {
std::optional<magma::PlatformObject::Type> GetObjectType(fuchsia_gpu_magma::ObjectType fidl_type) {
  switch (fidl_type) {
    case fuchsia_gpu_magma::ObjectType::kBuffer:
      return magma::PlatformObject::Type::BUFFER;
    case fuchsia_gpu_magma::ObjectType::kEvent:
      return magma::PlatformObject::Type::SEMAPHORE;
    default:
      return std::nullopt;
  }
}

std::optional<int> GetBufferOp(fuchsia_gpu_magma::BufferOp fidl_type) {
  switch (fidl_type) {
    case fuchsia_gpu_magma::wire::BufferOp::kPopulateTables:
      return MAGMA_BUFFER_RANGE_OP_POPULATE_TABLES;
    case fuchsia_gpu_magma::wire::BufferOp::kDepopulateTables:
      return MAGMA_BUFFER_RANGE_OP_DEPOPULATE_TABLES;
    default:
      return std::nullopt;
  }
}

}  // namespace

namespace magma {

class ZirconPlatformPerfCountPool : public PlatformPerfCountPool {
 public:
  ZirconPlatformPerfCountPool(uint64_t id, zx::channel channel)
      : pool_id_(id), server_end_(std::move(channel)) {}

  uint64_t pool_id() override { return pool_id_; }

  // Sends a OnPerformanceCounterReadCompleted. May be called from any thread.
  magma::Status SendPerformanceCounterCompletion(uint32_t trigger_id, uint64_t buffer_id,
                                                 uint32_t buffer_offset, uint64_t time,
                                                 uint32_t result_flags) override {
    fidl::Arena allocator;
    auto builder = fuchsia_gpu_magma::wire::
        PerformanceCounterEventsOnPerformanceCounterReadCompletedRequest::Builder(allocator);
    builder.trigger_id(trigger_id)
        .buffer_id(buffer_id)
        .buffer_offset(buffer_offset)
        .timestamp(time)
        .flags(fuchsia_gpu_magma::wire::ResultFlags::TruncatingUnknown(result_flags));

    fidl::Status result =
        fidl::WireSendEvent(server_end_)->OnPerformanceCounterReadCompleted(builder.Build());
    switch (result.status()) {
      case ZX_OK:
        return MAGMA_STATUS_OK;
      case ZX_ERR_PEER_CLOSED:
        return MAGMA_STATUS_CONNECTION_LOST;
      case ZX_ERR_TIMED_OUT:
        return MAGMA_STATUS_TIMED_OUT;
      default:
        return MAGMA_STATUS_INTERNAL_ERROR;
    }
  }

 private:
  uint64_t pool_id_;
  fidl::ServerEnd<fuchsia_gpu_magma::PerformanceCounterEvents> server_end_;
};

void ZirconPlatformConnection::SetError(fidl::CompleterBase* completer, magma_status_t error) {
  if (!error_) {
    error_ = DRET_MSG(error, "ZirconPlatformConnection encountered dispatcher error");
    if (completer) {
      completer->Close(magma::ToZxStatus(error));
    } else {
      server_binding_->Close(magma::ToZxStatus(error));
    }
    async_loop()->Quit();
  }
}

bool ZirconPlatformConnection::Bind(zx::channel server_endpoint) {
  fidl::OnUnboundFn<ZirconPlatformConnection> unbind_callback =
      [](ZirconPlatformConnection* self, fidl::UnbindInfo unbind_info,
         fidl::ServerEnd<fuchsia_gpu_magma::Primary> server_channel) {
        // |kDispatcherError| indicates the async loop itself is shutting down,
        // which could only happen when |interface| is being destructed.
        // Therefore, we must avoid using the same object.
        if (unbind_info.reason() == fidl::Reason::kDispatcherError)
          return;

        self->server_binding_ = cpp17::nullopt;
        self->async_loop()->Quit();
      };

  // Note: the async loop should not be started until we assign |server_binding_|.
  server_binding_ =
      fidl::BindServer(async_loop()->dispatcher(),
                       fidl::ServerEnd<fuchsia_gpu_magma::Primary>(std::move(server_endpoint)),
                       this, std::move(unbind_callback));
  return true;
}

bool ZirconPlatformConnection::HandleRequest() {
  zx_status_t status = async_loop_.Run(zx::time::infinite(), true /* once */);
  if (status != ZX_OK)
    return false;
  return true;
}

bool ZirconPlatformConnection::BeginShutdownWait() {
  zx_status_t status = async_begin_wait(async_loop()->dispatcher(), &async_wait_shutdown_);
  if (status != ZX_OK)
    return DRETF(false, "Couldn't begin wait on shutdown: %s", zx_status_get_string(status));
  return true;
}

void ZirconPlatformConnection::AsyncWaitHandler(async_dispatcher_t* dispatcher, AsyncWait* wait,
                                                zx_status_t status,
                                                const zx_packet_signal_t* signal) {
  if (status != ZX_OK)
    return;

  bool quit = false;
  if (wait == &async_wait_shutdown_) {
    DASSERT(signal->observed == ZX_EVENT_SIGNALED);
    quit = true;
    DLOG("got shutdown event");
  } else {
    DASSERT(false);
  }

  if (quit) {
    server_binding_->Close(ZX_ERR_CANCELED);
    async_loop()->Quit();
  }
}

struct AsyncHandleWait : public async_wait {
  AsyncHandleWait(msd_connection_handle_wait_complete_t completer, void* completer_context,
                  zx_handle_t object) {
    this->state = ASYNC_STATE_INIT;
    this->handler = Handler;
    this->object = object;
    this->trigger = ZX_EVENT_SIGNALED;
    this->options = 0;
    this->completer = completer;
    this->completer_context = completer_context;
  }

  static void Handler(async_dispatcher_t* dispatcher, async_wait_t* async_wait, zx_status_t status,
                      const zx_packet_signal_t* signal) {
    auto wait = static_cast<AsyncHandleWait*>(async_wait);

    wait->completer(wait->completer_context, magma::FromZxStatus(status).get(), wait->object);

    delete wait;
  }

  msd_connection_handle_wait_complete_t completer;
  void* completer_context;
};

bool ZirconPlatformConnection::AsyncTaskHandler(async_dispatcher_t* dispatcher, AsyncTask* task,
                                                zx_status_t status) {
  switch (static_cast<MSD_CONNECTION_NOTIFICATION_TYPE>(task->notification.type)) {
    case MSD_CONNECTION_NOTIFICATION_CHANNEL_SEND: {
      zx_status_t status = zx_channel_write(server_notification_endpoint_.get(), 0,
                                            task->notification.u.channel_send.data,
                                            task->notification.u.channel_send.size, nullptr, 0);
      if (status != ZX_OK)
        return DRETF(false, "Failed writing to channel: %s", zx_status_get_string(status));
      return true;
    }

    case MSD_CONNECTION_NOTIFICATION_CONTEXT_KILLED:
      // Setting the error will close the connection.
      SetError(nullptr, MAGMA_STATUS_CONTEXT_KILLED);
      return true;

    case MSD_CONNECTION_NOTIFICATION_PERFORMANCE_COUNTERS_READ_COMPLETED:
      // Should be handled in MagmaSystemConnection.
      break;

    case MSD_CONNECTION_NOTIFICATION_HANDLE_WAIT: {
      DASSERT(task->notification.u.handle_wait.handle != ZX_HANDLE_INVALID);

      auto wait_ptr = std::make_unique<AsyncHandleWait>(
          task->notification.u.handle_wait.completer, task->notification.u.handle_wait.wait_context,
          task->notification.u.handle_wait.handle);

      zx_status_t status = async_begin_wait(async_loop()->dispatcher(), wait_ptr.get());
      if (status != ZX_OK)
        return DRETF(false, "async_begin_wait failed: %s", zx_status_get_string(status));

      task->notification.u.handle_wait.starter(task->notification.u.handle_wait.wait_context,
                                               wait_ptr.release());
      return true;
    }

    case MSD_CONNECTION_NOTIFICATION_HANDLE_WAIT_CANCEL: {
      auto wait_ptr =
          reinterpret_cast<AsyncHandleWait*>(task->notification.u.handle_wait_cancel.cancel_token);
      DASSERT(wait_ptr);

      zx_status_t status = async_cancel_wait(async_loop()->dispatcher(), wait_ptr);
      if (status != ZX_OK)
        return DRETF(false, "async_cancel_wait failed: %s", zx_status_get_string(status));

      // Call back to ensure cleanup
      AsyncHandleWait::Handler(async_loop()->dispatcher(), wait_ptr, ZX_ERR_CANCELED, nullptr);
      return true;
    }
  }
  return DRETF(false, "Unhandled notification type: %lu", task->notification.type);
}

void ZirconPlatformConnection::EnableFlowControl(EnableFlowControlRequestView request,
                                                 EnableFlowControlCompleter::Sync& completer) {
  flow_control_enabled_ = true;
}

void ZirconPlatformConnection::FlowControl(uint64_t size) {
  if (!flow_control_enabled_)
    return;

  messages_consumed_ += 1;
  bytes_imported_ += size;

  if (messages_consumed_ >= kMaxInflightMessages / 2) {
    fidl::Status result =
        fidl::WireSendEvent(server_binding_.value())->OnNotifyMessagesConsumed(messages_consumed_);
    if (result.ok()) {
      messages_consumed_ = 0;
    } else if (!result.is_canceled() && !result.is_peer_closed()) {
      DMESSAGE("SendOnNotifyMessagesConsumedEvent failed: %s", result.FormatDescription().c_str());
    }
  }

  if (bytes_imported_ >= kMaxInflightBytes / 2) {
    fidl::Status result =
        fidl::WireSendEvent(server_binding_.value())->OnNotifyMemoryImported(bytes_imported_);
    if (result.ok()) {
      bytes_imported_ = 0;
    } else if (!result.is_canceled() && !result.is_peer_closed()) {
      DMESSAGE("SendOnNotifyMemoryImportedEvent failed: %s", result.FormatDescription().c_str());
    }
  }
}

void ZirconPlatformConnection::ImportObject(ImportObjectRequestView request,
                                            ImportObjectCompleter::Sync& completer) {
  DLOG("ZirconPlatformConnection: ImportObject");

  auto object_type = GetObjectType(request->object_type);
  if (!object_type) {
    SetError(&completer, MAGMA_STATUS_INVALID_ARGS);
    return;
  }

  uint64_t size = 0;

  if (object_type == magma::PlatformObject::BUFFER) {
    zx::unowned_vmo vmo(request->object.get());
    zx_status_t status = vmo->get_size(&size);
    if (status != ZX_OK) {
      SetError(&completer, MAGMA_STATUS_INVALID_ARGS);
      return;
    }
  }

  uint64_t id;
  if (!magma::PlatformObject::IdFromHandle(request->object.get(), &id)) {
    SetError(&completer, MAGMA_STATUS_INVALID_ARGS);
    return;
  }

  FlowControl(size);

  if (!delegate_->ImportObject(request->object.release(), *object_type, id))
    SetError(&completer, MAGMA_STATUS_INVALID_ARGS);
}

void ZirconPlatformConnection::ImportObject2(ImportObject2RequestView request,
                                             ImportObject2Completer::Sync& completer) {
  DLOG("ZirconPlatformConnection: ImportObject2");

  auto object_type = GetObjectType(request->object_type);
  if (!object_type) {
    SetError(&completer, MAGMA_STATUS_INVALID_ARGS);
    return;
  }

  uint64_t size = 0;

  if (object_type == magma::PlatformObject::BUFFER) {
    zx::unowned_vmo vmo(request->object.get());
    zx_status_t status = vmo->get_size(&size);
    if (status != ZX_OK) {
      SetError(&completer, MAGMA_STATUS_INVALID_ARGS);
      return;
    }
  }
  FlowControl(size);

  if (!delegate_->ImportObject(request->object.release(), *object_type, request->object_id))
    SetError(&completer, MAGMA_STATUS_INVALID_ARGS);
}

void ZirconPlatformConnection::ReleaseObject(ReleaseObjectRequestView request,
                                             ReleaseObjectCompleter::Sync& completer) {
  DLOG("ZirconPlatformConnection: ReleaseObject");
  FlowControl();

  auto object_type = GetObjectType(request->object_type);
  if (!object_type) {
    SetError(&completer, MAGMA_STATUS_INVALID_ARGS);
    return;
  }

  if (!delegate_->ReleaseObject(request->object_id, *object_type))
    SetError(&completer, MAGMA_STATUS_INVALID_ARGS);
}

void ZirconPlatformConnection::CreateContext(CreateContextRequestView request,
                                             CreateContextCompleter::Sync& completer) {
  DLOG("ZirconPlatformConnection: CreateContext");
  FlowControl();

  magma::Status status = delegate_->CreateContext(request->context_id);
  if (!status.ok())
    SetError(&completer, status.get());
}

void ZirconPlatformConnection::DestroyContext(DestroyContextRequestView request,
                                              DestroyContextCompleter::Sync& completer) {
  DLOG("ZirconPlatformConnection: DestroyContext");
  FlowControl();

  magma::Status status = delegate_->DestroyContext(request->context_id);
  if (!status.ok())
    SetError(&completer, status.get());
}

// DEPRECATED - TODO(fxb/86670) remove
void ZirconPlatformConnection::ExecuteCommandBufferWithResources2(
    ExecuteCommandBufferWithResources2RequestView request,
    ExecuteCommandBufferWithResources2Completer::Sync& completer) {
  FlowControl();

  auto command_buffer = std::make_unique<magma_command_buffer>();

  *command_buffer = {
      .resource_count = static_cast<uint32_t>(request->resources.count()),
      .batch_buffer_resource_index = request->command_buffer.resource_index,
      .batch_start_offset = request->command_buffer.start_offset,
      .wait_semaphore_count = static_cast<uint32_t>(request->wait_semaphores.count()),
      .signal_semaphore_count = static_cast<uint32_t>(request->signal_semaphores.count()),
      .flags = static_cast<uint64_t>(request->command_buffer.flags),
  };

  std::vector<magma_exec_resource> resources;
  resources.reserve(request->resources.count());

  for (auto& buffer_range : request->resources) {
    resources.push_back({
        buffer_range.buffer_id,
        buffer_range.offset,
        buffer_range.size,
    });
  }

  // Merge semaphores into one vector
  std::vector<uint64_t> semaphores;
  semaphores.reserve(request->wait_semaphores.count() + request->signal_semaphores.count());

  for (uint64_t semaphore_id : request->wait_semaphores) {
    semaphores.push_back(semaphore_id);
  }
  for (uint64_t semaphore_id : request->signal_semaphores) {
    semaphores.push_back(semaphore_id);
  }

  magma::Status status = delegate_->ExecuteCommandBufferWithResources(
      request->context_id, std::move(command_buffer), std::move(resources), std::move(semaphores));

  if (!status)
    SetError(&completer, status.get());
}

void ZirconPlatformConnection::ExecuteCommand(ExecuteCommandRequestView request,
                                              ExecuteCommandCompleter::Sync& completer) {
  FlowControl();

  // TODO(fxbug.dev/92606) - support > 1 command buffer
  if (request->command_buffers.count() > 1) {
    SetError(&completer, MAGMA_STATUS_UNIMPLEMENTED);
    return;
  }

  auto command_buffer = std::make_unique<magma_command_buffer>();

  *command_buffer = {
      .resource_count = static_cast<uint32_t>(request->resources.count()),
      .batch_buffer_resource_index = request->command_buffers[0].resource_index,
      .batch_start_offset = request->command_buffers[0].start_offset,
      .wait_semaphore_count = static_cast<uint32_t>(request->wait_semaphores.count()),
      .signal_semaphore_count = static_cast<uint32_t>(request->signal_semaphores.count()),
      .flags = static_cast<uint64_t>(request->flags),
  };

  std::vector<magma_exec_resource> resources;
  resources.reserve(request->resources.count());

  for (auto& buffer_range : request->resources) {
    resources.push_back({
        buffer_range.buffer_id,
        buffer_range.offset,
        buffer_range.size,
    });
  }

  // Merge semaphores into one vector
  std::vector<uint64_t> semaphores;
  semaphores.reserve(request->wait_semaphores.count() + request->signal_semaphores.count());

  for (uint64_t semaphore_id : request->wait_semaphores) {
    semaphores.push_back(semaphore_id);
  }
  for (uint64_t semaphore_id : request->signal_semaphores) {
    semaphores.push_back(semaphore_id);
  }

  magma::Status status = delegate_->ExecuteCommandBufferWithResources(
      request->context_id, std::move(command_buffer), std::move(resources), std::move(semaphores));

  if (!status)
    SetError(&completer, status.get());
}

void ZirconPlatformConnection::ExecuteImmediateCommands(
    ExecuteImmediateCommandsRequestView request,
    ExecuteImmediateCommandsCompleter::Sync& completer) {
  DLOG("ZirconPlatformConnection: ExecuteImmediateCommands");
  FlowControl();

  magma::Status status = delegate_->ExecuteImmediateCommands(
      request->context_id, request->command_data.count(), request->command_data.mutable_data(),
      request->semaphores.count(), request->semaphores.mutable_data());
  if (!status)
    SetError(&completer, status.get());
}

void ZirconPlatformConnection::Flush(FlushRequestView request, FlushCompleter::Sync& completer) {
  DLOG("ZirconPlatformConnection: Flush");
  completer.Reply();
}

void ZirconPlatformConnection::MapBufferGpu(MapBufferGpuRequestView request,
                                            MapBufferGpuCompleter::Sync& completer) {
  DLOG("ZirconPlatformConnection: MapBufferGpuFIDL");
  FlowControl();

  magma::Status status =
      delegate_->MapBufferGpu(request->buffer_id, request->gpu_va, request->page_offset,
                              request->page_count, static_cast<uint64_t>(request->flags));
  if (!status.ok())
    SetError(&completer, status.get());
}

void ZirconPlatformConnection::UnmapBufferGpu(UnmapBufferGpuRequestView request,
                                              UnmapBufferGpuCompleter::Sync& completer) {
  DLOG("ZirconPlatformConnection: UnmapBufferGpuFIDL");
  FlowControl();

  magma::Status status = delegate_->UnmapBufferGpu(request->buffer_id, request->gpu_va);
  if (!status.ok())
    SetError(&completer, status.get());
}

void ZirconPlatformConnection::BufferRangeOp(BufferRangeOpRequestView request,
                                             BufferRangeOpCompleter::Sync& completer) {
  DLOG("ZirconPlatformConnection:::BufferOp");
  FlowControl();

  std::optional<int> buffer_op = GetBufferOp(request->op);
  if (!buffer_op) {
    SetError(&completer, MAGMA_STATUS_INVALID_ARGS);
    return;
  }

  magma::Status status =
      delegate_->BufferRangeOp(request->buffer_id, *buffer_op, request->offset, request->length);

  if (!status) {
    SetError(&completer, status.get());
  }
}

void ZirconPlatformConnection::EnablePerformanceCounterAccess(
    EnablePerformanceCounterAccessRequestView request,
    EnablePerformanceCounterAccessCompleter::Sync& completer) {
  DLOG("ZirconPlatformConnection:::EnablePerformanceCounterAccess");
  FlowControl();

  magma::Status status = delegate_->EnablePerformanceCounterAccess(
      magma::PlatformHandle::Create(request->access_token.release()));
  if (!status) {
    SetError(&completer, status.get());
  }
}

void ZirconPlatformConnection::IsPerformanceCounterAccessAllowed(
    IsPerformanceCounterAccessAllowedRequestView request,
    IsPerformanceCounterAccessAllowedCompleter::Sync& completer) {
  DLOG("ZirconPlatformConnection:::IsPerformanceCounterAccessAllowed");
  completer.Reply(delegate_->IsPerformanceCounterAccessAllowed());
}

void ZirconPlatformConnection::EnablePerformanceCounters(
    EnablePerformanceCountersRequestView request,
    EnablePerformanceCountersCompleter::Sync& completer) {
  FlowControl();
  magma::Status status =
      delegate_->EnablePerformanceCounters(request->counters.data(), request->counters.count());
  if (!status) {
    SetError(&completer, status.get());
  }
}

void ZirconPlatformConnection::CreatePerformanceCounterBufferPool(
    CreatePerformanceCounterBufferPoolRequestView request,
    CreatePerformanceCounterBufferPoolCompleter::Sync& completer) {
  FlowControl();
  auto pool = std::make_unique<ZirconPlatformPerfCountPool>(request->pool_id,
                                                            request->event_channel.TakeChannel());
  magma::Status status = delegate_->CreatePerformanceCounterBufferPool(std::move(pool));
  if (!status) {
    SetError(&completer, status.get());
  }
}

void ZirconPlatformConnection::ReleasePerformanceCounterBufferPool(
    ReleasePerformanceCounterBufferPoolRequestView request,
    ReleasePerformanceCounterBufferPoolCompleter::Sync& completer) {
  FlowControl();
  magma::Status status = delegate_->ReleasePerformanceCounterBufferPool(request->pool_id);
  if (!status) {
    SetError(&completer, status.get());
  }
}

void ZirconPlatformConnection::AddPerformanceCounterBufferOffsetsToPool(
    AddPerformanceCounterBufferOffsetsToPoolRequestView request,
    AddPerformanceCounterBufferOffsetsToPoolCompleter::Sync& completer) {
  FlowControl();
  for (auto& offset : request->offsets) {
    magma::Status status = delegate_->AddPerformanceCounterBufferOffsetToPool(
        request->pool_id, offset.buffer_id, offset.offset, offset.size);
    if (!status) {
      SetError(&completer, status.get());
    }
  }
}

void ZirconPlatformConnection::RemovePerformanceCounterBufferFromPool(
    RemovePerformanceCounterBufferFromPoolRequestView request,
    RemovePerformanceCounterBufferFromPoolCompleter::Sync& completer) {
  FlowControl();
  magma::Status status =
      delegate_->RemovePerformanceCounterBufferFromPool(request->pool_id, request->buffer_id);
  if (!status) {
    SetError(&completer, status.get());
  }
}

void ZirconPlatformConnection::DumpPerformanceCounters(
    DumpPerformanceCountersRequestView request, DumpPerformanceCountersCompleter::Sync& completer) {
  FlowControl();
  magma::Status status = delegate_->DumpPerformanceCounters(request->pool_id, request->trigger_id);
  if (!status) {
    SetError(&completer, status.get());
  }
}

void ZirconPlatformConnection::ClearPerformanceCounters(
    ClearPerformanceCountersRequestView request,
    ClearPerformanceCountersCompleter::Sync& completer) {
  FlowControl();
  magma::Status status =
      delegate_->ClearPerformanceCounters(request->counters.data(), request->counters.count());
  if (!status) {
    SetError(&completer, status.get());
  }
}

std::shared_ptr<PlatformConnection> PlatformConnection::Create(
    std::unique_ptr<PlatformConnection::Delegate> delegate, msd_client_id_t client_id,
    std::unique_ptr<magma::PlatformHandle> thread_profile,
    std::unique_ptr<magma::PlatformHandle> server_endpoint,
    std::unique_ptr<magma::PlatformHandle> server_notification_endpoint) {
  if (!delegate)
    return DRETP(nullptr, "attempting to create PlatformConnection with null delegate");

  auto shutdown_event = magma::PlatformEvent::Create();
  if (!shutdown_event)
    return DRETP(nullptr, "Failed to create shutdown event");

  auto connection = std::make_shared<ZirconPlatformConnection>(
      std::move(delegate), client_id, zx::channel(server_notification_endpoint->release()),
      std::shared_ptr<magma::PlatformEvent>(std::move(shutdown_event)), std::move(thread_profile));

  if (!connection->Bind(zx::channel(server_endpoint->release())))
    return DRETP(nullptr, "Bind failed");

  if (!connection->BeginShutdownWait())
    return DRETP(nullptr, "Failed to begin shutdown wait");

  return connection;
}

}  // namespace magma
