// Copyright 2021 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "dawn/wire/client/Adapter.h"

#include "dawn/common/Log.h"
#include "dawn/wire/client/Client.h"

namespace dawn::wire::client {

Adapter::~Adapter() {
    mRequestDeviceRequests.CloseAll([](RequestDeviceData* request) {
        request->callback(WGPURequestDeviceStatus_Unknown, nullptr,
                          "Adapter destroyed before callback", request->userdata);
    });
}

void Adapter::CancelCallbacksForDisconnect() {
    mRequestDeviceRequests.CloseAll([](RequestDeviceData* request) {
        request->callback(WGPURequestDeviceStatus_Unknown, nullptr, "GPU connection lost",
                          request->userdata);
    });
}

bool Adapter::GetLimits(WGPUSupportedLimits* limits) const {
    return mLimitsAndFeatures.GetLimits(limits);
}

bool Adapter::HasFeature(WGPUFeatureName feature) const {
    return mLimitsAndFeatures.HasFeature(feature);
}

size_t Adapter::EnumerateFeatures(WGPUFeatureName* features) const {
    return mLimitsAndFeatures.EnumerateFeatures(features);
}

void Adapter::SetLimits(const WGPUSupportedLimits* limits) {
    return mLimitsAndFeatures.SetLimits(limits);
}

void Adapter::SetFeatures(const WGPUFeatureName* features, uint32_t featuresCount) {
    return mLimitsAndFeatures.SetFeatures(features, featuresCount);
}

void Adapter::SetProperties(const WGPUAdapterProperties* properties) {
    mProperties = *properties;
    mProperties.nextInChain = nullptr;
}

void Adapter::GetProperties(WGPUAdapterProperties* properties) const {
    *properties = mProperties;
}

void Adapter::RequestDevice(const WGPUDeviceDescriptor* descriptor,
                            WGPURequestDeviceCallback callback,
                            void* userdata) {
    Client* client = GetClient();
    if (client->IsDisconnected()) {
        callback(WGPURequestDeviceStatus_Error, nullptr, "GPU connection lost", userdata);
        return;
    }

    // The descriptor is passed so that the deviceLostCallback can be tracked client-side and called
    // when the device is lost.
    Device* device = client->Make<Device>(descriptor);
    uint64_t serial = mRequestDeviceRequests.Add({callback, device->GetWireId(), userdata});

    // Ensure the device lost callback isn't serialized as part of the command, as it cannot be
    // passed between processes.
    WGPUDeviceDescriptor wireDescriptor = {};
    if (descriptor) {
        wireDescriptor = *descriptor;
        wireDescriptor.deviceLostCallback = nullptr;
        wireDescriptor.deviceLostUserdata = nullptr;
    }

    AdapterRequestDeviceCmd cmd;
    cmd.adapterId = GetWireId();
    cmd.requestSerial = serial;
    cmd.deviceObjectHandle = device->GetWireHandle();
    cmd.descriptor = &wireDescriptor;

    client->SerializeCommand(cmd);
}

bool Client::DoAdapterRequestDeviceCallback(Adapter* adapter,
                                            uint64_t requestSerial,
                                            WGPURequestDeviceStatus status,
                                            const char* message,
                                            const WGPUSupportedLimits* limits,
                                            uint32_t featuresCount,
                                            const WGPUFeatureName* features) {
    // May have been deleted or recreated so this isn't an error.
    if (adapter == nullptr) {
        return true;
    }
    return adapter->OnRequestDeviceCallback(requestSerial, status, message, limits, featuresCount,
                                            features);
}

bool Adapter::OnRequestDeviceCallback(uint64_t requestSerial,
                                      WGPURequestDeviceStatus status,
                                      const char* message,
                                      const WGPUSupportedLimits* limits,
                                      uint32_t featuresCount,
                                      const WGPUFeatureName* features) {
    RequestDeviceData request;
    if (!mRequestDeviceRequests.Acquire(requestSerial, &request)) {
        return false;
    }

    Client* client = GetClient();
    Device* device = client->Get<Device>(request.deviceObjectId);

    // If the return status is a failure we should give a null device to the callback and
    // free the allocation.
    if (status != WGPURequestDeviceStatus_Success) {
        client->Free(device);
        request.callback(status, nullptr, message, request.userdata);
        return true;
    }

    device->SetLimits(limits);
    device->SetFeatures(features, featuresCount);

    request.callback(status, ToAPI(device), message, request.userdata);
    return true;
}

WGPUInstance Adapter::GetInstance() const {
    dawn::ErrorLog() << "adapter.GetInstance not supported with dawn_wire.";
    return nullptr;
}

WGPUDevice Adapter::CreateDevice(const WGPUDeviceDescriptor*) {
    dawn::ErrorLog() << "adapter.CreateDevice not supported with dawn_wire.";
    return nullptr;
}

}  // namespace dawn::wire::client
