// 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/server/Server.h"

#include "dawn_wire/SupportedFeatures.h"

namespace dawn::wire::server {

    bool Server::DoAdapterRequestDevice(ObjectId adapterId,
                                        uint64_t requestSerial,
                                        ObjectHandle deviceHandle,
                                        const WGPUDeviceDescriptor* descriptor) {
        auto* adapter = AdapterObjects().Get(adapterId);
        if (adapter == nullptr) {
            return false;
        }

        auto* resultData = DeviceObjects().Allocate(deviceHandle.id, AllocationState::Reserved);
        if (resultData == nullptr) {
            return false;
        }

        resultData->generation = deviceHandle.generation;

        auto userdata = MakeUserdata<RequestDeviceUserdata>();
        userdata->adapter = ObjectHandle{adapterId, adapter->generation};
        userdata->requestSerial = requestSerial;
        userdata->deviceObjectId = deviceHandle.id;

        mProcs.adapterRequestDevice(adapter->handle, descriptor,
                                    ForwardToServer<&Server::OnRequestDeviceCallback>,
                                    userdata.release());
        return true;
    }

    void Server::OnRequestDeviceCallback(RequestDeviceUserdata* data,
                                         WGPURequestDeviceStatus status,
                                         WGPUDevice device,
                                         const char* message) {
        auto* deviceObject = DeviceObjects().Get(data->deviceObjectId, AllocationState::Reserved);
        // Should be impossible to fail. ObjectIds can't be freed by a destroy command until
        // they move from Reserved to Allocated, or if they are destroyed here.
        ASSERT(deviceObject != nullptr);

        ReturnAdapterRequestDeviceCallbackCmd cmd = {};
        cmd.adapter = data->adapter;
        cmd.requestSerial = data->requestSerial;
        cmd.status = status;
        cmd.message = message;

        if (status != WGPURequestDeviceStatus_Success) {
            // Free the ObjectId which will make it unusable.
            DeviceObjects().Free(data->deviceObjectId);
            ASSERT(device == nullptr);
            SerializeCommand(cmd);
            return;
        }

        std::vector<WGPUFeatureName> features;

        size_t featuresCount = mProcs.deviceEnumerateFeatures(device, nullptr);
        features.resize(featuresCount);
        mProcs.deviceEnumerateFeatures(device, features.data());

        // The client should only be able to request supported features, so all enumerated
        // features that were enabled must also be supported by the wire.
        // Note: We fail the callback here, instead of immediately upon receiving
        // the request to preserve callback ordering.
        for (WGPUFeatureName f : features) {
            if (!IsFeatureSupported(f)) {
                // Release the device.
                mProcs.deviceRelease(device);
                // Free the ObjectId which will make it unusable.
                DeviceObjects().Free(data->deviceObjectId);

                cmd.status = WGPURequestDeviceStatus_Error;
                cmd.message = "Requested feature not supported.";
                SerializeCommand(cmd);
                return;
            }
        }

        cmd.featuresCount = features.size();
        cmd.features = features.data();

        WGPUSupportedLimits limits = {};
        mProcs.deviceGetLimits(device, &limits);
        cmd.limits = &limits;

        // Assign the handle and allocated status if the device is created successfully.
        deviceObject->state = AllocationState::Allocated;
        deviceObject->handle = device;
        SetForwardingDeviceCallbacks(deviceObject);

        SerializeCommand(cmd);
    }

}  // namespace dawn::wire::server
